DrawTargetSkia.cpp 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150
  1. /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. * This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "DrawTargetSkia.h"
  6. #include "SourceSurfaceSkia.h"
  7. #include "ScaledFontBase.h"
  8. #include "ScaledFontCairo.h"
  9. #include "skia/include/core/SkBitmapDevice.h"
  10. #include "FilterNodeSoftware.h"
  11. #include "HelpersSkia.h"
  12. #include "mozilla/ArrayUtils.h"
  13. #include "skia/include/core/SkSurface.h"
  14. #include "skia/include/core/SkTypeface.h"
  15. #include "skia/include/effects/SkGradientShader.h"
  16. #include "skia/include/core/SkColorFilter.h"
  17. #include "skia/include/effects/SkBlurImageFilter.h"
  18. #include "skia/include/effects/SkLayerRasterizer.h"
  19. #include "skia/src/core/SkSpecialImage.h"
  20. #include "Blur.h"
  21. #include "Logging.h"
  22. #include "Tools.h"
  23. #include "DataSurfaceHelpers.h"
  24. #include <algorithm>
  25. #ifdef USE_SKIA_GPU
  26. #include "GLDefs.h"
  27. #include "skia/include/gpu/SkGr.h"
  28. #include "skia/include/gpu/GrContext.h"
  29. #include "skia/include/gpu/GrDrawContext.h"
  30. #include "skia/include/gpu/gl/GrGLInterface.h"
  31. #include "skia/src/image/SkImage_Gpu.h"
  32. #endif
  33. #ifdef MOZ_WIDGET_COCOA
  34. #include "BorrowedContext.h"
  35. #include <ApplicationServices/ApplicationServices.h>
  36. #include "mozilla/Vector.h"
  37. #include "ScaledFontMac.h"
  38. #include "CGTextDrawing.h"
  39. #endif
  40. #ifdef XP_WIN
  41. #include "ScaledFontDWrite.h"
  42. #endif
  43. namespace mozilla {
  44. namespace gfx {
  45. class GradientStopsSkia : public GradientStops
  46. {
  47. public:
  48. MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsSkia)
  49. GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops, ExtendMode aExtendMode)
  50. : mCount(aNumStops)
  51. , mExtendMode(aExtendMode)
  52. {
  53. if (mCount == 0) {
  54. return;
  55. }
  56. // Skia gradients always require a stop at 0.0 and 1.0, insert these if
  57. // we don't have them.
  58. uint32_t shift = 0;
  59. if (aStops[0].offset != 0) {
  60. mCount++;
  61. shift = 1;
  62. }
  63. if (aStops[aNumStops-1].offset != 1) {
  64. mCount++;
  65. }
  66. mColors.resize(mCount);
  67. mPositions.resize(mCount);
  68. if (aStops[0].offset != 0) {
  69. mColors[0] = ColorToSkColor(aStops[0].color, 1.0);
  70. mPositions[0] = 0;
  71. }
  72. for (uint32_t i = 0; i < aNumStops; i++) {
  73. mColors[i + shift] = ColorToSkColor(aStops[i].color, 1.0);
  74. mPositions[i + shift] = SkFloatToScalar(aStops[i].offset);
  75. }
  76. if (aStops[aNumStops-1].offset != 1) {
  77. mColors[mCount-1] = ColorToSkColor(aStops[aNumStops-1].color, 1.0);
  78. mPositions[mCount-1] = SK_Scalar1;
  79. }
  80. }
  81. BackendType GetBackendType() const { return BackendType::SKIA; }
  82. std::vector<SkColor> mColors;
  83. std::vector<SkScalar> mPositions;
  84. int mCount;
  85. ExtendMode mExtendMode;
  86. };
  87. /**
  88. * When constructing a temporary SkImage via GetSkImageForSurface, we may also
  89. * have to construct a temporary DataSourceSurface, which must live as long as
  90. * the SkImage. We attach this temporary surface to the image's pixelref, so
  91. * that it can be released once the pixelref is freed.
  92. */
  93. static void
  94. ReleaseTemporarySurface(const void* aPixels, void* aContext)
  95. {
  96. DataSourceSurface* surf = static_cast<DataSourceSurface*>(aContext);
  97. if (surf) {
  98. surf->Release();
  99. }
  100. }
  101. #ifdef IS_BIG_ENDIAN
  102. static const int kARGBAlphaOffset = 0;
  103. #else
  104. static const int kARGBAlphaOffset = 3;
  105. #endif
  106. static void
  107. WriteRGBXFormat(uint8_t* aData, const IntSize &aSize,
  108. const int32_t aStride, SurfaceFormat aFormat)
  109. {
  110. if (aFormat != SurfaceFormat::B8G8R8X8 || aSize.IsEmpty()) {
  111. return;
  112. }
  113. int height = aSize.height;
  114. int width = aSize.width * 4;
  115. for (int row = 0; row < height; ++row) {
  116. for (int column = 0; column < width; column += 4) {
  117. aData[column + kARGBAlphaOffset] = 0xFF;
  118. }
  119. aData += aStride;
  120. }
  121. return;
  122. }
  123. #ifdef DEBUG
  124. static bool
  125. VerifyRGBXFormat(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat)
  126. {
  127. if (aFormat != SurfaceFormat::B8G8R8X8 || aSize.IsEmpty()) {
  128. return true;
  129. }
  130. // We should've initialized the data to be opaque already
  131. // On debug builds, verify that this is actually true.
  132. int height = aSize.height;
  133. int width = aSize.width * 4;
  134. for (int row = 0; row < height; ++row) {
  135. for (int column = 0; column < width; column += 4) {
  136. if (aData[column + kARGBAlphaOffset] != 0xFF) {
  137. gfxCriticalError() << "RGBX pixel at (" << column << "," << row << ") in "
  138. << width << "x" << height << " surface is not opaque: "
  139. << int(aData[column]) << ","
  140. << int(aData[column+1]) << ","
  141. << int(aData[column+2]) << ","
  142. << int(aData[column+3]);
  143. }
  144. }
  145. aData += aStride;
  146. }
  147. return true;
  148. }
  149. // Since checking every pixel is expensive, this only checks the four corners and center
  150. // of a surface that their alpha value is 0xFF.
  151. static bool
  152. VerifyRGBXCorners(uint8_t* aData, const IntSize &aSize, const int32_t aStride, SurfaceFormat aFormat)
  153. {
  154. if (aFormat != SurfaceFormat::B8G8R8X8 || aSize.IsEmpty()) {
  155. return true;
  156. }
  157. int height = aSize.height;
  158. int width = aSize.width;
  159. const int pixelSize = 4;
  160. const int strideDiff = aStride - (width * pixelSize);
  161. MOZ_ASSERT(width * pixelSize <= aStride);
  162. const int topLeft = 0;
  163. const int topRight = width * pixelSize - pixelSize;
  164. const int bottomRight = aStride * height - strideDiff - pixelSize;
  165. const int bottomLeft = aStride * height - aStride;
  166. // Lastly the center pixel
  167. int middleRowHeight = height / 2;
  168. int middleRowWidth = (width / 2) * pixelSize;
  169. const int middle = aStride * middleRowHeight + middleRowWidth;
  170. const int offsets[] = { topLeft, topRight, bottomRight, bottomLeft, middle };
  171. for (size_t i = 0; i < MOZ_ARRAY_LENGTH(offsets); i++) {
  172. int offset = offsets[i];
  173. if (aData[offset + kARGBAlphaOffset] != 0xFF) {
  174. int row = offset / aStride;
  175. int column = (offset % aStride) / pixelSize;
  176. gfxCriticalError() << "RGBX corner pixel at (" << column << "," << row << ") in "
  177. << width << "x" << height << " surface is not opaque: "
  178. << int(aData[offset]) << ","
  179. << int(aData[offset+1]) << ","
  180. << int(aData[offset+2]) << ","
  181. << int(aData[offset+3]);
  182. }
  183. }
  184. return true;
  185. }
  186. #endif
  187. static sk_sp<SkImage>
  188. GetSkImageForSurface(SourceSurface* aSurface, Maybe<MutexAutoLock>* aLock)
  189. {
  190. if (!aSurface) {
  191. gfxDebug() << "Creating null Skia image from null SourceSurface";
  192. return nullptr;
  193. }
  194. if (aSurface->GetType() == SurfaceType::SKIA) {
  195. return static_cast<SourceSurfaceSkia*>(aSurface)->GetImage(aLock);
  196. }
  197. DataSourceSurface* surf = aSurface->GetDataSurface().take();
  198. if (!surf) {
  199. gfxWarning() << "Failed getting DataSourceSurface for Skia image";
  200. return nullptr;
  201. }
  202. SkPixmap pixmap(MakeSkiaImageInfo(surf->GetSize(), surf->GetFormat()),
  203. surf->GetData(), surf->Stride());
  204. sk_sp<SkImage> image = SkImage::MakeFromRaster(pixmap, ReleaseTemporarySurface, surf);
  205. if (!image) {
  206. ReleaseTemporarySurface(nullptr, surf);
  207. gfxDebug() << "Failed making Skia raster image for temporary surface";
  208. }
  209. // Skia doesn't support RGBX surfaces so ensure that the alpha value is opaque white.
  210. MOZ_ASSERT(VerifyRGBXCorners(surf->GetData(), surf->GetSize(),
  211. surf->Stride(), surf->GetFormat()));
  212. return image;
  213. }
  214. DrawTargetSkia::DrawTargetSkia()
  215. : mSnapshot(nullptr)
  216. #ifdef MOZ_WIDGET_COCOA
  217. , mCG(nullptr)
  218. , mColorSpace(nullptr)
  219. , mCanvasData(nullptr)
  220. , mCGSize(0, 0)
  221. #endif
  222. {
  223. }
  224. DrawTargetSkia::~DrawTargetSkia()
  225. {
  226. #ifdef MOZ_WIDGET_COCOA
  227. if (mCG) {
  228. CGContextRelease(mCG);
  229. mCG = nullptr;
  230. }
  231. if (mColorSpace) {
  232. CGColorSpaceRelease(mColorSpace);
  233. mColorSpace = nullptr;
  234. }
  235. #endif
  236. }
  237. already_AddRefed<SourceSurface>
  238. DrawTargetSkia::Snapshot()
  239. {
  240. RefPtr<SourceSurfaceSkia> snapshot = mSnapshot;
  241. if (mSurface && !snapshot) {
  242. snapshot = new SourceSurfaceSkia();
  243. sk_sp<SkImage> image;
  244. // If the surface is raster, making a snapshot may trigger a pixel copy.
  245. // Instead, try to directly make a raster image referencing the surface pixels.
  246. SkPixmap pixmap;
  247. if (mSurface->peekPixels(&pixmap)) {
  248. image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
  249. } else {
  250. image = mSurface->makeImageSnapshot(SkBudgeted::kNo);
  251. }
  252. if (!snapshot->InitFromImage(image, mFormat, this)) {
  253. return nullptr;
  254. }
  255. mSnapshot = snapshot;
  256. }
  257. return snapshot.forget();
  258. }
  259. bool
  260. DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize,
  261. int32_t* aStride, SurfaceFormat* aFormat,
  262. IntPoint* aOrigin)
  263. {
  264. // Ensure the layer is at the origin if required.
  265. SkIPoint origin = mCanvas->getTopDevice()->getOrigin();
  266. if (!aOrigin && !origin.isZero()) {
  267. return false;
  268. }
  269. /* Test if the canvas' device has accessible pixels first, as actually
  270. * accessing the pixels may trigger side-effects, even if it fails.
  271. */
  272. if (!mCanvas->peekPixels(nullptr)) {
  273. return false;
  274. }
  275. SkImageInfo info;
  276. size_t rowBytes;
  277. void* pixels = mCanvas->accessTopLayerPixels(&info, &rowBytes);
  278. if (!pixels) {
  279. return false;
  280. }
  281. MarkChanged();
  282. *aData = reinterpret_cast<uint8_t*>(pixels);
  283. *aSize = IntSize(info.width(), info.height());
  284. *aStride = int32_t(rowBytes);
  285. *aFormat = SkiaColorTypeToGfxFormat(info.colorType(), info.alphaType());
  286. if (aOrigin) {
  287. *aOrigin = IntPoint(origin.x(), origin.y());
  288. }
  289. return true;
  290. }
  291. void
  292. DrawTargetSkia::ReleaseBits(uint8_t* aData)
  293. {
  294. }
  295. static void
  296. ReleaseImage(const void* aPixels, void* aContext)
  297. {
  298. SkImage* image = static_cast<SkImage*>(aContext);
  299. SkSafeUnref(image);
  300. }
  301. static sk_sp<SkImage>
  302. ExtractSubset(sk_sp<SkImage> aImage, const IntRect& aRect)
  303. {
  304. SkIRect subsetRect = IntRectToSkIRect(aRect);
  305. if (aImage->bounds() == subsetRect) {
  306. return aImage;
  307. }
  308. // makeSubset is slow, so prefer to use SkPixmap::extractSubset where possible.
  309. SkPixmap pixmap, subsetPixmap;
  310. if (aImage->peekPixels(&pixmap) &&
  311. pixmap.extractSubset(&subsetPixmap, subsetRect)) {
  312. // Release the original image reference so only the subset image keeps it alive.
  313. return SkImage::MakeFromRaster(subsetPixmap, ReleaseImage, aImage.release());
  314. }
  315. return aImage->makeSubset(subsetRect);
  316. }
  317. static inline bool
  318. SkImageIsMask(const sk_sp<SkImage>& aImage)
  319. {
  320. SkPixmap pixmap;
  321. if (aImage->peekPixels(&pixmap)) {
  322. return pixmap.colorType() == kAlpha_8_SkColorType;
  323. #ifdef USE_SKIA_GPU
  324. } else if (GrTexture* tex = aImage->getTexture()) {
  325. return GrPixelConfigIsAlphaOnly(tex->config());
  326. #endif
  327. } else {
  328. return false;
  329. }
  330. }
  331. static bool
  332. ExtractAlphaBitmap(sk_sp<SkImage> aImage, SkBitmap* aResultBitmap)
  333. {
  334. SkImageInfo info = SkImageInfo::MakeA8(aImage->width(), aImage->height());
  335. SkBitmap bitmap;
  336. if (!bitmap.tryAllocPixels(info, SkAlign4(info.minRowBytes())) ||
  337. !aImage->readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), 0, 0)) {
  338. gfxWarning() << "Failed reading alpha pixels for Skia bitmap";
  339. return false;
  340. }
  341. *aResultBitmap = bitmap;
  342. return true;
  343. }
  344. static sk_sp<SkImage>
  345. ExtractAlphaForSurface(SourceSurface* aSurface, Maybe<MutexAutoLock>& aLock)
  346. {
  347. sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &aLock);
  348. if (!image) {
  349. return nullptr;
  350. }
  351. if (SkImageIsMask(image)) {
  352. return image;
  353. }
  354. SkBitmap bitmap;
  355. if (!ExtractAlphaBitmap(image, &bitmap)) {
  356. return nullptr;
  357. }
  358. // Mark the bitmap immutable so that it will be shared rather than copied.
  359. bitmap.setImmutable();
  360. return SkImage::MakeFromBitmap(bitmap);
  361. }
  362. static void
  363. SetPaintPattern(SkPaint& aPaint,
  364. const Pattern& aPattern,
  365. Maybe<MutexAutoLock>& aLock,
  366. Float aAlpha = 1.0,
  367. Point aOffset = Point(0, 0))
  368. {
  369. switch (aPattern.GetType()) {
  370. case PatternType::COLOR: {
  371. Color color = static_cast<const ColorPattern&>(aPattern).mColor;
  372. aPaint.setColor(ColorToSkColor(color, aAlpha));
  373. break;
  374. }
  375. case PatternType::LINEAR_GRADIENT: {
  376. const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
  377. GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
  378. if (!stops || stops->mCount < 2 ||
  379. !pat.mBegin.IsFinite() || !pat.mEnd.IsFinite()) {
  380. aPaint.setColor(SK_ColorTRANSPARENT);
  381. } else {
  382. SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode, Axis::BOTH);
  383. SkPoint points[2];
  384. points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
  385. points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
  386. SkMatrix mat;
  387. GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
  388. mat.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
  389. sk_sp<SkShader> shader = SkGradientShader::MakeLinear(points,
  390. &stops->mColors.front(),
  391. &stops->mPositions.front(),
  392. stops->mCount,
  393. mode, 0, &mat);
  394. aPaint.setShader(shader);
  395. }
  396. break;
  397. }
  398. case PatternType::RADIAL_GRADIENT: {
  399. const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
  400. GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
  401. if (!stops || stops->mCount < 2 ||
  402. !pat.mCenter1.IsFinite() || !IsFinite(pat.mRadius1) ||
  403. !pat.mCenter2.IsFinite() || !IsFinite(pat.mRadius2)) {
  404. aPaint.setColor(SK_ColorTRANSPARENT);
  405. } else {
  406. SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode, Axis::BOTH);
  407. SkPoint points[2];
  408. points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
  409. points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
  410. SkMatrix mat;
  411. GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
  412. mat.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
  413. sk_sp<SkShader> shader = SkGradientShader::MakeTwoPointConical(points[0],
  414. SkFloatToScalar(pat.mRadius1),
  415. points[1],
  416. SkFloatToScalar(pat.mRadius2),
  417. &stops->mColors.front(),
  418. &stops->mPositions.front(),
  419. stops->mCount,
  420. mode, 0, &mat);
  421. aPaint.setShader(shader);
  422. }
  423. break;
  424. }
  425. case PatternType::SURFACE: {
  426. const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
  427. sk_sp<SkImage> image = GetSkImageForSurface(pat.mSurface, &aLock);
  428. if (!image) {
  429. aPaint.setColor(SK_ColorTRANSPARENT);
  430. break;
  431. }
  432. SkMatrix mat;
  433. GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
  434. mat.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y));
  435. if (!pat.mSamplingRect.IsEmpty()) {
  436. image = ExtractSubset(image, pat.mSamplingRect);
  437. mat.preTranslate(pat.mSamplingRect.x, pat.mSamplingRect.y);
  438. }
  439. SkShader::TileMode xTileMode = ExtendModeToTileMode(pat.mExtendMode, Axis::X_AXIS);
  440. SkShader::TileMode yTileMode = ExtendModeToTileMode(pat.mExtendMode, Axis::Y_AXIS);
  441. aPaint.setShader(image->makeShader(xTileMode, yTileMode, &mat));
  442. if (pat.mSamplingFilter == SamplingFilter::POINT) {
  443. aPaint.setFilterQuality(kNone_SkFilterQuality);
  444. }
  445. break;
  446. }
  447. }
  448. }
  449. static inline Rect
  450. GetClipBounds(SkCanvas *aCanvas)
  451. {
  452. // Use a manually transformed getClipDeviceBounds instead of
  453. // getClipBounds because getClipBounds inflates the the bounds
  454. // by a pixel in each direction to compensate for antialiasing.
  455. SkIRect deviceBounds;
  456. if (!aCanvas->getClipDeviceBounds(&deviceBounds)) {
  457. return Rect();
  458. }
  459. SkMatrix inverseCTM;
  460. if (!aCanvas->getTotalMatrix().invert(&inverseCTM)) {
  461. return Rect();
  462. }
  463. SkRect localBounds;
  464. inverseCTM.mapRect(&localBounds, SkRect::Make(deviceBounds));
  465. return SkRectToRect(localBounds);
  466. }
  467. struct AutoPaintSetup {
  468. AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern, const Rect* aMaskBounds = nullptr, Point aOffset = Point(0, 0))
  469. : mNeedsRestore(false), mAlpha(1.0)
  470. {
  471. Init(aCanvas, aOptions, aMaskBounds, false);
  472. SetPaintPattern(mPaint, aPattern, mLock, mAlpha, aOffset);
  473. }
  474. AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr, bool aForceGroup = false)
  475. : mNeedsRestore(false), mAlpha(1.0)
  476. {
  477. Init(aCanvas, aOptions, aMaskBounds, aForceGroup);
  478. }
  479. ~AutoPaintSetup()
  480. {
  481. if (mNeedsRestore) {
  482. mCanvas->restore();
  483. }
  484. }
  485. void Init(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds, bool aForceGroup)
  486. {
  487. mPaint.setBlendMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
  488. mCanvas = aCanvas;
  489. //TODO: Can we set greyscale somehow?
  490. if (aOptions.mAntialiasMode != AntialiasMode::NONE) {
  491. mPaint.setAntiAlias(true);
  492. } else {
  493. mPaint.setAntiAlias(false);
  494. }
  495. bool needsGroup = aForceGroup ||
  496. (!IsOperatorBoundByMask(aOptions.mCompositionOp) &&
  497. (!aMaskBounds || !aMaskBounds->Contains(GetClipBounds(aCanvas))));
  498. // TODO: We could skip the temporary for operator_source and just
  499. // clear the clip rect. The other operators would be harder
  500. // but could be worth it to skip pushing a group.
  501. if (needsGroup) {
  502. mPaint.setBlendMode(SkBlendMode::kSrcOver);
  503. SkPaint temp;
  504. temp.setBlendMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
  505. temp.setAlpha(ColorFloatToByte(aOptions.mAlpha));
  506. //TODO: Get a rect here
  507. mCanvas->saveLayer(nullptr, &temp);
  508. mNeedsRestore = true;
  509. } else {
  510. mPaint.setAlpha(ColorFloatToByte(aOptions.mAlpha));
  511. mAlpha = aOptions.mAlpha;
  512. }
  513. mPaint.setFilterQuality(kLow_SkFilterQuality);
  514. }
  515. // TODO: Maybe add an operator overload to access this easier?
  516. SkPaint mPaint;
  517. bool mNeedsRestore;
  518. SkCanvas* mCanvas;
  519. Maybe<MutexAutoLock> mLock;
  520. Float mAlpha;
  521. };
  522. void
  523. DrawTargetSkia::Flush()
  524. {
  525. mCanvas->flush();
  526. }
  527. void
  528. DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
  529. const Rect &aDest,
  530. const Rect &aSource,
  531. const DrawSurfaceOptions &aSurfOptions,
  532. const DrawOptions &aOptions)
  533. {
  534. if (aSource.IsEmpty()) {
  535. return;
  536. }
  537. MarkChanged();
  538. Maybe<MutexAutoLock> lock;
  539. sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
  540. if (!image) {
  541. return;
  542. }
  543. SkRect destRect = RectToSkRect(aDest);
  544. SkRect sourceRect = RectToSkRect(aSource);
  545. bool forceGroup = SkImageIsMask(image) &&
  546. aOptions.mCompositionOp != CompositionOp::OP_OVER;
  547. AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest, forceGroup);
  548. if (aSurfOptions.mSamplingFilter == SamplingFilter::POINT) {
  549. paint.mPaint.setFilterQuality(kNone_SkFilterQuality);
  550. }
  551. mCanvas->drawImageRect(image, sourceRect, destRect, &paint.mPaint);
  552. }
  553. DrawTargetType
  554. DrawTargetSkia::GetType() const
  555. {
  556. #ifdef USE_SKIA_GPU
  557. if (mGrContext) {
  558. return DrawTargetType::HARDWARE_RASTER;
  559. }
  560. #endif
  561. return DrawTargetType::SOFTWARE_RASTER;
  562. }
  563. void
  564. DrawTargetSkia::DrawFilter(FilterNode *aNode,
  565. const Rect &aSourceRect,
  566. const Point &aDestPoint,
  567. const DrawOptions &aOptions)
  568. {
  569. FilterNodeSoftware* filter = static_cast<FilterNodeSoftware*>(aNode);
  570. filter->Draw(this, aSourceRect, aDestPoint, aOptions);
  571. }
  572. void
  573. DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
  574. const Point &aDest,
  575. const Color &aColor,
  576. const Point &aOffset,
  577. Float aSigma,
  578. CompositionOp aOperator)
  579. {
  580. if (aSurface->GetSize().IsEmpty()) {
  581. return;
  582. }
  583. MarkChanged();
  584. Maybe<MutexAutoLock> lock;
  585. sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
  586. if (!image) {
  587. return;
  588. }
  589. mCanvas->save();
  590. mCanvas->resetMatrix();
  591. SkPaint paint;
  592. paint.setBlendMode(GfxOpToSkiaOp(aOperator));
  593. // bug 1201272
  594. // We can't use the SkDropShadowImageFilter here because it applies the xfer
  595. // mode first to render the bitmap to a temporary layer, and then implicitly
  596. // uses src-over to composite the resulting shadow.
  597. // The canvas spec, however, states that the composite op must be used to
  598. // composite the resulting shadow, so we must instead use a SkBlurImageFilter
  599. // to blur the image ourselves.
  600. SkPaint shadowPaint;
  601. shadowPaint.setBlendMode(GfxOpToSkiaOp(aOperator));
  602. auto shadowDest = IntPoint::Round(aDest + aOffset);
  603. SkBitmap blurMask;
  604. if (!UsingSkiaGPU() &&
  605. ExtractAlphaBitmap(image, &blurMask)) {
  606. // Prefer using our own box blur instead of Skia's when we're
  607. // not using the GPU. It currently performs much better than
  608. // SkBlurImageFilter or SkBlurMaskFilter on the CPU.
  609. AlphaBoxBlur blur(Rect(0, 0, blurMask.width(), blurMask.height()),
  610. int32_t(blurMask.rowBytes()),
  611. aSigma, aSigma);
  612. blurMask.lockPixels();
  613. blur.Blur(reinterpret_cast<uint8_t*>(blurMask.getPixels()));
  614. blurMask.unlockPixels();
  615. blurMask.notifyPixelsChanged();
  616. shadowPaint.setColor(ColorToSkColor(aColor, 1.0f));
  617. mCanvas->drawBitmap(blurMask, shadowDest.x, shadowDest.y, &shadowPaint);
  618. } else {
  619. sk_sp<SkImageFilter> blurFilter(SkBlurImageFilter::Make(aSigma, aSigma, nullptr));
  620. sk_sp<SkColorFilter> colorFilter(
  621. SkColorFilter::MakeModeFilter(ColorToSkColor(aColor, 1.0f), SkBlendMode::kSrcIn));
  622. shadowPaint.setImageFilter(blurFilter);
  623. shadowPaint.setColorFilter(colorFilter);
  624. mCanvas->drawImage(image, shadowDest.x, shadowDest.y, &shadowPaint);
  625. }
  626. // Composite the original image after the shadow
  627. auto dest = IntPoint::Round(aDest);
  628. mCanvas->drawImage(image, dest.x, dest.y, &paint);
  629. mCanvas->restore();
  630. }
  631. void
  632. DrawTargetSkia::FillRect(const Rect &aRect,
  633. const Pattern &aPattern,
  634. const DrawOptions &aOptions)
  635. {
  636. // The sprite blitting path in Skia can be faster than the shader blitter for
  637. // operators other than source (or source-over with opaque surface). So, when
  638. // possible/beneficial, route to DrawSurface which will use the sprite blitter.
  639. if (aPattern.GetType() == PatternType::SURFACE &&
  640. aOptions.mCompositionOp != CompositionOp::OP_SOURCE) {
  641. const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
  642. // Verify there is a valid surface and a pattern matrix without skew.
  643. if (pat.mSurface &&
  644. (aOptions.mCompositionOp != CompositionOp::OP_OVER ||
  645. GfxFormatToSkiaAlphaType(pat.mSurface->GetFormat()) != kOpaque_SkAlphaType) &&
  646. !pat.mMatrix.HasNonAxisAlignedTransform()) {
  647. // Bound the sampling to smaller of the bounds or the sampling rect.
  648. IntRect srcRect(IntPoint(0, 0), pat.mSurface->GetSize());
  649. if (!pat.mSamplingRect.IsEmpty()) {
  650. srcRect = srcRect.Intersect(pat.mSamplingRect);
  651. }
  652. // Transform the destination rectangle by the inverse of the pattern
  653. // matrix so that it is in pattern space like the source rectangle.
  654. Rect patRect = aRect - pat.mMatrix.GetTranslation();
  655. patRect.Scale(1.0f / pat.mMatrix._11, 1.0f / pat.mMatrix._22);
  656. // Verify the pattern rectangle will not tile or clamp.
  657. if (!patRect.IsEmpty() && srcRect.Contains(RoundedOut(patRect))) {
  658. // The pattern is a surface with an axis-aligned source rectangle
  659. // fitting entirely in its bounds, so just treat it as a DrawSurface.
  660. DrawSurface(pat.mSurface, aRect, patRect,
  661. DrawSurfaceOptions(pat.mSamplingFilter),
  662. aOptions);
  663. return;
  664. }
  665. }
  666. }
  667. MarkChanged();
  668. SkRect rect = RectToSkRect(aRect);
  669. AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern, &aRect);
  670. mCanvas->drawRect(rect, paint.mPaint);
  671. }
  672. void
  673. DrawTargetSkia::Stroke(const Path *aPath,
  674. const Pattern &aPattern,
  675. const StrokeOptions &aStrokeOptions,
  676. const DrawOptions &aOptions)
  677. {
  678. MarkChanged();
  679. MOZ_ASSERT(aPath, "Null path");
  680. if (aPath->GetBackendType() != BackendType::SKIA) {
  681. return;
  682. }
  683. const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
  684. AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
  685. if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
  686. return;
  687. }
  688. if (!skiaPath->GetPath().isFinite()) {
  689. return;
  690. }
  691. mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
  692. }
  693. void
  694. DrawTargetSkia::StrokeRect(const Rect &aRect,
  695. const Pattern &aPattern,
  696. const StrokeOptions &aStrokeOptions,
  697. const DrawOptions &aOptions)
  698. {
  699. MarkChanged();
  700. AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
  701. if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
  702. return;
  703. }
  704. mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint);
  705. }
  706. void
  707. DrawTargetSkia::StrokeLine(const Point &aStart,
  708. const Point &aEnd,
  709. const Pattern &aPattern,
  710. const StrokeOptions &aStrokeOptions,
  711. const DrawOptions &aOptions)
  712. {
  713. MarkChanged();
  714. AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
  715. if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
  716. return;
  717. }
  718. mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y),
  719. SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y),
  720. paint.mPaint);
  721. }
  722. void
  723. DrawTargetSkia::Fill(const Path *aPath,
  724. const Pattern &aPattern,
  725. const DrawOptions &aOptions)
  726. {
  727. MarkChanged();
  728. if (!aPath || aPath->GetBackendType() != BackendType::SKIA) {
  729. return;
  730. }
  731. const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
  732. AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
  733. if (!skiaPath->GetPath().isFinite()) {
  734. return;
  735. }
  736. mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
  737. }
  738. bool
  739. DrawTargetSkia::ShouldLCDRenderText(FontType aFontType, AntialiasMode aAntialiasMode)
  740. {
  741. // For non-opaque surfaces, only allow subpixel AA if explicitly permitted.
  742. if (!IsOpaque(mFormat) && !mPermitSubpixelAA) {
  743. return false;
  744. }
  745. if (aAntialiasMode == AntialiasMode::DEFAULT) {
  746. switch (aFontType) {
  747. case FontType::MAC:
  748. case FontType::GDI:
  749. case FontType::DWRITE:
  750. case FontType::FONTCONFIG:
  751. return true;
  752. default:
  753. // TODO: Figure out what to do for the other platforms.
  754. return false;
  755. }
  756. }
  757. return (aAntialiasMode == AntialiasMode::SUBPIXEL);
  758. }
  759. #ifdef MOZ_WIDGET_COCOA
  760. class CGClipApply : public SkCanvas::ClipVisitor {
  761. public:
  762. explicit CGClipApply(CGContextRef aCGContext)
  763. : mCG(aCGContext) {}
  764. void clipRect(const SkRect& aRect, SkCanvas::ClipOp op, bool antialias) override {
  765. CGRect rect = CGRectMake(aRect.x(), aRect.y(), aRect.width(), aRect.height());
  766. CGContextClipToRect(mCG, rect);
  767. }
  768. void clipRRect(const SkRRect& rrect, SkCanvas::ClipOp op, bool antialias) override {
  769. SkPath path;
  770. path.addRRect(rrect);
  771. clipPath(path, op, antialias);
  772. }
  773. void clipPath(const SkPath& aPath, SkCanvas::ClipOp, bool antialias) override {
  774. SkPath::Iter iter(aPath, true);
  775. SkPoint source[4];
  776. SkPath::Verb verb;
  777. RefPtr<PathBuilderCG> pathBuilder =
  778. new PathBuilderCG(GetFillRule(aPath.getFillType()));
  779. while ((verb = iter.next(source)) != SkPath::kDone_Verb) {
  780. switch (verb) {
  781. case SkPath::kMove_Verb:
  782. {
  783. SkPoint dest = source[0];
  784. pathBuilder->MoveTo(Point(dest.fX, dest.fY));
  785. break;
  786. }
  787. case SkPath::kLine_Verb:
  788. {
  789. // The first point should be the end point of whatever
  790. // verb we got to get here.
  791. SkPoint second = source[1];
  792. pathBuilder->LineTo(Point(second.fX, second.fY));
  793. break;
  794. }
  795. case SkPath::kQuad_Verb:
  796. {
  797. SkPoint second = source[1];
  798. SkPoint third = source[2];
  799. pathBuilder->QuadraticBezierTo(Point(second.fX, second.fY),
  800. Point(third.fX, third.fY));
  801. break;
  802. }
  803. case SkPath::kCubic_Verb:
  804. {
  805. SkPoint second = source[1];
  806. SkPoint third = source[2];
  807. SkPoint fourth = source[2];
  808. pathBuilder->BezierTo(Point(second.fX, second.fY),
  809. Point(third.fX, third.fY),
  810. Point(fourth.fX, fourth.fY));
  811. break;
  812. }
  813. case SkPath::kClose_Verb:
  814. {
  815. pathBuilder->Close();
  816. break;
  817. }
  818. default:
  819. {
  820. SkDEBUGFAIL("unknown verb");
  821. break;
  822. }
  823. } // end switch
  824. } // end while
  825. RefPtr<Path> path = pathBuilder->Finish();
  826. PathCG* cgPath = static_cast<PathCG*>(path.get());
  827. // Weirdly, CoreGraphics clips empty paths as all shown
  828. // but empty rects as all clipped. We detect this situation and
  829. // workaround it appropriately
  830. if (CGPathIsEmpty(cgPath->GetPath())) {
  831. CGContextClipToRect(mCG, CGRectZero);
  832. return;
  833. }
  834. CGContextBeginPath(mCG);
  835. CGContextAddPath(mCG, cgPath->GetPath());
  836. if (cgPath->GetFillRule() == FillRule::FILL_EVEN_ODD) {
  837. CGContextEOClip(mCG);
  838. } else {
  839. CGContextClip(mCG);
  840. }
  841. }
  842. private:
  843. CGContextRef mCG;
  844. };
  845. static inline CGAffineTransform
  846. GfxMatrixToCGAffineTransform(const Matrix &m)
  847. {
  848. CGAffineTransform t;
  849. t.a = m._11;
  850. t.b = m._12;
  851. t.c = m._21;
  852. t.d = m._22;
  853. t.tx = m._31;
  854. t.ty = m._32;
  855. return t;
  856. }
  857. /***
  858. * We have to do a lot of work to draw glyphs with CG because
  859. * CG assumes that the origin of rects are in the bottom left
  860. * while every other DrawTarget assumes the top left is the origin.
  861. * This means we have to transform the CGContext to have rects
  862. * actually be applied in top left fashion. We do this by:
  863. *
  864. * 1) Translating the context up by the height of the canvas
  865. * 2) Flipping the context by the Y axis so it's upside down.
  866. *
  867. * These two transforms put the origin in the top left.
  868. * Transforms are better understood thinking about them from right to left order (mathematically).
  869. *
  870. * Consider a point we want to draw at (0, 10) in normal cartesian planes with
  871. * a box of (100, 100). in CG terms, this would be at (0, 10).
  872. * Positive Y values point up.
  873. * In our DrawTarget terms, positive Y values point down, so (0, 10) would be
  874. * at (0, 90) in cartesian plane terms. That means our point at (0, 10) in DrawTarget
  875. * terms should end up at (0, 90). How does this work with the current transforms?
  876. *
  877. * Going right to left with the transforms, a CGPoint of (0, 10) has cartesian coordinates
  878. * of (0, 10). The first flip of the Y axis puts the point now at (0, -10);
  879. * Next, we translate the context up by the size of the canvas (Positive Y values go up in CG
  880. * coordinates but down in our draw target coordinates). Since our canvas size is (100, 100),
  881. * the resulting coordinate becomes (0, 90), which is what we expect from our DrawTarget code.
  882. * These two transforms put the CG context equal to what every other DrawTarget expects.
  883. *
  884. * Next, we need two more transforms for actual text. IF we left the transforms as is,
  885. * the text would be drawn upside down, so we need another flip of the Y axis
  886. * to draw the text right side up. However, with only the flip, the text would be drawn
  887. * in the wrong place. Thus we also have to invert the Y position of the glyphs to get them
  888. * in the right place.
  889. *
  890. * Thus we have the following transforms:
  891. * 1) Translation of the context up
  892. * 2) Flipping the context around the Y axis
  893. * 3) Flipping the context around the Y axis
  894. * 4) Inverting the Y position of each glyph
  895. *
  896. * We cannot cancel out (2) and (3) as we have to apply the clips and transforms
  897. * of DrawTargetSkia between (2) and (3).
  898. *
  899. * Consider the example letter P, drawn at (0, 20) in CG coordinates in a (100, 100) rect.
  900. * Again, going right to left of the transforms. We'd get:
  901. *
  902. * 1) The letter P drawn at (0, -20) due to the inversion of the Y axis
  903. * 2) The letter P upside down (b) at (0, 20) due to the second flip
  904. * 3) The letter P right side up at (0, -20) due to the first flip
  905. * 4) The letter P right side up at (0, 80) due to the translation
  906. *
  907. * tl;dr - CGRects assume origin is bottom left, DrawTarget rects assume top left.
  908. */
  909. static bool
  910. SetupCGContext(DrawTargetSkia* aDT,
  911. CGContextRef aCGContext,
  912. sk_sp<SkCanvas> aCanvas)
  913. {
  914. // DrawTarget expects the origin to be at the top left, but CG
  915. // expects it to be at the bottom left. Transform to set the origin to
  916. // the top left. Have to set this before we do anything else.
  917. // This is transform (1) up top
  918. CGContextTranslateCTM(aCGContext, 0, aDT->GetSize().height);
  919. // Transform (2) from the comments.
  920. CGContextScaleCTM(aCGContext, 1, -1);
  921. // Want to apply clips BEFORE the transform since the transform
  922. // will apply to the clips we apply.
  923. // CGClipApply applies clips in device space, so it would be a mistake
  924. // to transform these clips.
  925. CGClipApply clipApply(aCGContext);
  926. aCanvas->replayClips(&clipApply);
  927. CGContextConcatCTM(aCGContext, GfxMatrixToCGAffineTransform(aDT->GetTransform()));
  928. return true;
  929. }
  930. static bool
  931. SetupCGGlyphs(CGContextRef aCGContext,
  932. const GlyphBuffer& aBuffer,
  933. Vector<CGGlyph,32>& aGlyphs,
  934. Vector<CGPoint,32>& aPositions)
  935. {
  936. // Flip again so we draw text in right side up. Transform (3) from the top
  937. CGContextScaleCTM(aCGContext, 1, -1);
  938. if (!aGlyphs.resizeUninitialized(aBuffer.mNumGlyphs) ||
  939. !aPositions.resizeUninitialized(aBuffer.mNumGlyphs)) {
  940. gfxDevCrash(LogReason::GlyphAllocFailedCG) << "glyphs/positions allocation failed";
  941. return false;
  942. }
  943. for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
  944. aGlyphs[i] = aBuffer.mGlyphs[i].mIndex;
  945. // Flip the y coordinates so that text ends up in the right spot after the (3) flip
  946. // Inversion from (4) in the comments.
  947. aPositions[i] = CGPointMake(aBuffer.mGlyphs[i].mPosition.x,
  948. -aBuffer.mGlyphs[i].mPosition.y);
  949. }
  950. return true;
  951. }
  952. // End long comment about transforms. SetupCGContext and SetupCGGlyphs should stay
  953. // next to each other.
  954. // The context returned from this method will have the origin
  955. // in the top left and will hvae applied all the neccessary clips
  956. // and transforms to the CGContext. See the comment above
  957. // SetupCGContext.
  958. CGContextRef
  959. DrawTargetSkia::BorrowCGContext(const DrawOptions &aOptions)
  960. {
  961. int32_t stride;
  962. SurfaceFormat format;
  963. IntSize size;
  964. uint8_t* aSurfaceData = nullptr;
  965. if (!LockBits(&aSurfaceData, &size, &stride, &format)) {
  966. NS_WARNING("Could not lock skia bits to wrap CG around");
  967. return nullptr;
  968. }
  969. if ((aSurfaceData == mCanvasData) && mCG && (mCGSize == size)) {
  970. // If our canvas data still points to the same data,
  971. // we can reuse the CG Context
  972. CGContextSaveGState(mCG);
  973. CGContextSetAlpha(mCG, aOptions.mAlpha);
  974. SetupCGContext(this, mCG, mCanvas);
  975. return mCG;
  976. }
  977. if (!mColorSpace) {
  978. mColorSpace = (format == SurfaceFormat::A8) ?
  979. CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
  980. }
  981. if (mCG) {
  982. // Release the old CG context since it's no longer valid.
  983. CGContextRelease(mCG);
  984. }
  985. mCanvasData = aSurfaceData;
  986. mCGSize = size;
  987. uint32_t bitmapInfo = (format == SurfaceFormat::A8) ?
  988. kCGImageAlphaOnly :
  989. kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
  990. mCG = CGBitmapContextCreateWithData(mCanvasData,
  991. mCGSize.width,
  992. mCGSize.height,
  993. 8, /* bits per component */
  994. stride,
  995. mColorSpace,
  996. bitmapInfo,
  997. NULL, /* Callback when released */
  998. NULL);
  999. if (!mCG) {
  1000. ReleaseBits(mCanvasData);
  1001. NS_WARNING("Could not create bitmap around skia data\n");
  1002. return nullptr;
  1003. }
  1004. CGContextSetAlpha(mCG, aOptions.mAlpha);
  1005. CGContextSetShouldAntialias(mCG, aOptions.mAntialiasMode != AntialiasMode::NONE);
  1006. CGContextSetShouldSmoothFonts(mCG, true);
  1007. CGContextSetTextDrawingMode(mCG, kCGTextFill);
  1008. CGContextSaveGState(mCG);
  1009. SetupCGContext(this, mCG, mCanvas);
  1010. return mCG;
  1011. }
  1012. void
  1013. DrawTargetSkia::ReturnCGContext(CGContextRef aCGContext)
  1014. {
  1015. MOZ_ASSERT(aCGContext == mCG);
  1016. ReleaseBits(mCanvasData);
  1017. CGContextRestoreGState(aCGContext);
  1018. }
  1019. CGContextRef
  1020. BorrowedCGContext::BorrowCGContextFromDrawTarget(DrawTarget *aDT)
  1021. {
  1022. DrawTargetSkia* skiaDT = static_cast<DrawTargetSkia*>(aDT);
  1023. return skiaDT->BorrowCGContext(DrawOptions());
  1024. }
  1025. void
  1026. BorrowedCGContext::ReturnCGContextToDrawTarget(DrawTarget *aDT, CGContextRef cg)
  1027. {
  1028. DrawTargetSkia* skiaDT = static_cast<DrawTargetSkia*>(aDT);
  1029. skiaDT->ReturnCGContext(cg);
  1030. return;
  1031. }
  1032. static void
  1033. SetFontColor(CGContextRef aCGContext, CGColorSpaceRef aColorSpace, const Pattern& aPattern)
  1034. {
  1035. const Color& color = static_cast<const ColorPattern&>(aPattern).mColor;
  1036. CGColorRef textColor = ColorToCGColor(aColorSpace, color);
  1037. CGContextSetFillColorWithColor(aCGContext, textColor);
  1038. CGColorRelease(textColor);
  1039. }
  1040. /***
  1041. * We need this to support subpixel AA text on OS X in two cases:
  1042. * text in DrawTargets that are not opaque and text over vibrant backgrounds.
  1043. * Skia normally doesn't support subpixel AA text on transparent backgrounds.
  1044. * To get around this, we have to wrap the Skia bytes with a CGContext and ask
  1045. * CG to draw the text.
  1046. * In vibrancy cases, we have to use a private API,
  1047. * CGContextSetFontSmoothingBackgroundColor, which sets the expected
  1048. * background color the text will draw onto so that CG can render the text
  1049. * properly. After that, we have to go back and fixup the pixels
  1050. * such that their alpha values are correct.
  1051. */
  1052. bool
  1053. DrawTargetSkia::FillGlyphsWithCG(ScaledFont *aFont,
  1054. const GlyphBuffer &aBuffer,
  1055. const Pattern &aPattern,
  1056. const DrawOptions &aOptions,
  1057. const GlyphRenderingOptions *aRenderingOptions)
  1058. {
  1059. MOZ_ASSERT(aFont->GetType() == FontType::MAC);
  1060. MOZ_ASSERT(aPattern.GetType() == PatternType::COLOR);
  1061. CGContextRef cgContext = BorrowCGContext(aOptions);
  1062. if (!cgContext) {
  1063. return false;
  1064. }
  1065. Vector<CGGlyph,32> glyphs;
  1066. Vector<CGPoint,32> positions;
  1067. if (!SetupCGGlyphs(cgContext, aBuffer, glyphs, positions)) {
  1068. ReturnCGContext(cgContext);
  1069. return false;
  1070. }
  1071. SetFontSmoothingBackgroundColor(cgContext, mColorSpace, aRenderingOptions);
  1072. SetFontColor(cgContext, mColorSpace, aPattern);
  1073. ScaledFontMac* macFont = static_cast<ScaledFontMac*>(aFont);
  1074. if (ScaledFontMac::CTFontDrawGlyphsPtr != nullptr) {
  1075. ScaledFontMac::CTFontDrawGlyphsPtr(macFont->mCTFont, glyphs.begin(),
  1076. positions.begin(),
  1077. aBuffer.mNumGlyphs, cgContext);
  1078. } else {
  1079. CGContextSetFont(cgContext, macFont->mFont);
  1080. CGContextSetFontSize(cgContext, macFont->mSize);
  1081. CGContextShowGlyphsAtPositions(cgContext, glyphs.begin(), positions.begin(),
  1082. aBuffer.mNumGlyphs);
  1083. }
  1084. // Calculate the area of the text we just drew
  1085. CGRect *bboxes = new CGRect[aBuffer.mNumGlyphs];
  1086. CTFontGetBoundingRectsForGlyphs(macFont->mCTFont, kCTFontDefaultOrientation,
  1087. glyphs.begin(), bboxes, aBuffer.mNumGlyphs);
  1088. CGRect extents = ComputeGlyphsExtents(bboxes, positions.begin(), aBuffer.mNumGlyphs, 1.0f);
  1089. delete[] bboxes;
  1090. CGAffineTransform cgTransform = CGContextGetCTM(cgContext);
  1091. extents = CGRectApplyAffineTransform(extents, cgTransform);
  1092. // Have to round it out to ensure we fully cover all pixels
  1093. Rect rect(extents.origin.x, extents.origin.y, extents.size.width, extents.size.height);
  1094. rect.RoundOut();
  1095. extents = CGRectMake(rect.x, rect.y, rect.width, rect.height);
  1096. EnsureValidPremultipliedData(cgContext, extents);
  1097. ReturnCGContext(cgContext);
  1098. return true;
  1099. }
  1100. static bool
  1101. HasFontSmoothingBackgroundColor(const GlyphRenderingOptions* aRenderingOptions)
  1102. {
  1103. // This should generally only be true if we have a popup context menu
  1104. if (aRenderingOptions && aRenderingOptions->GetType() == FontType::MAC) {
  1105. Color fontSmoothingBackgroundColor =
  1106. static_cast<const GlyphRenderingOptionsCG*>(aRenderingOptions)->FontSmoothingBackgroundColor();
  1107. return fontSmoothingBackgroundColor.a > 0;
  1108. }
  1109. return false;
  1110. }
  1111. static bool
  1112. ShouldUseCGToFillGlyphs(const GlyphRenderingOptions* aOptions, const Pattern& aPattern)
  1113. {
  1114. return HasFontSmoothingBackgroundColor(aOptions) &&
  1115. aPattern.GetType() == PatternType::COLOR;
  1116. }
  1117. #endif
  1118. static bool
  1119. CanDrawFont(ScaledFont* aFont)
  1120. {
  1121. switch (aFont->GetType()) {
  1122. case FontType::SKIA:
  1123. case FontType::CAIRO:
  1124. case FontType::FONTCONFIG:
  1125. case FontType::MAC:
  1126. case FontType::GDI:
  1127. case FontType::DWRITE:
  1128. return true;
  1129. default:
  1130. return false;
  1131. }
  1132. }
  1133. void
  1134. DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
  1135. const GlyphBuffer &aBuffer,
  1136. const Pattern &aPattern,
  1137. const DrawOptions &aOptions,
  1138. const GlyphRenderingOptions *aRenderingOptions)
  1139. {
  1140. if (!CanDrawFont(aFont)) {
  1141. return;
  1142. }
  1143. MarkChanged();
  1144. #ifdef MOZ_WIDGET_COCOA
  1145. if (ShouldUseCGToFillGlyphs(aRenderingOptions, aPattern)) {
  1146. if (FillGlyphsWithCG(aFont, aBuffer, aPattern, aOptions, aRenderingOptions)) {
  1147. return;
  1148. }
  1149. }
  1150. #endif
  1151. ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont);
  1152. SkTypeface* typeface = skiaFont->GetSkTypeface();
  1153. if (!typeface) {
  1154. return;
  1155. }
  1156. AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
  1157. AntialiasMode aaMode = aFont->GetDefaultAAMode();
  1158. if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
  1159. aaMode = aOptions.mAntialiasMode;
  1160. }
  1161. bool aaEnabled = aaMode != AntialiasMode::NONE;
  1162. paint.mPaint.setAntiAlias(aaEnabled);
  1163. paint.mPaint.setTypeface(sk_ref_sp(typeface));
  1164. paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize));
  1165. paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
  1166. bool shouldLCDRenderText = ShouldLCDRenderText(aFont->GetType(), aaMode);
  1167. paint.mPaint.setLCDRenderText(shouldLCDRenderText);
  1168. bool useSubpixelText = true;
  1169. switch (aFont->GetType()) {
  1170. case FontType::SKIA:
  1171. case FontType::CAIRO:
  1172. case FontType::FONTCONFIG:
  1173. // SkFontHost_cairo does not support subpixel text positioning,
  1174. // so only enable it for other font hosts.
  1175. useSubpixelText = false;
  1176. break;
  1177. case FontType::MAC:
  1178. if (aaMode == AntialiasMode::GRAY) {
  1179. // Normally, Skia enables LCD FontSmoothing which creates thicker fonts
  1180. // and also enables subpixel AA. CoreGraphics without font smoothing
  1181. // explicitly creates thinner fonts and grayscale AA.
  1182. // CoreGraphics doesn't support a configuration that produces thicker
  1183. // fonts with grayscale AA as LCD Font Smoothing enables or disables both.
  1184. // However, Skia supports it by enabling font smoothing (producing subpixel AA)
  1185. // and converts it to grayscale AA. Since Skia doesn't support subpixel AA on
  1186. // transparent backgrounds, we still want font smoothing for the thicker fonts,
  1187. // even if it is grayscale AA.
  1188. //
  1189. // With explicit Grayscale AA (from -moz-osx-font-smoothing:grayscale),
  1190. // we want to have grayscale AA with no smoothing at all. This means
  1191. // disabling the LCD font smoothing behaviour.
  1192. // To accomplish this we have to explicitly disable hinting,
  1193. // and disable LCDRenderText.
  1194. paint.mPaint.setHinting(SkPaint::kNo_Hinting);
  1195. }
  1196. break;
  1197. case FontType::GDI:
  1198. {
  1199. if (!shouldLCDRenderText && aaEnabled) {
  1200. // If we have non LCD GDI text, render the fonts as cleartype and convert them
  1201. // to grayscale. This seems to be what Chrome and IE are doing on Windows 7.
  1202. // This also applies if cleartype is disabled system wide.
  1203. paint.mPaint.setFlags(paint.mPaint.getFlags() | SkPaint::kGenA8FromLCD_Flag);
  1204. }
  1205. break;
  1206. }
  1207. #ifdef XP_WIN
  1208. case FontType::DWRITE:
  1209. {
  1210. ScaledFontDWrite* dwriteFont = static_cast<ScaledFontDWrite*>(aFont);
  1211. paint.mPaint.setEmbeddedBitmapText(dwriteFont->UseEmbeddedBitmaps());
  1212. if (dwriteFont->ForceGDIMode()) {
  1213. paint.mPaint.setEmbeddedBitmapText(true);
  1214. useSubpixelText = false;
  1215. }
  1216. break;
  1217. }
  1218. #endif
  1219. default:
  1220. break;
  1221. }
  1222. paint.mPaint.setSubpixelText(useSubpixelText);
  1223. std::vector<uint16_t> indices;
  1224. std::vector<SkPoint> offsets;
  1225. indices.resize(aBuffer.mNumGlyphs);
  1226. offsets.resize(aBuffer.mNumGlyphs);
  1227. for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) {
  1228. indices[i] = aBuffer.mGlyphs[i].mIndex;
  1229. offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x);
  1230. offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y);
  1231. }
  1232. mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint);
  1233. }
  1234. void
  1235. DrawTargetSkia::Mask(const Pattern &aSource,
  1236. const Pattern &aMask,
  1237. const DrawOptions &aOptions)
  1238. {
  1239. MarkChanged();
  1240. AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
  1241. Maybe<MutexAutoLock> lock;
  1242. SkPaint maskPaint;
  1243. SetPaintPattern(maskPaint, aMask, lock);
  1244. SkLayerRasterizer::Builder builder;
  1245. builder.addLayer(maskPaint);
  1246. sk_sp<SkLayerRasterizer> raster(builder.detach());
  1247. paint.mPaint.setRasterizer(raster);
  1248. mCanvas->drawPaint(paint.mPaint);
  1249. }
  1250. void
  1251. DrawTargetSkia::MaskSurface(const Pattern &aSource,
  1252. SourceSurface *aMask,
  1253. Point aOffset,
  1254. const DrawOptions &aOptions)
  1255. {
  1256. MarkChanged();
  1257. AutoPaintSetup paint(mCanvas.get(), aOptions, aSource, nullptr, -aOffset);
  1258. Maybe<MutexAutoLock> lock;
  1259. sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(aMask, lock);
  1260. if (!alphaMask) {
  1261. gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
  1262. return;
  1263. }
  1264. mCanvas->drawImage(alphaMask, aOffset.x, aOffset.y, &paint.mPaint);
  1265. }
  1266. bool
  1267. DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
  1268. {
  1269. // Composite the 3D transform with the DT's transform.
  1270. Matrix4x4 fullMat = aMatrix * Matrix4x4::From2D(mTransform);
  1271. if (fullMat.IsSingular()) {
  1272. return false;
  1273. }
  1274. // Transform the surface bounds and clip to this DT.
  1275. IntRect xformBounds =
  1276. RoundedOut(
  1277. fullMat.TransformAndClipBounds(Rect(Point(0, 0), Size(aSurface->GetSize())),
  1278. Rect(Point(0, 0), Size(GetSize()))));
  1279. if (xformBounds.IsEmpty()) {
  1280. return true;
  1281. }
  1282. // Offset the matrix by the transformed origin.
  1283. fullMat.PostTranslate(-xformBounds.x, -xformBounds.y, 0);
  1284. // Read in the source data.
  1285. Maybe<MutexAutoLock> lock;
  1286. sk_sp<SkImage> srcImage = GetSkImageForSurface(aSurface, &lock);
  1287. if (!srcImage) {
  1288. return true;
  1289. }
  1290. // Set up an intermediate destination surface only the size of the transformed bounds.
  1291. // Try to pass through the source's format unmodified in both the BGRA and ARGB cases.
  1292. RefPtr<DataSourceSurface> dstSurf =
  1293. Factory::CreateDataSourceSurface(xformBounds.Size(),
  1294. !srcImage->isOpaque() ?
  1295. aSurface->GetFormat() : SurfaceFormat::A8R8G8B8_UINT32,
  1296. true);
  1297. if (!dstSurf) {
  1298. return false;
  1299. }
  1300. sk_sp<SkCanvas> dstCanvas(
  1301. SkCanvas::NewRasterDirect(
  1302. SkImageInfo::Make(xformBounds.width, xformBounds.height,
  1303. GfxFormatToSkiaColorType(dstSurf->GetFormat()),
  1304. kPremul_SkAlphaType),
  1305. dstSurf->GetData(), dstSurf->Stride()));
  1306. if (!dstCanvas) {
  1307. return false;
  1308. }
  1309. // Do the transform.
  1310. SkPaint paint;
  1311. paint.setAntiAlias(true);
  1312. paint.setFilterQuality(kLow_SkFilterQuality);
  1313. paint.setBlendMode(SkBlendMode::kSrc);
  1314. SkMatrix xform;
  1315. GfxMatrixToSkiaMatrix(fullMat, xform);
  1316. dstCanvas->setMatrix(xform);
  1317. dstCanvas->drawImage(srcImage, 0, 0, &paint);
  1318. dstCanvas->flush();
  1319. // Temporarily reset the DT's transform, since it has already been composed above.
  1320. Matrix origTransform = mTransform;
  1321. SetTransform(Matrix());
  1322. // Draw the transformed surface within the transformed bounds.
  1323. DrawSurface(dstSurf, Rect(xformBounds), Rect(Point(0, 0), Size(xformBounds.Size())));
  1324. SetTransform(origTransform);
  1325. return true;
  1326. }
  1327. bool
  1328. DrawTargetSkia::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
  1329. {
  1330. if (aMatrix.IsSingular()) {
  1331. return false;
  1332. }
  1333. MarkChanged();
  1334. Maybe<MutexAutoLock> lock;
  1335. sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
  1336. if (!image) {
  1337. return true;
  1338. }
  1339. mCanvas->save();
  1340. SkPaint paint;
  1341. paint.setAntiAlias(true);
  1342. paint.setFilterQuality(kLow_SkFilterQuality);
  1343. SkMatrix xform;
  1344. GfxMatrixToSkiaMatrix(aMatrix, xform);
  1345. mCanvas->concat(xform);
  1346. mCanvas->drawImage(image, 0, 0, &paint);
  1347. mCanvas->restore();
  1348. return true;
  1349. }
  1350. already_AddRefed<SourceSurface>
  1351. DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
  1352. const IntSize &aSize,
  1353. int32_t aStride,
  1354. SurfaceFormat aFormat) const
  1355. {
  1356. RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
  1357. if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
  1358. gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize;
  1359. return nullptr;
  1360. }
  1361. return newSurf.forget();
  1362. }
  1363. already_AddRefed<DrawTarget>
  1364. DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
  1365. {
  1366. RefPtr<DrawTargetSkia> target = new DrawTargetSkia();
  1367. #ifdef USE_SKIA_GPU
  1368. if (UsingSkiaGPU()) {
  1369. // Try to create a GPU draw target first if we're currently using the GPU.
  1370. // Mark the DT as cached so that shadow DTs, extracted subrects, and similar can be reused.
  1371. if (target->InitWithGrContext(mGrContext.get(), aSize, aFormat, true)) {
  1372. return target.forget();
  1373. }
  1374. // Otherwise, just fall back to a software draw target.
  1375. }
  1376. #endif
  1377. #ifdef DEBUG
  1378. if (!IsBackedByPixels(mCanvas.get())) {
  1379. // If our canvas is backed by vector storage such as PDF then we want to
  1380. // create a new DrawTarget with similar storage to avoid losing fidelity
  1381. // (fidelity will be lost if the returned DT is Snapshot()'ed and drawn
  1382. // back onto us since a raster will be drawn instead of vector commands).
  1383. NS_WARNING("Not backed by pixels - we need to handle PDF backed SkCanvas");
  1384. }
  1385. #endif
  1386. if (!target->Init(aSize, aFormat)) {
  1387. return nullptr;
  1388. }
  1389. return target.forget();
  1390. }
  1391. bool
  1392. DrawTargetSkia::UsingSkiaGPU() const
  1393. {
  1394. #ifdef USE_SKIA_GPU
  1395. return !!mGrContext;
  1396. #else
  1397. return false;
  1398. #endif
  1399. }
  1400. #ifdef USE_SKIA_GPU
  1401. already_AddRefed<SourceSurface>
  1402. DrawTargetSkia::OptimizeGPUSourceSurface(SourceSurface *aSurface) const
  1403. {
  1404. // Check if the underlying SkImage already has an associated GrTexture.
  1405. Maybe<MutexAutoLock> lock;
  1406. sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
  1407. if (!image || image->isTextureBacked()) {
  1408. RefPtr<SourceSurface> surface(aSurface);
  1409. return surface.forget();
  1410. }
  1411. // Upload the SkImage to a GrTexture otherwise.
  1412. sk_sp<SkImage> texture = image->makeTextureImage(mGrContext.get());
  1413. if (texture) {
  1414. // Create a new SourceSurfaceSkia whose SkImage contains the GrTexture.
  1415. RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
  1416. if (surface->InitFromImage(texture, aSurface->GetFormat())) {
  1417. return surface.forget();
  1418. }
  1419. }
  1420. // The data was too big to fit in a GrTexture.
  1421. if (aSurface->GetType() == SurfaceType::SKIA) {
  1422. // It is already a Skia source surface, so just reuse it as-is.
  1423. RefPtr<SourceSurface> surface(aSurface);
  1424. return surface.forget();
  1425. }
  1426. // Wrap it in a Skia source surface so that can do tiled uploads on-demand.
  1427. RefPtr<SourceSurfaceSkia> surface = new SourceSurfaceSkia();
  1428. surface->InitFromImage(image);
  1429. return surface.forget();
  1430. }
  1431. #endif
  1432. already_AddRefed<SourceSurface>
  1433. DrawTargetSkia::OptimizeSourceSurfaceForUnknownAlpha(SourceSurface *aSurface) const
  1434. {
  1435. #ifdef USE_SKIA_GPU
  1436. if (UsingSkiaGPU()) {
  1437. return OptimizeGPUSourceSurface(aSurface);
  1438. }
  1439. #endif
  1440. if (aSurface->GetType() == SurfaceType::SKIA) {
  1441. RefPtr<SourceSurface> surface(aSurface);
  1442. return surface.forget();
  1443. }
  1444. RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
  1445. // For plugins, GDI can sometimes just write 0 to the alpha channel
  1446. // even for RGBX formats. In this case, we have to manually write
  1447. // the alpha channel to make Skia happy with RGBX and in case GDI
  1448. // writes some bad data. Luckily, this only happens on plugins.
  1449. WriteRGBXFormat(dataSurface->GetData(), dataSurface->GetSize(),
  1450. dataSurface->Stride(), dataSurface->GetFormat());
  1451. return dataSurface.forget();
  1452. }
  1453. already_AddRefed<SourceSurface>
  1454. DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const
  1455. {
  1456. #ifdef USE_SKIA_GPU
  1457. if (UsingSkiaGPU()) {
  1458. return OptimizeGPUSourceSurface(aSurface);
  1459. }
  1460. #endif
  1461. if (aSurface->GetType() == SurfaceType::SKIA) {
  1462. RefPtr<SourceSurface> surface(aSurface);
  1463. return surface.forget();
  1464. }
  1465. // If we're not using skia-gl then drawing doesn't require any
  1466. // uploading, so any data surface is fine. Call GetDataSurface
  1467. // to trigger any required readback so that it only happens
  1468. // once.
  1469. RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
  1470. MOZ_ASSERT(VerifyRGBXFormat(dataSurface->GetData(), dataSurface->GetSize(),
  1471. dataSurface->Stride(), dataSurface->GetFormat()));
  1472. return dataSurface.forget();
  1473. }
  1474. already_AddRefed<SourceSurface>
  1475. DrawTargetSkia::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
  1476. {
  1477. #ifdef USE_SKIA_GPU
  1478. if (aSurface.mType == NativeSurfaceType::OPENGL_TEXTURE && UsingSkiaGPU()) {
  1479. // Wrap the OpenGL texture id in a Skia texture handle.
  1480. GrBackendTextureDesc texDesc;
  1481. texDesc.fWidth = aSurface.mSize.width;
  1482. texDesc.fHeight = aSurface.mSize.height;
  1483. texDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
  1484. texDesc.fConfig = GfxFormatToGrConfig(aSurface.mFormat);
  1485. GrGLTextureInfo texInfo;
  1486. texInfo.fTarget = LOCAL_GL_TEXTURE_2D;
  1487. texInfo.fID = (GrGLuint)(uintptr_t)aSurface.mSurface;
  1488. texDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texInfo);
  1489. sk_sp<SkImage> texture =
  1490. SkImage::MakeFromAdoptedTexture(mGrContext.get(), texDesc,
  1491. GfxFormatToSkiaAlphaType(aSurface.mFormat));
  1492. RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
  1493. if (texture && newSurf->InitFromImage(texture, aSurface.mFormat)) {
  1494. return newSurf.forget();
  1495. }
  1496. return nullptr;
  1497. }
  1498. #endif
  1499. return nullptr;
  1500. }
  1501. void
  1502. DrawTargetSkia::CopySurface(SourceSurface *aSurface,
  1503. const IntRect& aSourceRect,
  1504. const IntPoint &aDestination)
  1505. {
  1506. MarkChanged();
  1507. Maybe<MutexAutoLock> lock;
  1508. sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
  1509. if (!image) {
  1510. return;
  1511. }
  1512. mCanvas->save();
  1513. mCanvas->setMatrix(SkMatrix::MakeTrans(SkIntToScalar(aDestination.x), SkIntToScalar(aDestination.y)));
  1514. mCanvas->clipRect(SkRect::MakeIWH(aSourceRect.width, aSourceRect.height), kReplace_SkClipOp);
  1515. SkPaint paint;
  1516. if (!image->isOpaque()) {
  1517. // Keep the xfermode as SOURCE_OVER for opaque bitmaps
  1518. // http://code.google.com/p/skia/issues/detail?id=628
  1519. paint.setBlendMode(SkBlendMode::kSrc);
  1520. }
  1521. // drawImage with A8 images ends up doing a mask operation
  1522. // so we need to clear before
  1523. if (SkImageIsMask(image)) {
  1524. mCanvas->clear(SK_ColorTRANSPARENT);
  1525. }
  1526. mCanvas->drawImage(image, -SkIntToScalar(aSourceRect.x), -SkIntToScalar(aSourceRect.y), &paint);
  1527. mCanvas->restore();
  1528. }
  1529. bool
  1530. DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
  1531. {
  1532. if (size_t(std::max(aSize.width, aSize.height)) > GetMaxSurfaceSize()) {
  1533. return false;
  1534. }
  1535. // we need to have surfaces that have a stride aligned to 4 for interop with cairo
  1536. SkImageInfo info = MakeSkiaImageInfo(aSize, aFormat);
  1537. size_t stride = SkAlign4(info.minRowBytes());
  1538. mSurface = SkSurface::MakeRaster(info, stride, nullptr);
  1539. if (!mSurface) {
  1540. return false;
  1541. }
  1542. mSize = aSize;
  1543. mFormat = aFormat;
  1544. mCanvas = sk_ref_sp(mSurface->getCanvas());
  1545. if (info.isOpaque()) {
  1546. mCanvas->clear(SK_ColorBLACK);
  1547. }
  1548. return true;
  1549. }
  1550. bool
  1551. DrawTargetSkia::Init(SkCanvas* aCanvas)
  1552. {
  1553. mCanvas = sk_ref_sp(aCanvas);
  1554. SkImageInfo imageInfo = mCanvas->imageInfo();
  1555. // If the canvas is backed by pixels we clear it to be on the safe side. If
  1556. // it's not (for example, for PDF output) we don't.
  1557. if (IsBackedByPixels(mCanvas.get())) {
  1558. SkColor clearColor = imageInfo.isOpaque() ? SK_ColorBLACK : SK_ColorTRANSPARENT;
  1559. mCanvas->clear(clearColor);
  1560. }
  1561. SkISize size = mCanvas->getBaseLayerSize();
  1562. mSize.width = size.width();
  1563. mSize.height = size.height();
  1564. mFormat = SkiaColorTypeToGfxFormat(imageInfo.colorType(),
  1565. imageInfo.alphaType());
  1566. return true;
  1567. }
  1568. #ifdef USE_SKIA_GPU
  1569. /** Indicating a DT should be cached means that space will be reserved in Skia's cache
  1570. * for the render target at creation time, with any unused resources exceeding the cache
  1571. * limits being purged. When the DT is freed, it will then be guaranteed to be kept around
  1572. * for subsequent allocations until it gets incidentally purged.
  1573. *
  1574. * If it is not marked as cached, no space will be purged to make room for the render
  1575. * target in the cache. When the DT is freed, If there is space within the resource limits
  1576. * it may be added to the cache, otherwise it will be freed immediately if the cache is
  1577. * already full.
  1578. *
  1579. * If you want to ensure that the resources will be kept around for reuse, it is better
  1580. * to mark them as cached. Such resources should be short-lived to ensure they don't
  1581. * permanently tie up cache resource limits. Long-lived resources should generally be
  1582. * left as uncached.
  1583. *
  1584. * In neither case will cache resource limits affect whether the resource allocation
  1585. * succeeds. The amount of in-use GPU resources is allowed to exceed the size of the cache.
  1586. * Thus, only hard GPU out-of-memory conditions will cause resource allocation to fail.
  1587. */
  1588. bool
  1589. DrawTargetSkia::InitWithGrContext(GrContext* aGrContext,
  1590. const IntSize &aSize,
  1591. SurfaceFormat aFormat,
  1592. bool aCached)
  1593. {
  1594. MOZ_ASSERT(aGrContext, "null GrContext");
  1595. if (size_t(std::max(aSize.width, aSize.height)) > GetMaxSurfaceSize()) {
  1596. return false;
  1597. }
  1598. // Create a GPU rendertarget/texture using the supplied GrContext.
  1599. // NewRenderTarget also implicitly clears the underlying texture on creation.
  1600. mSurface =
  1601. SkSurface::MakeRenderTarget(aGrContext,
  1602. SkBudgeted(aCached),
  1603. MakeSkiaImageInfo(aSize, aFormat));
  1604. if (!mSurface) {
  1605. return false;
  1606. }
  1607. mGrContext = sk_ref_sp(aGrContext);
  1608. mSize = aSize;
  1609. mFormat = aFormat;
  1610. mCanvas = sk_ref_sp(mSurface->getCanvas());
  1611. return true;
  1612. }
  1613. #endif
  1614. bool
  1615. DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized)
  1616. {
  1617. MOZ_ASSERT((aFormat != SurfaceFormat::B8G8R8X8) ||
  1618. aUninitialized || VerifyRGBXFormat(aData, aSize, aStride, aFormat));
  1619. mSurface = SkSurface::MakeRasterDirect(MakeSkiaImageInfo(aSize, aFormat), aData, aStride);
  1620. if (!mSurface) {
  1621. return false;
  1622. }
  1623. mSize = aSize;
  1624. mFormat = aFormat;
  1625. mCanvas = sk_ref_sp(mSurface->getCanvas());
  1626. return true;
  1627. }
  1628. void
  1629. DrawTargetSkia::SetTransform(const Matrix& aTransform)
  1630. {
  1631. SkMatrix mat;
  1632. GfxMatrixToSkiaMatrix(aTransform, mat);
  1633. mCanvas->setMatrix(mat);
  1634. mTransform = aTransform;
  1635. }
  1636. void*
  1637. DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType)
  1638. {
  1639. #ifdef USE_SKIA_GPU
  1640. if (aType == NativeSurfaceType::OPENGL_TEXTURE && mSurface) {
  1641. GrBackendObject handle = mSurface->getTextureHandle(SkSurface::kFlushRead_BackendHandleAccess);
  1642. if (handle) {
  1643. return (void*)(uintptr_t)reinterpret_cast<GrGLTextureInfo *>(handle)->fID;
  1644. }
  1645. }
  1646. #endif
  1647. return nullptr;
  1648. }
  1649. already_AddRefed<PathBuilder>
  1650. DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
  1651. {
  1652. return MakeAndAddRef<PathBuilderSkia>(aFillRule);
  1653. }
  1654. void
  1655. DrawTargetSkia::ClearRect(const Rect &aRect)
  1656. {
  1657. MarkChanged();
  1658. mCanvas->save();
  1659. mCanvas->clipRect(RectToSkRect(aRect), kIntersect_SkClipOp, true);
  1660. SkColor clearColor = (mFormat == SurfaceFormat::B8G8R8X8) ? SK_ColorBLACK : SK_ColorTRANSPARENT;
  1661. mCanvas->clear(clearColor);
  1662. mCanvas->restore();
  1663. }
  1664. void
  1665. DrawTargetSkia::PushClip(const Path *aPath)
  1666. {
  1667. if (aPath->GetBackendType() != BackendType::SKIA) {
  1668. return;
  1669. }
  1670. const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath);
  1671. mCanvas->save();
  1672. mCanvas->clipPath(skiaPath->GetPath(), kIntersect_SkClipOp, true);
  1673. }
  1674. void
  1675. DrawTargetSkia::PushDeviceSpaceClipRects(const IntRect* aRects, uint32_t aCount)
  1676. {
  1677. // Build a region by unioning all the rects together.
  1678. SkRegion region;
  1679. for (uint32_t i = 0; i < aCount; i++) {
  1680. region.op(IntRectToSkIRect(aRects[i]), SkRegion::kUnion_Op);
  1681. }
  1682. // Clip with the resulting region. clipRegion does not transform
  1683. // this region by the current transform, unlike the other SkCanvas
  1684. // clip methods, so it is just passed through in device-space.
  1685. mCanvas->save();
  1686. mCanvas->clipRegion(region, kIntersect_SkClipOp);
  1687. }
  1688. void
  1689. DrawTargetSkia::PushClipRect(const Rect& aRect)
  1690. {
  1691. SkRect rect = RectToSkRect(aRect);
  1692. mCanvas->save();
  1693. mCanvas->clipRect(rect, kIntersect_SkClipOp, true);
  1694. }
  1695. void
  1696. DrawTargetSkia::PopClip()
  1697. {
  1698. mCanvas->restore();
  1699. }
  1700. // Image filter that just passes the source through to the result unmodified.
  1701. class CopyLayerImageFilter : public SkImageFilter
  1702. {
  1703. public:
  1704. CopyLayerImageFilter()
  1705. : SkImageFilter(nullptr, 0, nullptr)
  1706. {}
  1707. virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source,
  1708. const Context& ctx,
  1709. SkIPoint* offset) const override {
  1710. offset->set(0, 0);
  1711. return sk_ref_sp(source);
  1712. }
  1713. SK_TO_STRING_OVERRIDE()
  1714. SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(CopyLayerImageFilter)
  1715. };
  1716. sk_sp<SkFlattenable>
  1717. CopyLayerImageFilter::CreateProc(SkReadBuffer& buffer)
  1718. {
  1719. SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
  1720. return sk_make_sp<CopyLayerImageFilter>();
  1721. }
  1722. #ifndef SK_IGNORE_TO_STRING
  1723. void
  1724. CopyLayerImageFilter::toString(SkString* str) const
  1725. {
  1726. str->append("CopyLayerImageFilter: ()");
  1727. }
  1728. #endif
  1729. void
  1730. DrawTargetSkia::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
  1731. const Matrix& aMaskTransform, const IntRect& aBounds,
  1732. bool aCopyBackground)
  1733. {
  1734. PushedLayer layer(GetPermitSubpixelAA(), aOpaque, aOpacity, aMask, aMaskTransform);
  1735. mPushedLayers.push_back(layer);
  1736. SkPaint paint;
  1737. // If we have a mask, set the opacity to 0 so that SkCanvas::restore skips
  1738. // implicitly drawing the layer so that we can properly mask it in PopLayer.
  1739. paint.setAlpha(aMask ? 0 : ColorFloatToByte(aOpacity));
  1740. SkRect bounds = IntRectToSkRect(aBounds);
  1741. sk_sp<SkImageFilter> backdrop(aCopyBackground ? new CopyLayerImageFilter : nullptr);
  1742. SkCanvas::SaveLayerRec saveRec(aBounds.IsEmpty() ? nullptr : &bounds,
  1743. &paint,
  1744. backdrop.get(),
  1745. aOpaque ? SkCanvas::kIsOpaque_SaveLayerFlag : 0);
  1746. mCanvas->saveLayer(saveRec);
  1747. SetPermitSubpixelAA(aOpaque);
  1748. #ifdef MOZ_WIDGET_COCOA
  1749. CGContextRelease(mCG);
  1750. mCG = nullptr;
  1751. #endif
  1752. }
  1753. void
  1754. DrawTargetSkia::PopLayer()
  1755. {
  1756. MarkChanged();
  1757. MOZ_ASSERT(mPushedLayers.size());
  1758. const PushedLayer& layer = mPushedLayers.back();
  1759. if (layer.mMask) {
  1760. // If we have a mask, take a reference to the top layer's device so that
  1761. // we can mask it ourselves. This assumes we forced SkCanvas::restore to
  1762. // skip implicitly drawing the layer.
  1763. sk_sp<SkBaseDevice> layerDevice = sk_ref_sp(mCanvas->getTopDevice());
  1764. SkIRect layerBounds = layerDevice->getGlobalBounds();
  1765. sk_sp<SkImage> layerImage;
  1766. SkPixmap layerPixmap;
  1767. if (layerDevice->peekPixels(&layerPixmap)) {
  1768. layerImage = SkImage::MakeFromRaster(layerPixmap, nullptr, nullptr);
  1769. #ifdef USE_SKIA_GPU
  1770. } else if (GrDrawContext* drawCtx = mCanvas->internal_private_accessTopLayerDrawContext()) {
  1771. drawCtx->prepareForExternalIO();
  1772. if (GrTexture* tex = drawCtx->accessRenderTarget()->asTexture()) {
  1773. layerImage = sk_make_sp<SkImage_Gpu>(layerBounds.width(), layerBounds.height(),
  1774. kNeedNewImageUniqueID,
  1775. layerDevice->imageInfo().alphaType(),
  1776. tex, nullptr, SkBudgeted::kNo);
  1777. }
  1778. #endif
  1779. }
  1780. // Restore the background with the layer's device left alive.
  1781. mCanvas->restore();
  1782. SkPaint paint;
  1783. paint.setAlpha(ColorFloatToByte(layer.mOpacity));
  1784. SkMatrix maskMat, layerMat;
  1785. // Get the total transform affecting the mask, considering its pattern
  1786. // transform and the current canvas transform.
  1787. GfxMatrixToSkiaMatrix(layer.mMaskTransform, maskMat);
  1788. maskMat.postConcat(mCanvas->getTotalMatrix());
  1789. if (!maskMat.invert(&layerMat)) {
  1790. gfxDebug() << *this << ": PopLayer() failed to invert mask transform";
  1791. } else {
  1792. // The layer should not be affected by the current canvas transform,
  1793. // even though the mask is. So first we use the inverse of the transform
  1794. // affecting the mask, then add back on the layer's origin.
  1795. layerMat.preTranslate(layerBounds.x(), layerBounds.y());
  1796. if (layerImage) {
  1797. paint.setShader(layerImage->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &layerMat));
  1798. } else {
  1799. paint.setColor(SK_ColorTRANSPARENT);
  1800. }
  1801. Maybe<MutexAutoLock> lock;
  1802. sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(layer.mMask, lock);
  1803. if (!alphaMask) {
  1804. gfxDebug() << *this << ": PopLayer() failed to extract alpha for mask";
  1805. } else {
  1806. mCanvas->save();
  1807. // The layer may be smaller than the canvas size, so make sure drawing is
  1808. // clipped to within the bounds of the layer.
  1809. mCanvas->resetMatrix();
  1810. mCanvas->clipRect(SkRect::Make(layerBounds));
  1811. mCanvas->setMatrix(maskMat);
  1812. mCanvas->drawImage(alphaMask, 0, 0, &paint);
  1813. mCanvas->restore();
  1814. }
  1815. }
  1816. } else {
  1817. mCanvas->restore();
  1818. }
  1819. SetPermitSubpixelAA(layer.mOldPermitSubpixelAA);
  1820. mPushedLayers.pop_back();
  1821. #ifdef MOZ_WIDGET_COCOA
  1822. CGContextRelease(mCG);
  1823. mCG = nullptr;
  1824. #endif
  1825. }
  1826. already_AddRefed<GradientStops>
  1827. DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
  1828. {
  1829. std::vector<GradientStop> stops;
  1830. stops.resize(aNumStops);
  1831. for (uint32_t i = 0; i < aNumStops; i++) {
  1832. stops[i] = aStops[i];
  1833. }
  1834. std::stable_sort(stops.begin(), stops.end());
  1835. return MakeAndAddRef<GradientStopsSkia>(stops, aNumStops, aExtendMode);
  1836. }
  1837. already_AddRefed<FilterNode>
  1838. DrawTargetSkia::CreateFilter(FilterType aType)
  1839. {
  1840. return FilterNodeSoftware::Create(aType);
  1841. }
  1842. void
  1843. DrawTargetSkia::MarkChanged()
  1844. {
  1845. if (mSnapshot) {
  1846. mSnapshot->DrawTargetWillChange();
  1847. mSnapshot = nullptr;
  1848. // Handle copying of any image snapshots bound to the surface.
  1849. if (mSurface) {
  1850. mSurface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
  1851. }
  1852. }
  1853. }
  1854. void
  1855. DrawTargetSkia::SnapshotDestroyed()
  1856. {
  1857. mSnapshot = nullptr;
  1858. }
  1859. } // namespace gfx
  1860. } // namespace mozilla