SkRecorder.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * Copyright 2014 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/SkRecorder.h"
  8. #include "include/core/SkImage.h"
  9. #include "include/core/SkPicture.h"
  10. #include "include/core/SkSurface.h"
  11. #include "include/private/SkTo.h"
  12. #include "src/core/SkBigPicture.h"
  13. #include "src/core/SkCanvasPriv.h"
  14. #include "src/utils/SkPatchUtils.h"
  15. #include <new>
  16. SkDrawableList::~SkDrawableList() {
  17. fArray.unrefAll();
  18. }
  19. SkBigPicture::SnapshotArray* SkDrawableList::newDrawableSnapshot() {
  20. const int count = fArray.count();
  21. if (0 == count) {
  22. return nullptr;
  23. }
  24. SkAutoTMalloc<const SkPicture*> pics(count);
  25. for (int i = 0; i < count; ++i) {
  26. pics[i] = fArray[i]->newPictureSnapshot();
  27. }
  28. return new SkBigPicture::SnapshotArray(pics.release(), count);
  29. }
  30. void SkDrawableList::append(SkDrawable* drawable) {
  31. *fArray.append() = SkRef(drawable);
  32. }
  33. ///////////////////////////////////////////////////////////////////////////////////////////////
  34. SkRecorder::SkRecorder(SkRecord* record, int width, int height, SkMiniRecorder* mr)
  35. : SkCanvasVirtualEnforcer<SkNoDrawCanvas>(width, height)
  36. , fDrawPictureMode(Record_DrawPictureMode)
  37. , fApproxBytesUsedBySubPictures(0)
  38. , fRecord(record)
  39. , fMiniRecorder(mr) {}
  40. SkRecorder::SkRecorder(SkRecord* record, const SkRect& bounds, SkMiniRecorder* mr)
  41. : SkCanvasVirtualEnforcer<SkNoDrawCanvas>(bounds.roundOut())
  42. , fDrawPictureMode(Record_DrawPictureMode)
  43. , fApproxBytesUsedBySubPictures(0)
  44. , fRecord(record)
  45. , fMiniRecorder(mr) {}
  46. void SkRecorder::reset(SkRecord* record, const SkRect& bounds,
  47. DrawPictureMode dpm, SkMiniRecorder* mr) {
  48. this->forgetRecord();
  49. fDrawPictureMode = dpm;
  50. fRecord = record;
  51. SkIRect rounded = bounds.roundOut();
  52. this->resetCanvas(rounded.right(), rounded.bottom());
  53. fMiniRecorder = mr;
  54. }
  55. void SkRecorder::forgetRecord() {
  56. fDrawableList.reset(nullptr);
  57. fApproxBytesUsedBySubPictures = 0;
  58. fRecord = nullptr;
  59. }
  60. // To make appending to fRecord a little less verbose.
  61. template<typename T, typename... Args>
  62. void SkRecorder::append(Args&&... args) {
  63. if (fMiniRecorder) {
  64. this->flushMiniRecorder();
  65. }
  66. new (fRecord->append<T>()) T{std::forward<Args>(args)...};
  67. }
  68. #define TRY_MINIRECORDER(method, ...) \
  69. if (fMiniRecorder && fMiniRecorder->method(__VA_ARGS__)) return
  70. // For methods which must call back into SkNoDrawCanvas.
  71. #define INHERITED(method, ...) this->SkNoDrawCanvas::method(__VA_ARGS__)
  72. // Use copy() only for optional arguments, to be copied if present or skipped if not.
  73. // (For most types we just pass by value and let copy constructors do their thing.)
  74. template <typename T>
  75. T* SkRecorder::copy(const T* src) {
  76. if (nullptr == src) {
  77. return nullptr;
  78. }
  79. return new (fRecord->alloc<T>()) T(*src);
  80. }
  81. // This copy() is for arrays.
  82. // It will work with POD or non-POD, though currently we only use it for POD.
  83. template <typename T>
  84. T* SkRecorder::copy(const T src[], size_t count) {
  85. if (nullptr == src) {
  86. return nullptr;
  87. }
  88. T* dst = fRecord->alloc<T>(count);
  89. for (size_t i = 0; i < count; i++) {
  90. new (dst + i) T(src[i]);
  91. }
  92. return dst;
  93. }
  94. // Specialization for copying strings, using memcpy.
  95. // This measured around 2x faster for copying code points,
  96. // but I found no corresponding speedup for other arrays.
  97. template <>
  98. char* SkRecorder::copy(const char src[], size_t count) {
  99. if (nullptr == src) {
  100. return nullptr;
  101. }
  102. char* dst = fRecord->alloc<char>(count);
  103. memcpy(dst, src, count);
  104. return dst;
  105. }
  106. // As above, assuming and copying a terminating \0.
  107. template <>
  108. char* SkRecorder::copy(const char* src) {
  109. return this->copy(src, strlen(src)+1);
  110. }
  111. void SkRecorder::flushMiniRecorder() {
  112. if (fMiniRecorder) {
  113. SkMiniRecorder* mr = fMiniRecorder;
  114. fMiniRecorder = nullptr; // Needs to happen before flushAndReset() or we recurse forever.
  115. mr->flushAndReset(this);
  116. }
  117. }
  118. void SkRecorder::onDrawPaint(const SkPaint& paint) {
  119. this->append<SkRecords::DrawPaint>(paint);
  120. }
  121. void SkRecorder::onDrawBehind(const SkPaint& paint) {
  122. this->append<SkRecords::DrawBehind>(paint);
  123. }
  124. void SkRecorder::onDrawPoints(PointMode mode,
  125. size_t count,
  126. const SkPoint pts[],
  127. const SkPaint& paint) {
  128. this->append<SkRecords::DrawPoints>(paint, mode, SkToUInt(count), this->copy(pts, count));
  129. }
  130. void SkRecorder::onDrawRect(const SkRect& rect, const SkPaint& paint) {
  131. TRY_MINIRECORDER(drawRect, rect, paint);
  132. this->append<SkRecords::DrawRect>(paint, rect);
  133. }
  134. void SkRecorder::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
  135. this->append<SkRecords::DrawRegion>(paint, region);
  136. }
  137. void SkRecorder::onDrawOval(const SkRect& oval, const SkPaint& paint) {
  138. this->append<SkRecords::DrawOval>(paint, oval);
  139. }
  140. void SkRecorder::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
  141. bool useCenter, const SkPaint& paint) {
  142. this->append<SkRecords::DrawArc>(paint, oval, startAngle, sweepAngle, useCenter);
  143. }
  144. void SkRecorder::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
  145. this->append<SkRecords::DrawRRect>(paint, rrect);
  146. }
  147. void SkRecorder::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
  148. this->append<SkRecords::DrawDRRect>(paint, outer, inner);
  149. }
  150. void SkRecorder::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
  151. if (fDrawPictureMode == Record_DrawPictureMode) {
  152. if (!fDrawableList) {
  153. fDrawableList.reset(new SkDrawableList);
  154. }
  155. fDrawableList->append(drawable);
  156. this->append<SkRecords::DrawDrawable>(this->copy(matrix), drawable->getBounds(), fDrawableList->count() - 1);
  157. } else {
  158. SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
  159. drawable->draw(this, matrix);
  160. }
  161. }
  162. void SkRecorder::onDrawPath(const SkPath& path, const SkPaint& paint) {
  163. TRY_MINIRECORDER(drawPath, path, paint);
  164. this->append<SkRecords::DrawPath>(paint, path);
  165. }
  166. void SkRecorder::onDrawBitmap(const SkBitmap& bitmap,
  167. SkScalar left,
  168. SkScalar top,
  169. const SkPaint* paint) {
  170. sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
  171. if (image) {
  172. this->onDrawImage(image.get(), left, top, paint);
  173. }
  174. }
  175. void SkRecorder::onDrawBitmapRect(const SkBitmap& bitmap,
  176. const SkRect* src,
  177. const SkRect& dst,
  178. const SkPaint* paint,
  179. SrcRectConstraint constraint) {
  180. sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
  181. if (image) {
  182. this->onDrawImageRect(image.get(), src, dst, paint, constraint);
  183. }
  184. }
  185. void SkRecorder::onDrawBitmapNine(const SkBitmap& bitmap,
  186. const SkIRect& center,
  187. const SkRect& dst,
  188. const SkPaint* paint) {
  189. sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
  190. if (image) {
  191. this->onDrawImageNine(image.get(), center, dst, paint);
  192. }
  193. }
  194. void SkRecorder::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
  195. const SkRect& dst, const SkPaint* paint) {
  196. sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
  197. this->onDrawImageLattice(image.get(), lattice, dst, paint);
  198. }
  199. void SkRecorder::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
  200. const SkPaint* paint) {
  201. this->append<SkRecords::DrawImage>(this->copy(paint), sk_ref_sp(image), left, top);
  202. }
  203. void SkRecorder::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
  204. const SkPaint* paint, SrcRectConstraint constraint) {
  205. this->append<SkRecords::DrawImageRect>(this->copy(paint), sk_ref_sp(image), this->copy(src), dst, constraint);
  206. }
  207. void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center,
  208. const SkRect& dst, const SkPaint* paint) {
  209. this->append<SkRecords::DrawImageNine>(this->copy(paint), sk_ref_sp(image), center, dst);
  210. }
  211. void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
  212. const SkPaint* paint) {
  213. int flagCount = lattice.fRectTypes ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0;
  214. SkASSERT(lattice.fBounds);
  215. this->append<SkRecords::DrawImageLattice>(this->copy(paint), sk_ref_sp(image),
  216. lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount),
  217. lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount),
  218. flagCount, this->copy(lattice.fRectTypes, flagCount),
  219. this->copy(lattice.fColors, flagCount), *lattice.fBounds, dst);
  220. }
  221. void SkRecorder::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
  222. const SkPaint& paint) {
  223. TRY_MINIRECORDER(drawTextBlob, blob, x, y, paint);
  224. this->append<SkRecords::DrawTextBlob>(paint, sk_ref_sp(blob), x, y);
  225. }
  226. void SkRecorder::onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, const SkPaint* paint) {
  227. if (fDrawPictureMode == Record_DrawPictureMode) {
  228. fApproxBytesUsedBySubPictures += pic->approximateBytesUsed();
  229. this->append<SkRecords::DrawPicture>(this->copy(paint), sk_ref_sp(pic), matrix ? *matrix : SkMatrix::I());
  230. } else {
  231. SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
  232. SkAutoCanvasMatrixPaint acmp(this, matrix, paint, pic->cullRect());
  233. pic->playback(this);
  234. }
  235. }
  236. void SkRecorder::onDrawVerticesObject(const SkVertices* vertices, const SkVertices::Bone bones[],
  237. int boneCount, SkBlendMode bmode, const SkPaint& paint) {
  238. this->append<SkRecords::DrawVertices>(paint,
  239. sk_ref_sp(const_cast<SkVertices*>(vertices)),
  240. this->copy(bones, boneCount),
  241. boneCount,
  242. bmode);
  243. }
  244. void SkRecorder::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
  245. const SkPoint texCoords[4], SkBlendMode bmode,
  246. const SkPaint& paint) {
  247. this->append<SkRecords::DrawPatch>(paint,
  248. cubics ? this->copy(cubics, SkPatchUtils::kNumCtrlPts) : nullptr,
  249. colors ? this->copy(colors, SkPatchUtils::kNumCorners) : nullptr,
  250. texCoords ? this->copy(texCoords, SkPatchUtils::kNumCorners) : nullptr,
  251. bmode);
  252. }
  253. void SkRecorder::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
  254. const SkColor colors[], int count, SkBlendMode mode,
  255. const SkRect* cull, const SkPaint* paint) {
  256. this->append<SkRecords::DrawAtlas>(this->copy(paint),
  257. sk_ref_sp(atlas),
  258. this->copy(xform, count),
  259. this->copy(tex, count),
  260. this->copy(colors, count),
  261. count,
  262. mode,
  263. this->copy(cull));
  264. }
  265. void SkRecorder::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
  266. this->append<SkRecords::DrawShadowRec>(path, rec);
  267. }
  268. void SkRecorder::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
  269. this->append<SkRecords::DrawAnnotation>(rect, SkString(key), sk_ref_sp(value));
  270. }
  271. void SkRecorder::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
  272. QuadAAFlags aa, SkColor color, SkBlendMode mode) {
  273. this->append<SkRecords::DrawEdgeAAQuad>(
  274. rect, this->copy(clip, 4), aa, color, mode);
  275. }
  276. void SkRecorder::onDrawEdgeAAImageSet(const ImageSetEntry set[], int count,
  277. const SkPoint dstClips[], const SkMatrix preViewMatrices[],
  278. const SkPaint* paint, SrcRectConstraint constraint) {
  279. int totalDstClipCount, totalMatrixCount;
  280. SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
  281. SkAutoTArray<ImageSetEntry> setCopy(count);
  282. for (int i = 0; i < count; ++i) {
  283. setCopy[i] = set[i];
  284. }
  285. this->append<SkRecords::DrawEdgeAAImageSet>(this->copy(paint), std::move(setCopy), count,
  286. this->copy(dstClips, totalDstClipCount),
  287. this->copy(preViewMatrices, totalMatrixCount), constraint);
  288. }
  289. void SkRecorder::onFlush() {
  290. this->append<SkRecords::Flush>();
  291. }
  292. void SkRecorder::willSave() {
  293. this->append<SkRecords::Save>();
  294. }
  295. SkCanvas::SaveLayerStrategy SkRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) {
  296. this->append<SkRecords::SaveLayer>(this->copy(rec.fBounds)
  297. , this->copy(rec.fPaint)
  298. , sk_ref_sp(rec.fBackdrop)
  299. , sk_ref_sp(rec.fClipMask)
  300. , this->copy(rec.fClipMatrix)
  301. , rec.fSaveLayerFlags);
  302. return SkCanvas::kNoLayer_SaveLayerStrategy;
  303. }
  304. bool SkRecorder::onDoSaveBehind(const SkRect* subset) {
  305. this->append<SkRecords::SaveBehind>(this->copy(subset));
  306. return false;
  307. }
  308. void SkRecorder::didRestore() {
  309. this->append<SkRecords::Restore>(this->getTotalMatrix());
  310. }
  311. void SkRecorder::didConcat(const SkMatrix& matrix) {
  312. this->append<SkRecords::Concat>(matrix);
  313. }
  314. void SkRecorder::didSetMatrix(const SkMatrix& matrix) {
  315. this->append<SkRecords::SetMatrix>(matrix);
  316. }
  317. void SkRecorder::didTranslate(SkScalar dx, SkScalar dy) {
  318. this->append<SkRecords::Translate>(dx, dy);
  319. }
  320. void SkRecorder::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
  321. INHERITED(onClipRect, rect, op, edgeStyle);
  322. SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
  323. this->append<SkRecords::ClipRect>(rect, opAA);
  324. }
  325. void SkRecorder::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
  326. INHERITED(onClipRRect, rrect, op, edgeStyle);
  327. SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
  328. this->append<SkRecords::ClipRRect>(rrect, opAA);
  329. }
  330. void SkRecorder::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
  331. INHERITED(onClipPath, path, op, edgeStyle);
  332. SkRecords::ClipOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
  333. this->append<SkRecords::ClipPath>(path, opAA);
  334. }
  335. void SkRecorder::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
  336. INHERITED(onClipRegion, deviceRgn, op);
  337. this->append<SkRecords::ClipRegion>(deviceRgn, op);
  338. }
  339. sk_sp<SkSurface> SkRecorder::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
  340. return nullptr;
  341. }