SkDevice.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Copyright 2011 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/core/SkDevice.h"
  8. #include "include/core/SkColorFilter.h"
  9. #include "include/core/SkDrawable.h"
  10. #include "include/core/SkImageFilter.h"
  11. #include "include/core/SkPathMeasure.h"
  12. #include "include/core/SkRSXform.h"
  13. #include "include/core/SkShader.h"
  14. #include "include/core/SkVertices.h"
  15. #include "include/private/SkTo.h"
  16. #include "src/core/SkDraw.h"
  17. #include "src/core/SkGlyphRun.h"
  18. #include "src/core/SkImageFilterCache.h"
  19. #include "src/core/SkImagePriv.h"
  20. #include "src/core/SkLatticeIter.h"
  21. #include "src/core/SkMakeUnique.h"
  22. #include "src/core/SkMatrixPriv.h"
  23. #include "src/core/SkPathPriv.h"
  24. #include "src/core/SkRasterClip.h"
  25. #include "src/core/SkSpecialImage.h"
  26. #include "src/core/SkTLazy.h"
  27. #include "src/core/SkTextBlobPriv.h"
  28. #include "src/core/SkUtils.h"
  29. #include "src/image/SkImage_Base.h"
  30. #include "src/shaders/SkLocalMatrixShader.h"
  31. #include "src/utils/SkPatchUtils.h"
  32. SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfaceProps)
  33. : fInfo(info)
  34. , fSurfaceProps(surfaceProps)
  35. {
  36. fOrigin = {0, 0};
  37. fCTM.reset();
  38. }
  39. void SkBaseDevice::setOrigin(const SkMatrix& globalCTM, int x, int y) {
  40. fOrigin.set(x, y);
  41. fCTM = globalCTM;
  42. fCTM.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
  43. }
  44. void SkBaseDevice::setGlobalCTM(const SkMatrix& ctm) {
  45. fCTM = ctm;
  46. if (fOrigin.fX | fOrigin.fY) {
  47. fCTM.postTranslate(-SkIntToScalar(fOrigin.fX), -SkIntToScalar(fOrigin.fY));
  48. }
  49. }
  50. bool SkBaseDevice::clipIsWideOpen() const {
  51. if (kRect_ClipType == this->onGetClipType()) {
  52. SkRegion rgn;
  53. this->onAsRgnClip(&rgn);
  54. SkASSERT(rgn.isRect());
  55. return rgn.getBounds() == SkIRect::MakeWH(this->width(), this->height());
  56. } else {
  57. return false;
  58. }
  59. }
  60. SkPixelGeometry SkBaseDevice::CreateInfo::AdjustGeometry(const SkImageInfo& info,
  61. TileUsage tileUsage,
  62. SkPixelGeometry geo,
  63. bool preserveLCDText) {
  64. switch (tileUsage) {
  65. case kPossible_TileUsage:
  66. // (we think) for compatibility with old clients, we assume this layer can support LCD
  67. // even though they may not have marked it as opaque... seems like we should update
  68. // our callers (reed/robertphilips).
  69. break;
  70. case kNever_TileUsage:
  71. if (!preserveLCDText) {
  72. geo = kUnknown_SkPixelGeometry;
  73. }
  74. break;
  75. }
  76. return geo;
  77. }
  78. static inline bool is_int(float x) {
  79. return x == (float) sk_float_round2int(x);
  80. }
  81. void SkBaseDevice::drawRegion(const SkRegion& region, const SkPaint& paint) {
  82. const SkMatrix& ctm = this->ctm();
  83. bool isNonTranslate = ctm.getType() & ~(SkMatrix::kTranslate_Mask);
  84. bool complexPaint = paint.getStyle() != SkPaint::kFill_Style || paint.getMaskFilter() ||
  85. paint.getPathEffect();
  86. bool antiAlias = paint.isAntiAlias() && (!is_int(ctm.getTranslateX()) ||
  87. !is_int(ctm.getTranslateY()));
  88. if (isNonTranslate || complexPaint || antiAlias) {
  89. SkPath path;
  90. region.getBoundaryPath(&path);
  91. path.setIsVolatile(true);
  92. return this->drawPath(path, paint, true);
  93. }
  94. SkRegion::Iterator it(region);
  95. while (!it.done()) {
  96. this->drawRect(SkRect::Make(it.rect()), paint);
  97. it.next();
  98. }
  99. }
  100. void SkBaseDevice::drawArc(const SkRect& oval, SkScalar startAngle,
  101. SkScalar sweepAngle, bool useCenter, const SkPaint& paint) {
  102. SkPath path;
  103. bool isFillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect();
  104. SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
  105. isFillNoPathEffect);
  106. this->drawPath(path, paint);
  107. }
  108. void SkBaseDevice::drawDRRect(const SkRRect& outer,
  109. const SkRRect& inner, const SkPaint& paint) {
  110. SkPath path;
  111. path.addRRect(outer);
  112. path.addRRect(inner);
  113. path.setFillType(SkPath::kEvenOdd_FillType);
  114. path.setIsVolatile(true);
  115. this->drawPath(path, paint, true);
  116. }
  117. void SkBaseDevice::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
  118. const SkPoint texCoords[4], SkBlendMode bmode, const SkPaint& paint) {
  119. SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &this->ctm());
  120. auto vertices = SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height(),
  121. this->imageInfo().colorSpace());
  122. if (vertices) {
  123. this->drawVertices(vertices.get(), nullptr, 0, bmode, paint);
  124. }
  125. }
  126. void SkBaseDevice::drawImageRect(const SkImage* image, const SkRect* src,
  127. const SkRect& dst, const SkPaint& paint,
  128. SkCanvas::SrcRectConstraint constraint) {
  129. SkBitmap bm;
  130. if (as_IB(image)->getROPixels(&bm)) {
  131. this->drawBitmapRect(bm, src, dst, paint, constraint);
  132. }
  133. }
  134. void SkBaseDevice::drawImageNine(const SkImage* image, const SkIRect& center,
  135. const SkRect& dst, const SkPaint& paint) {
  136. SkLatticeIter iter(image->width(), image->height(), center, dst);
  137. SkRect srcR, dstR;
  138. while (iter.next(&srcR, &dstR)) {
  139. this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
  140. }
  141. }
  142. void SkBaseDevice::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
  143. const SkRect& dst, const SkPaint& paint) {
  144. SkLatticeIter iter(bitmap.width(), bitmap.height(), center, dst);
  145. SkRect srcR, dstR;
  146. while (iter.next(&srcR, &dstR)) {
  147. this->drawBitmapRect(bitmap, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
  148. }
  149. }
  150. void SkBaseDevice::drawImageLattice(const SkImage* image,
  151. const SkCanvas::Lattice& lattice, const SkRect& dst,
  152. const SkPaint& paint) {
  153. SkLatticeIter iter(lattice, dst);
  154. SkRect srcR, dstR;
  155. SkColor c;
  156. bool isFixedColor = false;
  157. const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
  158. while (iter.next(&srcR, &dstR, &isFixedColor, &c)) {
  159. if (isFixedColor || (srcR.width() <= 1.0f && srcR.height() <= 1.0f &&
  160. image->readPixels(info, &c, 4, srcR.fLeft, srcR.fTop))) {
  161. // Fast draw with drawRect, if this is a patch containing a single color
  162. // or if this is a patch containing a single pixel.
  163. if (0 != c || !paint.isSrcOver()) {
  164. SkPaint paintCopy(paint);
  165. int alpha = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
  166. paintCopy.setColor(SkColorSetA(c, alpha));
  167. this->drawRect(dstR, paintCopy);
  168. }
  169. } else {
  170. this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
  171. }
  172. }
  173. }
  174. void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap,
  175. const SkCanvas::Lattice& lattice, const SkRect& dst,
  176. const SkPaint& paint) {
  177. SkLatticeIter iter(lattice, dst);
  178. SkRect srcR, dstR;
  179. while (iter.next(&srcR, &dstR)) {
  180. this->drawBitmapRect(bitmap, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
  181. }
  182. }
  183. static SkPoint* quad_to_tris(SkPoint tris[6], const SkPoint quad[4]) {
  184. tris[0] = quad[0];
  185. tris[1] = quad[1];
  186. tris[2] = quad[2];
  187. tris[3] = quad[0];
  188. tris[4] = quad[2];
  189. tris[5] = quad[3];
  190. return tris + 6;
  191. }
  192. void SkBaseDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
  193. const SkRect tex[], const SkColor colors[], int quadCount,
  194. SkBlendMode mode, const SkPaint& paint) {
  195. const int triCount = quadCount << 1;
  196. const int vertexCount = triCount * 3;
  197. uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
  198. if (colors) {
  199. flags |= SkVertices::kHasColors_BuilderFlag;
  200. }
  201. SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, vertexCount, 0, flags);
  202. SkPoint* vPos = builder.positions();
  203. SkPoint* vTex = builder.texCoords();
  204. SkColor* vCol = builder.colors();
  205. for (int i = 0; i < quadCount; ++i) {
  206. SkPoint tmp[4];
  207. xform[i].toQuad(tex[i].width(), tex[i].height(), tmp);
  208. vPos = quad_to_tris(vPos, tmp);
  209. tex[i].toQuad(tmp);
  210. vTex = quad_to_tris(vTex, tmp);
  211. if (colors) {
  212. sk_memset32(vCol, colors[i], 6);
  213. vCol += 6;
  214. }
  215. }
  216. SkPaint p(paint);
  217. p.setShader(atlas->makeShader());
  218. this->drawVertices(builder.detach().get(), nullptr, 0, mode, p);
  219. }
  220. void SkBaseDevice::drawEdgeAAQuad(const SkRect& r, const SkPoint clip[4],
  221. SkCanvas::QuadAAFlags aa, SkColor color, SkBlendMode mode) {
  222. SkPaint paint;
  223. paint.setColor(color);
  224. paint.setBlendMode(mode);
  225. paint.setAntiAlias(aa == SkCanvas::kAll_QuadAAFlags);
  226. if (clip) {
  227. // Draw the clip directly as a quad since it's a filled color with no local coords
  228. SkPath clipPath;
  229. clipPath.addPoly(clip, 4, true);
  230. this->drawPath(clipPath, paint);
  231. } else {
  232. this->drawRect(r, paint);
  233. }
  234. }
  235. void SkBaseDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry images[], int count,
  236. const SkPoint dstClips[], const SkMatrix preViewMatrices[],
  237. const SkPaint& paint,
  238. SkCanvas::SrcRectConstraint constraint) {
  239. SkASSERT(paint.getStyle() == SkPaint::kFill_Style);
  240. SkASSERT(!paint.getPathEffect());
  241. SkPaint entryPaint = paint;
  242. const SkMatrix baseCTM = this->ctm();
  243. int clipIndex = 0;
  244. for (int i = 0; i < count; ++i) {
  245. // TODO: Handle per-edge AA. Right now this mirrors the SkiaRenderer component of Chrome
  246. // which turns off antialiasing unless all four edges should be antialiased. This avoids
  247. // seaming in tiled composited layers.
  248. entryPaint.setAntiAlias(images[i].fAAFlags == SkCanvas::kAll_QuadAAFlags);
  249. entryPaint.setAlphaf(paint.getAlphaf() * images[i].fAlpha);
  250. bool needsRestore = false;
  251. SkASSERT(images[i].fMatrixIndex < 0 || preViewMatrices);
  252. if (images[i].fMatrixIndex >= 0) {
  253. this->save();
  254. this->setGlobalCTM(SkMatrix::Concat(
  255. baseCTM, preViewMatrices[images[i].fMatrixIndex]));
  256. needsRestore = true;
  257. }
  258. SkASSERT(!images[i].fHasClip || dstClips);
  259. if (images[i].fHasClip) {
  260. // Since drawImageRect requires a srcRect, the dst clip is implemented as a true clip
  261. if (!needsRestore) {
  262. this->save();
  263. needsRestore = true;
  264. }
  265. SkPath clipPath;
  266. clipPath.addPoly(dstClips + clipIndex, 4, true);
  267. this->clipPath(clipPath, SkClipOp::kIntersect, entryPaint.isAntiAlias());
  268. clipIndex += 4;
  269. }
  270. this->drawImageRect(images[i].fImage.get(), &images[i].fSrcRect, images[i].fDstRect,
  271. entryPaint, constraint);
  272. if (needsRestore) {
  273. this->restore(baseCTM);
  274. }
  275. }
  276. }
  277. ///////////////////////////////////////////////////////////////////////////////////////////////////
  278. void SkBaseDevice::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, SkCanvas* canvas) {
  279. drawable->draw(canvas, matrix);
  280. }
  281. ///////////////////////////////////////////////////////////////////////////////////////////////////
  282. void SkBaseDevice::drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
  283. SkImage*, const SkMatrix&) {}
  284. sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkBitmap&) { return nullptr; }
  285. sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkImage*) { return nullptr; }
  286. sk_sp<SkSpecialImage> SkBaseDevice::snapSpecial() { return nullptr; }
  287. ///////////////////////////////////////////////////////////////////////////////////////////////////
  288. bool SkBaseDevice::readPixels(const SkPixmap& pm, int x, int y) {
  289. return this->onReadPixels(pm, x, y);
  290. }
  291. bool SkBaseDevice::writePixels(const SkPixmap& pm, int x, int y) {
  292. return this->onWritePixels(pm, x, y);
  293. }
  294. bool SkBaseDevice::onWritePixels(const SkPixmap&, int, int) {
  295. return false;
  296. }
  297. bool SkBaseDevice::onReadPixels(const SkPixmap&, int x, int y) {
  298. return false;
  299. }
  300. bool SkBaseDevice::accessPixels(SkPixmap* pmap) {
  301. SkPixmap tempStorage;
  302. if (nullptr == pmap) {
  303. pmap = &tempStorage;
  304. }
  305. return this->onAccessPixels(pmap);
  306. }
  307. bool SkBaseDevice::peekPixels(SkPixmap* pmap) {
  308. SkPixmap tempStorage;
  309. if (nullptr == pmap) {
  310. pmap = &tempStorage;
  311. }
  312. return this->onPeekPixels(pmap);
  313. }
  314. //////////////////////////////////////////////////////////////////////////////////////////
  315. #include "src/core/SkUtils.h"
  316. void SkBaseDevice::drawGlyphRunRSXform(const SkFont& font, const SkGlyphID glyphs[],
  317. const SkRSXform xform[], int count, SkPoint origin,
  318. const SkPaint& paint) {
  319. const SkMatrix originalCTM = this->ctm();
  320. if (!originalCTM.isFinite() || !SkScalarIsFinite(font.getSize()) ||
  321. !SkScalarIsFinite(font.getScaleX()) ||
  322. !SkScalarIsFinite(font.getSkewX())) {
  323. return;
  324. }
  325. SkPoint sharedPos{0, 0}; // we're at the origin
  326. SkGlyphID glyphID;
  327. SkGlyphRun glyphRun{
  328. font,
  329. SkSpan<const SkPoint>{&sharedPos, 1},
  330. SkSpan<const SkGlyphID>{&glyphID, 1},
  331. SkSpan<const char>{},
  332. SkSpan<const uint32_t>{}
  333. };
  334. for (int i = 0; i < count; i++) {
  335. glyphID = glyphs[i];
  336. // now "glyphRun" is pointing at the current glyphID
  337. SkMatrix ctm;
  338. ctm.setRSXform(xform[i]).postTranslate(origin.fX, origin.fY);
  339. // We want to rotate each glyph by the rsxform, but we don't want to rotate "space"
  340. // (i.e. the shader that cares about the ctm) so we have to undo our little ctm trick
  341. // with a localmatrixshader so that the shader draws as if there was no change to the ctm.
  342. SkPaint transformingPaint{paint};
  343. auto shader = transformingPaint.getShader();
  344. if (shader) {
  345. SkMatrix inverse;
  346. if (ctm.invert(&inverse)) {
  347. transformingPaint.setShader(shader->makeWithLocalMatrix(inverse));
  348. } else {
  349. transformingPaint.setShader(nullptr); // can't handle this xform
  350. }
  351. }
  352. ctm.setConcat(originalCTM, ctm);
  353. this->setCTM(ctm);
  354. this->drawGlyphRunList(SkGlyphRunList{glyphRun, transformingPaint});
  355. }
  356. this->setCTM(originalCTM);
  357. }
  358. //////////////////////////////////////////////////////////////////////////////////////////
  359. sk_sp<SkSurface> SkBaseDevice::makeSurface(SkImageInfo const&, SkSurfaceProps const&) {
  360. return nullptr;
  361. }
  362. sk_sp<SkSpecialImage> SkBaseDevice::snapBackImage(const SkIRect&) {
  363. return nullptr;
  364. }
  365. //////////////////////////////////////////////////////////////////////////////////////////
  366. void SkBaseDevice::LogDrawScaleFactor(const SkMatrix& view, const SkMatrix& srcToDst,
  367. SkFilterQuality filterQuality) {
  368. #if SK_HISTOGRAMS_ENABLED
  369. SkMatrix matrix = SkMatrix::Concat(view, srcToDst);
  370. enum ScaleFactor {
  371. kUpscale_ScaleFactor,
  372. kNoScale_ScaleFactor,
  373. kDownscale_ScaleFactor,
  374. kLargeDownscale_ScaleFactor,
  375. kLast_ScaleFactor = kLargeDownscale_ScaleFactor
  376. };
  377. float rawScaleFactor = matrix.getMinScale();
  378. ScaleFactor scaleFactor;
  379. if (rawScaleFactor < 0.5f) {
  380. scaleFactor = kLargeDownscale_ScaleFactor;
  381. } else if (rawScaleFactor < 1.0f) {
  382. scaleFactor = kDownscale_ScaleFactor;
  383. } else if (rawScaleFactor > 1.0f) {
  384. scaleFactor = kUpscale_ScaleFactor;
  385. } else {
  386. scaleFactor = kNoScale_ScaleFactor;
  387. }
  388. switch (filterQuality) {
  389. case kNone_SkFilterQuality:
  390. SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.NoneFilterQuality", scaleFactor,
  391. kLast_ScaleFactor + 1);
  392. break;
  393. case kLow_SkFilterQuality:
  394. SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.LowFilterQuality", scaleFactor,
  395. kLast_ScaleFactor + 1);
  396. break;
  397. case kMedium_SkFilterQuality:
  398. SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.MediumFilterQuality", scaleFactor,
  399. kLast_ScaleFactor + 1);
  400. break;
  401. case kHigh_SkFilterQuality:
  402. SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.HighFilterQuality", scaleFactor,
  403. kLast_ScaleFactor + 1);
  404. break;
  405. }
  406. // Also log filter quality independent scale factor.
  407. SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.AnyFilterQuality", scaleFactor,
  408. kLast_ScaleFactor + 1);
  409. // Also log an overall histogram of filter quality.
  410. SK_HISTOGRAM_ENUMERATION("FilterQuality", filterQuality, kLast_SkFilterQuality + 1);
  411. #endif
  412. }