SkPictureRecord.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  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/SkPictureRecord.h"
  8. #include "include/core/SkRRect.h"
  9. #include "include/core/SkRSXform.h"
  10. #include "include/core/SkTextBlob.h"
  11. #include "include/private/SkTo.h"
  12. #include "src/core/SkCanvasPriv.h"
  13. #include "src/core/SkClipOpPriv.h"
  14. #include "src/core/SkDrawShadowInfo.h"
  15. #include "src/core/SkMatrixPriv.h"
  16. #include "src/core/SkTSearch.h"
  17. #include "src/image/SkImage_Base.h"
  18. #include "src/utils/SkPatchUtils.h"
  19. #define HEAP_BLOCK_SIZE 4096
  20. enum {
  21. // just need a value that save or getSaveCount would never return
  22. kNoInitialSave = -1,
  23. };
  24. // A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
  25. static int const kUInt32Size = 4;
  26. SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
  27. : INHERITED(dimensions.width(), dimensions.height())
  28. , fRecordFlags(flags)
  29. , fInitialSaveCount(kNoInitialSave) {
  30. }
  31. ///////////////////////////////////////////////////////////////////////////////
  32. void SkPictureRecord::onFlush() {
  33. size_t size = sizeof(kUInt32Size);
  34. size_t initialOffset = this->addDraw(FLUSH, &size);
  35. this->validate(initialOffset, size);
  36. }
  37. void SkPictureRecord::willSave() {
  38. // record the offset to us, making it non-positive to distinguish a save
  39. // from a clip entry.
  40. fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
  41. this->recordSave();
  42. this->INHERITED::willSave();
  43. }
  44. void SkPictureRecord::recordSave() {
  45. // op only
  46. size_t size = sizeof(kUInt32Size);
  47. size_t initialOffset = this->addDraw(SAVE, &size);
  48. this->validate(initialOffset, size);
  49. }
  50. SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
  51. // record the offset to us, making it non-positive to distinguish a save
  52. // from a clip entry.
  53. fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
  54. this->recordSaveLayer(rec);
  55. (void)this->INHERITED::getSaveLayerStrategy(rec);
  56. /* No need for a (potentially very big) layer which we don't actually need
  57. at this time (and may not be able to afford since during record our
  58. clip starts out the size of the picture, which is often much larger
  59. than the size of the actual device we'll use during playback).
  60. */
  61. return kNoLayer_SaveLayerStrategy;
  62. }
  63. bool SkPictureRecord::onDoSaveBehind(const SkRect* subset) {
  64. fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
  65. size_t size = sizeof(kUInt32Size) + sizeof(uint32_t); // op + flags
  66. uint32_t flags = 0;
  67. if (subset) {
  68. flags |= SAVEBEHIND_HAS_SUBSET;
  69. size += sizeof(*subset);
  70. }
  71. size_t initialOffset = this->addDraw(SAVE_BEHIND, &size);
  72. this->addInt(flags);
  73. if (subset) {
  74. this->addRect(*subset);
  75. }
  76. this->validate(initialOffset, size);
  77. return false;
  78. }
  79. void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
  80. // op + flatflags
  81. size_t size = 2 * kUInt32Size;
  82. uint32_t flatFlags = 0;
  83. if (rec.fBounds) {
  84. flatFlags |= SAVELAYERREC_HAS_BOUNDS;
  85. size += sizeof(*rec.fBounds);
  86. }
  87. if (rec.fPaint) {
  88. flatFlags |= SAVELAYERREC_HAS_PAINT;
  89. size += sizeof(uint32_t); // index
  90. }
  91. if (rec.fBackdrop) {
  92. flatFlags |= SAVELAYERREC_HAS_BACKDROP;
  93. size += sizeof(uint32_t); // (paint) index
  94. }
  95. if (rec.fSaveLayerFlags) {
  96. flatFlags |= SAVELAYERREC_HAS_FLAGS;
  97. size += sizeof(uint32_t);
  98. }
  99. if (rec.fClipMask) {
  100. flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
  101. size += sizeof(uint32_t); // clip image index
  102. }
  103. if (rec.fClipMatrix) {
  104. flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
  105. size += SkMatrixPriv::WriteToMemory(*rec.fClipMatrix, nullptr);
  106. }
  107. const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
  108. this->addInt(flatFlags);
  109. if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
  110. this->addRect(*rec.fBounds);
  111. }
  112. if (flatFlags & SAVELAYERREC_HAS_PAINT) {
  113. this->addPaintPtr(rec.fPaint);
  114. }
  115. if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
  116. // overkill, but we didn't already track single flattenables, so using a paint for that
  117. SkPaint paint;
  118. paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
  119. this->addPaint(paint);
  120. }
  121. if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
  122. this->addInt(rec.fSaveLayerFlags);
  123. }
  124. if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
  125. this->addImage(rec.fClipMask);
  126. }
  127. if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
  128. this->addMatrix(*rec.fClipMatrix);
  129. }
  130. this->validate(initialOffset, size);
  131. }
  132. #ifdef SK_DEBUG
  133. /*
  134. * Read the op code from 'offset' in 'writer' and extract the size too.
  135. */
  136. static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
  137. uint32_t peek = writer->readTAt<uint32_t>(offset);
  138. uint32_t op;
  139. UNPACK_8_24(peek, op, *size);
  140. if (MASK_24 == *size) {
  141. // size required its own slot right after the op code
  142. *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
  143. }
  144. return (DrawType) op;
  145. }
  146. #endif//SK_DEBUG
  147. void SkPictureRecord::willRestore() {
  148. #if 0
  149. SkASSERT(fRestoreOffsetStack.count() > 1);
  150. #endif
  151. // check for underflow
  152. if (fRestoreOffsetStack.count() == 0) {
  153. return;
  154. }
  155. this->recordRestore();
  156. fRestoreOffsetStack.pop();
  157. this->INHERITED::willRestore();
  158. }
  159. void SkPictureRecord::recordRestore(bool fillInSkips) {
  160. if (fillInSkips) {
  161. this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
  162. }
  163. size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
  164. size_t initialOffset = this->addDraw(RESTORE, &size);
  165. this->validate(initialOffset, size);
  166. }
  167. void SkPictureRecord::recordTranslate(const SkMatrix& m) {
  168. SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
  169. // op + dx + dy
  170. size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
  171. size_t initialOffset = this->addDraw(TRANSLATE, &size);
  172. this->addScalar(m.getTranslateX());
  173. this->addScalar(m.getTranslateY());
  174. this->validate(initialOffset, size);
  175. }
  176. void SkPictureRecord::recordScale(const SkMatrix& m) {
  177. SkASSERT(SkMatrix::kScale_Mask == m.getType());
  178. // op + sx + sy
  179. size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
  180. size_t initialOffset = this->addDraw(SCALE, &size);
  181. this->addScalar(m.getScaleX());
  182. this->addScalar(m.getScaleY());
  183. this->validate(initialOffset, size);
  184. }
  185. void SkPictureRecord::didConcat(const SkMatrix& matrix) {
  186. switch (matrix.getType()) {
  187. case SkMatrix::kTranslate_Mask:
  188. this->recordTranslate(matrix);
  189. break;
  190. case SkMatrix::kScale_Mask:
  191. this->recordScale(matrix);
  192. break;
  193. default:
  194. this->recordConcat(matrix);
  195. break;
  196. }
  197. this->INHERITED::didConcat(matrix);
  198. }
  199. void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
  200. this->validate(fWriter.bytesWritten(), 0);
  201. // op + matrix
  202. size_t size = kUInt32Size + SkMatrixPriv::WriteToMemory(matrix, nullptr);
  203. size_t initialOffset = this->addDraw(CONCAT, &size);
  204. this->addMatrix(matrix);
  205. this->validate(initialOffset, size);
  206. }
  207. void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
  208. this->validate(fWriter.bytesWritten(), 0);
  209. // op + matrix
  210. size_t size = kUInt32Size + SkMatrixPriv::WriteToMemory(matrix, nullptr);
  211. size_t initialOffset = this->addDraw(SET_MATRIX, &size);
  212. this->addMatrix(matrix);
  213. this->validate(initialOffset, size);
  214. this->INHERITED::didSetMatrix(matrix);
  215. }
  216. static bool clipOpExpands(SkClipOp op) {
  217. switch (op) {
  218. case kUnion_SkClipOp:
  219. case kXOR_SkClipOp:
  220. case kReverseDifference_SkClipOp:
  221. case kReplace_SkClipOp:
  222. return true;
  223. case kIntersect_SkClipOp:
  224. case kDifference_SkClipOp:
  225. return false;
  226. default:
  227. SkDEBUGFAIL("unknown clipop");
  228. return false;
  229. }
  230. }
  231. void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
  232. int32_t offset = fRestoreOffsetStack.top();
  233. while (offset > 0) {
  234. uint32_t peek = fWriter.readTAt<uint32_t>(offset);
  235. fWriter.overwriteTAt(offset, restoreOffset);
  236. offset = peek;
  237. }
  238. #ifdef SK_DEBUG
  239. // offset of 0 has been disabled, so we skip it
  240. if (offset > 0) {
  241. // assert that the final offset value points to a save verb
  242. uint32_t opSize;
  243. DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
  244. SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
  245. }
  246. #endif
  247. }
  248. void SkPictureRecord::beginRecording() {
  249. // we have to call this *after* our constructor, to ensure that it gets
  250. // recorded. This is balanced by restoreToCount() call from endRecording,
  251. // which in-turn calls our overridden restore(), so those get recorded too.
  252. fInitialSaveCount = this->save();
  253. }
  254. void SkPictureRecord::endRecording() {
  255. SkASSERT(kNoInitialSave != fInitialSaveCount);
  256. this->restoreToCount(fInitialSaveCount);
  257. }
  258. size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
  259. if (fRestoreOffsetStack.isEmpty()) {
  260. return -1;
  261. }
  262. // The RestoreOffset field is initially filled with a placeholder
  263. // value that points to the offset of the previous RestoreOffset
  264. // in the current stack level, thus forming a linked list so that
  265. // the restore offsets can be filled in when the corresponding
  266. // restore command is recorded.
  267. int32_t prevOffset = fRestoreOffsetStack.top();
  268. if (clipOpExpands(op)) {
  269. // Run back through any previous clip ops, and mark their offset to
  270. // be 0, disabling their ability to trigger a jump-to-restore, otherwise
  271. // they could hide this clips ability to expand the clip (i.e. go from
  272. // empty to non-empty).
  273. this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
  274. // Reset the pointer back to the previous clip so that subsequent
  275. // restores don't overwrite the offsets we just cleared.
  276. prevOffset = 0;
  277. }
  278. size_t offset = fWriter.bytesWritten();
  279. this->addInt(prevOffset);
  280. fRestoreOffsetStack.top() = SkToU32(offset);
  281. return offset;
  282. }
  283. void SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
  284. this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
  285. this->INHERITED::onClipRect(rect, op, edgeStyle);
  286. }
  287. size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
  288. // id + rect + clip params
  289. size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
  290. // recordRestoreOffsetPlaceholder doesn't always write an offset
  291. if (!fRestoreOffsetStack.isEmpty()) {
  292. // + restore offset
  293. size += kUInt32Size;
  294. }
  295. size_t initialOffset = this->addDraw(CLIP_RECT, &size);
  296. this->addRect(rect);
  297. this->addInt(ClipParams_pack(op, doAA));
  298. size_t offset = this->recordRestoreOffsetPlaceholder(op);
  299. this->validate(initialOffset, size);
  300. return offset;
  301. }
  302. void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
  303. this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
  304. this->INHERITED::onClipRRect(rrect, op, edgeStyle);
  305. }
  306. size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
  307. // op + rrect + clip params
  308. size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
  309. // recordRestoreOffsetPlaceholder doesn't always write an offset
  310. if (!fRestoreOffsetStack.isEmpty()) {
  311. // + restore offset
  312. size += kUInt32Size;
  313. }
  314. size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
  315. this->addRRect(rrect);
  316. this->addInt(ClipParams_pack(op, doAA));
  317. size_t offset = recordRestoreOffsetPlaceholder(op);
  318. this->validate(initialOffset, size);
  319. return offset;
  320. }
  321. void SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
  322. int pathID = this->addPathToHeap(path);
  323. this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
  324. this->INHERITED::onClipPath(path, op, edgeStyle);
  325. }
  326. size_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
  327. // op + path index + clip params
  328. size_t size = 3 * kUInt32Size;
  329. // recordRestoreOffsetPlaceholder doesn't always write an offset
  330. if (!fRestoreOffsetStack.isEmpty()) {
  331. // + restore offset
  332. size += kUInt32Size;
  333. }
  334. size_t initialOffset = this->addDraw(CLIP_PATH, &size);
  335. this->addInt(pathID);
  336. this->addInt(ClipParams_pack(op, doAA));
  337. size_t offset = recordRestoreOffsetPlaceholder(op);
  338. this->validate(initialOffset, size);
  339. return offset;
  340. }
  341. void SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
  342. this->recordClipRegion(region, op);
  343. this->INHERITED::onClipRegion(region, op);
  344. }
  345. size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
  346. // op + clip params + region
  347. size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
  348. // recordRestoreOffsetPlaceholder doesn't always write an offset
  349. if (!fRestoreOffsetStack.isEmpty()) {
  350. // + restore offset
  351. size += kUInt32Size;
  352. }
  353. size_t initialOffset = this->addDraw(CLIP_REGION, &size);
  354. this->addRegion(region);
  355. this->addInt(ClipParams_pack(op, false));
  356. size_t offset = this->recordRestoreOffsetPlaceholder(op);
  357. this->validate(initialOffset, size);
  358. return offset;
  359. }
  360. void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
  361. // op + paint index
  362. size_t size = 2 * kUInt32Size;
  363. size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
  364. this->addPaint(paint);
  365. this->validate(initialOffset, size);
  366. }
  367. void SkPictureRecord::onDrawBehind(const SkPaint& paint) {
  368. // logically the same as drawPaint, but with a diff enum
  369. // op + paint index
  370. size_t size = 2 * kUInt32Size;
  371. size_t initialOffset = this->addDraw(DRAW_BEHIND_PAINT, &size);
  372. this->addPaint(paint);
  373. this->validate(initialOffset, size);
  374. }
  375. void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
  376. const SkPaint& paint) {
  377. // op + paint index + mode + count + point data
  378. size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
  379. size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
  380. this->addPaint(paint);
  381. this->addInt(mode);
  382. this->addInt(SkToInt(count));
  383. fWriter.writeMul4(pts, count * sizeof(SkPoint));
  384. this->validate(initialOffset, size);
  385. }
  386. void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
  387. // op + paint index + rect
  388. size_t size = 2 * kUInt32Size + sizeof(oval);
  389. size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
  390. this->addPaint(paint);
  391. this->addRect(oval);
  392. this->validate(initialOffset, size);
  393. }
  394. void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
  395. bool useCenter, const SkPaint& paint) {
  396. // op + paint index + rect + start + sweep + bool (as int)
  397. size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
  398. sizeof(int);
  399. size_t initialOffset = this->addDraw(DRAW_ARC, &size);
  400. this->addPaint(paint);
  401. this->addRect(oval);
  402. this->addScalar(startAngle);
  403. this->addScalar(sweepAngle);
  404. this->addInt(useCenter);
  405. this->validate(initialOffset, size);
  406. }
  407. void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
  408. // op + paint index + rect
  409. size_t size = 2 * kUInt32Size + sizeof(rect);
  410. size_t initialOffset = this->addDraw(DRAW_RECT, &size);
  411. this->addPaint(paint);
  412. this->addRect(rect);
  413. this->validate(initialOffset, size);
  414. }
  415. void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
  416. // op + paint index + region
  417. size_t regionBytes = region.writeToMemory(nullptr);
  418. size_t size = 2 * kUInt32Size + regionBytes;
  419. size_t initialOffset = this->addDraw(DRAW_REGION, &size);
  420. this->addPaint(paint);
  421. fWriter.writeRegion(region);
  422. this->validate(initialOffset, size);
  423. }
  424. void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
  425. // op + paint index + rrect
  426. size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
  427. size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
  428. this->addPaint(paint);
  429. this->addRRect(rrect);
  430. this->validate(initialOffset, size);
  431. }
  432. void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
  433. const SkPaint& paint) {
  434. // op + paint index + rrects
  435. size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
  436. size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
  437. this->addPaint(paint);
  438. this->addRRect(outer);
  439. this->addRRect(inner);
  440. this->validate(initialOffset, size);
  441. }
  442. void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
  443. // op + paint index + path index
  444. size_t size = 3 * kUInt32Size;
  445. size_t initialOffset = this->addDraw(DRAW_PATH, &size);
  446. this->addPaint(paint);
  447. this->addPath(path);
  448. this->validate(initialOffset, size);
  449. }
  450. void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
  451. const SkPaint* paint) {
  452. // op + paint_index + image_index + x + y
  453. size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
  454. size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
  455. this->addPaintPtr(paint);
  456. this->addImage(image);
  457. this->addScalar(x);
  458. this->addScalar(y);
  459. this->validate(initialOffset, size);
  460. }
  461. void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
  462. const SkPaint* paint, SrcRectConstraint constraint) {
  463. // id + paint_index + image_index + bool_for_src + constraint
  464. size_t size = 5 * kUInt32Size;
  465. if (src) {
  466. size += sizeof(*src); // + rect
  467. }
  468. size += sizeof(dst); // + rect
  469. size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
  470. this->addPaintPtr(paint);
  471. this->addImage(image);
  472. this->addRectPtr(src); // may be null
  473. this->addRect(dst);
  474. this->addInt(constraint);
  475. this->validate(initialOffset, size);
  476. }
  477. void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
  478. const SkPaint* paint) {
  479. // id + paint_index + image_index + center + dst
  480. size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
  481. size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
  482. this->addPaintPtr(paint);
  483. this->addImage(img);
  484. this->addIRect(center);
  485. this->addRect(dst);
  486. this->validate(initialOffset, size);
  487. }
  488. void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
  489. const SkRect& dst, const SkPaint* paint) {
  490. size_t latticeSize = SkCanvasPriv::WriteLattice(nullptr, lattice);
  491. // op + paint index + image index + lattice + dst rect
  492. size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
  493. size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
  494. this->addPaintPtr(paint);
  495. this->addImage(image);
  496. (void)SkCanvasPriv::WriteLattice(fWriter.reservePad(latticeSize), lattice);
  497. this->addRect(dst);
  498. this->validate(initialOffset, size);
  499. }
  500. void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
  501. const SkPaint& paint) {
  502. // op + paint index + blob index + x/y
  503. size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
  504. size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
  505. this->addPaint(paint);
  506. this->addTextBlob(blob);
  507. this->addScalar(x);
  508. this->addScalar(y);
  509. this->validate(initialOffset, size);
  510. }
  511. void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
  512. const SkPaint* paint) {
  513. // op + picture index
  514. size_t size = 2 * kUInt32Size;
  515. size_t initialOffset;
  516. if (nullptr == matrix && nullptr == paint) {
  517. initialOffset = this->addDraw(DRAW_PICTURE, &size);
  518. this->addPicture(picture);
  519. } else {
  520. const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
  521. size += SkMatrixPriv::WriteToMemory(m, nullptr) + kUInt32Size; // matrix + paint
  522. initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
  523. this->addPaintPtr(paint);
  524. this->addMatrix(m);
  525. this->addPicture(picture);
  526. }
  527. this->validate(initialOffset, size);
  528. }
  529. void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
  530. // op + drawable index
  531. size_t size = 2 * kUInt32Size;
  532. size_t initialOffset;
  533. if (nullptr == matrix) {
  534. initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
  535. this->addDrawable(drawable);
  536. } else {
  537. size += SkMatrixPriv::WriteToMemory(*matrix, nullptr); // matrix
  538. initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
  539. this->addMatrix(*matrix);
  540. this->addDrawable(drawable);
  541. }
  542. this->validate(initialOffset, size);
  543. }
  544. void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices,
  545. const SkVertices::Bone bones[], int boneCount,
  546. SkBlendMode mode, const SkPaint& paint) {
  547. // op + paint index + vertices index + number of bones + bone matrices + mode
  548. size_t size = 5 * kUInt32Size + boneCount * sizeof(SkVertices::Bone);
  549. size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
  550. this->addPaint(paint);
  551. this->addVertices(vertices);
  552. this->addInt(boneCount);
  553. fWriter.write(bones, boneCount * sizeof(SkVertices::Bone));
  554. this->addInt(static_cast<uint32_t>(mode));
  555. this->validate(initialOffset, size);
  556. }
  557. void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
  558. const SkPoint texCoords[4], SkBlendMode bmode,
  559. const SkPaint& paint) {
  560. // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
  561. size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
  562. uint32_t flag = 0;
  563. if (colors) {
  564. flag |= DRAW_VERTICES_HAS_COLORS;
  565. size += SkPatchUtils::kNumCorners * sizeof(SkColor);
  566. }
  567. if (texCoords) {
  568. flag |= DRAW_VERTICES_HAS_TEXS;
  569. size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
  570. }
  571. if (SkBlendMode::kModulate != bmode) {
  572. flag |= DRAW_VERTICES_HAS_XFER;
  573. size += kUInt32Size;
  574. }
  575. size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
  576. this->addPaint(paint);
  577. this->addPatch(cubics);
  578. this->addInt(flag);
  579. // write optional parameters
  580. if (colors) {
  581. fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
  582. }
  583. if (texCoords) {
  584. fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
  585. }
  586. if (flag & DRAW_VERTICES_HAS_XFER) {
  587. this->addInt((int)bmode);
  588. }
  589. this->validate(initialOffset, size);
  590. }
  591. void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
  592. const SkColor colors[], int count, SkBlendMode mode,
  593. const SkRect* cull, const SkPaint* paint) {
  594. // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
  595. size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
  596. uint32_t flags = 0;
  597. if (colors) {
  598. flags |= DRAW_ATLAS_HAS_COLORS;
  599. size += count * sizeof(SkColor);
  600. size += sizeof(uint32_t); // xfermode::mode
  601. }
  602. if (cull) {
  603. flags |= DRAW_ATLAS_HAS_CULL;
  604. size += sizeof(SkRect);
  605. }
  606. size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
  607. this->addPaintPtr(paint);
  608. this->addImage(atlas);
  609. this->addInt(flags);
  610. this->addInt(count);
  611. fWriter.write(xform, count * sizeof(SkRSXform));
  612. fWriter.write(tex, count * sizeof(SkRect));
  613. // write optional parameters
  614. if (colors) {
  615. fWriter.write(colors, count * sizeof(SkColor));
  616. this->addInt((int)mode);
  617. }
  618. if (cull) {
  619. fWriter.write(cull, sizeof(SkRect));
  620. }
  621. this->validate(initialOffset, size);
  622. }
  623. void SkPictureRecord::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
  624. // op + path index + zParams + lightPos + lightRadius + spot/ambient alphas + color + flags
  625. size_t size = 2 * kUInt32Size + 2 * sizeof(SkPoint3) + 1 * sizeof(SkScalar) + 3 * kUInt32Size;
  626. size_t initialOffset = this->addDraw(DRAW_SHADOW_REC, &size);
  627. this->addPath(path);
  628. fWriter.writePoint3(rec.fZPlaneParams);
  629. fWriter.writePoint3(rec.fLightPos);
  630. fWriter.writeScalar(rec.fLightRadius);
  631. fWriter.write32(rec.fAmbientColor);
  632. fWriter.write32(rec.fSpotColor);
  633. fWriter.write32(rec.fFlags);
  634. this->validate(initialOffset, size);
  635. }
  636. void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
  637. size_t keyLen = fWriter.WriteStringSize(key);
  638. size_t valueLen = fWriter.WriteDataSize(value);
  639. size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
  640. size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
  641. this->addRect(rect);
  642. fWriter.writeString(key);
  643. fWriter.writeData(value);
  644. this->validate(initialOffset, size);
  645. }
  646. void SkPictureRecord::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
  647. SkCanvas::QuadAAFlags aa, SkColor color, SkBlendMode mode) {
  648. // op + rect + aa flags + color + mode + hasClip(as int) + clipCount*points
  649. size_t size = 5 * kUInt32Size + sizeof(rect) + (clip ? 4 : 0) * sizeof(SkPoint);
  650. size_t initialOffset = this->addDraw(DRAW_EDGEAA_QUAD, &size);
  651. this->addRect(rect);
  652. this->addInt((int) aa);
  653. this->addInt((int) color);
  654. this->addInt((int) mode);
  655. this->addInt(clip != nullptr);
  656. if (clip) {
  657. this->addPoints(clip, 4);
  658. }
  659. this->validate(initialOffset, size);
  660. }
  661. void SkPictureRecord::onDrawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int count,
  662. const SkPoint dstClips[],
  663. const SkMatrix preViewMatrices[],
  664. const SkPaint* paint,
  665. SkCanvas::SrcRectConstraint constraint) {
  666. static constexpr size_t kMatrixSize = 9 * sizeof(SkScalar); // *not* sizeof(SkMatrix)
  667. // op + count + paint + constraint + (image index, src rect, dst rect, alpha, aa flags,
  668. // hasClip(int), matrixIndex) * cnt + totalClipCount + dstClips + totalMatrixCount + matrices
  669. int totalDstClipCount, totalMatrixCount;
  670. SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
  671. size_t size = 6 * kUInt32Size + sizeof(SkPoint) * totalDstClipCount +
  672. kMatrixSize * totalMatrixCount +
  673. (4 * kUInt32Size + 2 * sizeof(SkRect) + sizeof(SkScalar)) * count;
  674. size_t initialOffset = this->addDraw(DRAW_EDGEAA_IMAGE_SET, &size);
  675. this->addInt(count);
  676. this->addPaintPtr(paint);
  677. this->addInt((int) constraint);
  678. for (int i = 0; i < count; ++i) {
  679. this->addImage(set[i].fImage.get());
  680. this->addRect(set[i].fSrcRect);
  681. this->addRect(set[i].fDstRect);
  682. this->addInt(set[i].fMatrixIndex);
  683. this->addScalar(set[i].fAlpha);
  684. this->addInt((int)set[i].fAAFlags);
  685. this->addInt(set[i].fHasClip);
  686. }
  687. this->addInt(totalDstClipCount);
  688. this->addPoints(dstClips, totalDstClipCount);
  689. this->addInt(totalMatrixCount);
  690. for (int i = 0; i < totalMatrixCount; ++i) {
  691. this->addMatrix(preViewMatrices[i]);
  692. }
  693. this->validate(initialOffset, size);
  694. }
  695. ///////////////////////////////////////////////////////////////////////////////
  696. // De-duping helper.
  697. template <typename T>
  698. static bool equals(T* a, T* b) { return a->uniqueID() == b->uniqueID(); }
  699. template <>
  700. bool equals(SkDrawable* a, SkDrawable* b) {
  701. // SkDrawable's generationID is not a stable unique identifier.
  702. return a == b;
  703. }
  704. template <typename T>
  705. static int find_or_append(SkTArray<sk_sp<T>>& array, T* obj) {
  706. for (int i = 0; i < array.count(); i++) {
  707. if (equals(array[i].get(), obj)) {
  708. return i;
  709. }
  710. }
  711. array.push_back(sk_ref_sp(obj));
  712. return array.count() - 1;
  713. }
  714. sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
  715. return nullptr;
  716. }
  717. void SkPictureRecord::addImage(const SkImage* image) {
  718. // convention for images is 0-based index
  719. this->addInt(find_or_append(fImages, image));
  720. }
  721. void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
  722. fWriter.writeMatrix(matrix);
  723. }
  724. void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
  725. if (paint) {
  726. fPaints.push_back(*paint);
  727. this->addInt(fPaints.count());
  728. } else {
  729. this->addInt(0);
  730. }
  731. }
  732. int SkPictureRecord::addPathToHeap(const SkPath& path) {
  733. if (int* n = fPaths.find(path)) {
  734. return *n;
  735. }
  736. int n = fPaths.count() + 1; // 0 is reserved for null / error.
  737. fPaths.set(path, n);
  738. return n;
  739. }
  740. void SkPictureRecord::addPath(const SkPath& path) {
  741. this->addInt(this->addPathToHeap(path));
  742. }
  743. void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
  744. fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
  745. }
  746. void SkPictureRecord::addPicture(const SkPicture* picture) {
  747. // follow the convention of recording a 1-based index
  748. this->addInt(find_or_append(fPictures, picture) + 1);
  749. }
  750. void SkPictureRecord::addDrawable(SkDrawable* drawable) {
  751. // follow the convention of recording a 1-based index
  752. this->addInt(find_or_append(fDrawables, drawable) + 1);
  753. }
  754. void SkPictureRecord::addPoint(const SkPoint& point) {
  755. fWriter.writePoint(point);
  756. }
  757. void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
  758. fWriter.writeMul4(pts, count * sizeof(SkPoint));
  759. }
  760. void SkPictureRecord::addNoOp() {
  761. size_t size = kUInt32Size; // op
  762. this->addDraw(NOOP, &size);
  763. }
  764. void SkPictureRecord::addRect(const SkRect& rect) {
  765. fWriter.writeRect(rect);
  766. }
  767. void SkPictureRecord::addRectPtr(const SkRect* rect) {
  768. if (fWriter.writeBool(rect != nullptr)) {
  769. fWriter.writeRect(*rect);
  770. }
  771. }
  772. void SkPictureRecord::addIRect(const SkIRect& rect) {
  773. fWriter.write(&rect, sizeof(rect));
  774. }
  775. void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
  776. if (fWriter.writeBool(rect != nullptr)) {
  777. *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
  778. }
  779. }
  780. void SkPictureRecord::addRRect(const SkRRect& rrect) {
  781. fWriter.writeRRect(rrect);
  782. }
  783. void SkPictureRecord::addRegion(const SkRegion& region) {
  784. fWriter.writeRegion(region);
  785. }
  786. void SkPictureRecord::addText(const void* text, size_t byteLength) {
  787. addInt(SkToInt(byteLength));
  788. fWriter.writePad(text, byteLength);
  789. }
  790. void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
  791. // follow the convention of recording a 1-based index
  792. this->addInt(find_or_append(fTextBlobs, blob) + 1);
  793. }
  794. void SkPictureRecord::addVertices(const SkVertices* vertices) {
  795. // follow the convention of recording a 1-based index
  796. this->addInt(find_or_append(fVertices, vertices) + 1);
  797. }
  798. ///////////////////////////////////////////////////////////////////////////////