Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: src/core/SkPictureRecord.cpp

Issue 617953002: Strip old backend recording down to essentials (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: debug-only Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkPictureRecord.h ('k') | src/core/SkPictureRecorder.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPictureRecord.h" 8 #include "SkPictureRecord.h"
9 #include "SkBBoxHierarchy.h"
10 #include "SkDevice.h" 9 #include "SkDevice.h"
11 #include "SkPatchUtils.h" 10 #include "SkPatchUtils.h"
12 #include "SkPictureStateTree.h"
13 #include "SkPixelRef.h" 11 #include "SkPixelRef.h"
14 #include "SkRRect.h" 12 #include "SkRRect.h"
15 #include "SkTextBlob.h" 13 #include "SkTextBlob.h"
16 #include "SkTSearch.h" 14 #include "SkTSearch.h"
17 15
18 #define HEAP_BLOCK_SIZE 4096 16 #define HEAP_BLOCK_SIZE 4096
19 17
20 // If SK_RECORD_LITERAL_PICTURES is defined, record our inputs as literally as p ossible.
21 // Otherwise, we can be clever and record faster equivalents. kBeClever is norm ally true.
22 static const bool kBeClever =
23 #ifdef SK_RECORD_LITERAL_PICTURES
24 false;
25 #else
26 true;
27 #endif
28
29 enum { 18 enum {
30 // just need a value that save or getSaveCount would never return 19 // just need a value that save or getSaveCount would never return
31 kNoInitialSave = -1, 20 kNoInitialSave = -1,
32 }; 21 };
33 22
34 // A lot of basic types get stored as a uint32_t: bools, ints, paint indices, et c. 23 // A lot of basic types get stored as a uint32_t: bools, ints, paint indices, et c.
35 static int const kUInt32Size = 4; 24 static int const kUInt32Size = 4;
36 25
37 static const uint32_t kSaveSize = kUInt32Size; 26 static const uint32_t kSaveSize = kUInt32Size;
38 static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size; 27 static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
39 static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect ); 28 static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect );
40 29
41 SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags) 30 SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
42 : INHERITED(dimensions.width(), dimensions.height()) 31 : INHERITED(dimensions.width(), dimensions.height())
43 , fBoundingHierarchy(NULL)
44 , fStateTree(NULL)
45 , fFlattenableHeap(HEAP_BLOCK_SIZE) 32 , fFlattenableHeap(HEAP_BLOCK_SIZE)
46 , fPaints(&fFlattenableHeap) 33 , fPaints(&fFlattenableHeap)
47 , fRecordFlags(flags) 34 , fRecordFlags(flags) {
48 , fOptsEnabled(kBeClever) {
49 35
50 fBitmapHeap = SkNEW(SkBitmapHeap); 36 fBitmapHeap = SkNEW(SkBitmapHeap);
51 fFlattenableHeap.setBitmapStorage(fBitmapHeap); 37 fFlattenableHeap.setBitmapStorage(fBitmapHeap);
52 38
53 fFirstSavedLayerIndex = kNoSavedLayerIndex; 39 fFirstSavedLayerIndex = kNoSavedLayerIndex;
54 fInitialSaveCount = kNoInitialSave; 40 fInitialSaveCount = kNoInitialSave;
55 } 41 }
56 42
57 SkPictureRecord::~SkPictureRecord() { 43 SkPictureRecord::~SkPictureRecord() {
58 SkSafeUnref(fBitmapHeap); 44 SkSafeUnref(fBitmapHeap);
59 SkSafeUnref(fBoundingHierarchy);
60 SkSafeUnref(fStateTree);
61 fFlattenableHeap.setBitmapStorage(NULL); 45 fFlattenableHeap.setBitmapStorage(NULL);
62 fPictureRefs.unrefAll(); 46 fPictureRefs.unrefAll();
63 fTextBlobRefs.unrefAll(); 47 fTextBlobRefs.unrefAll();
64 } 48 }
65 49
66 /////////////////////////////////////////////////////////////////////////////// 50 ///////////////////////////////////////////////////////////////////////////////
67 51
68 // Return the offset of the paint inside a given op's byte stream. A zero 52 // Return the offset of the paint inside a given op's byte stream. A zero
69 // return value means there is no paint (and you really shouldn't be calling 53 // return value means there is no paint (and you really shouldn't be calling
70 // this method) 54 // this method)
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 this->addPaintPtr(paint); 188 this->addPaintPtr(paint);
205 this->addInt(flags); 189 this->addInt(flags);
206 190
207 this->validate(initialOffset, size); 191 this->validate(initialOffset, size);
208 } 192 }
209 193
210 bool SkPictureRecord::isDrawingToLayer() const { 194 bool SkPictureRecord::isDrawingToLayer() const {
211 return fFirstSavedLayerIndex != kNoSavedLayerIndex; 195 return fFirstSavedLayerIndex != kNoSavedLayerIndex;
212 } 196 }
213 197
214 /*
215 * Read the op code from 'offset' in 'writer'.
216 */
217 #ifdef SK_DEBUG 198 #ifdef SK_DEBUG
218 static DrawType peek_op(SkWriter32* writer, size_t offset) {
219 return (DrawType)(writer->readTAt<uint32_t>(offset) >> 24);
220 }
221 #endif
222
223 /* 199 /*
224 * Read the op code from 'offset' in 'writer' and extract the size too. 200 * Read the op code from 'offset' in 'writer' and extract the size too.
225 */ 201 */
226 static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* si ze) { 202 static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* si ze) {
227 uint32_t peek = writer->readTAt<uint32_t>(offset); 203 uint32_t peek = writer->readTAt<uint32_t>(offset);
228 204
229 uint32_t op; 205 uint32_t op;
230 UNPACK_8_24(peek, op, *size); 206 UNPACK_8_24(peek, op, *size);
231 if (MASK_24 == *size) { 207 if (MASK_24 == *size) {
232 // size required its own slot right after the op code 208 // size required its own slot right after the op code
233 *size = writer->readTAt<uint32_t>(offset + kUInt32Size); 209 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
234 } 210 }
235 return (DrawType) op; 211 return (DrawType) op;
236 } 212 }
237 213 #endif//SK_DEBUG
238 // Is the supplied paint simply a color?
239 static bool is_simple(const SkPaint& p) {
240 intptr_t orAccum = (intptr_t)p.getPathEffect() |
241 (intptr_t)p.getShader() |
242 (intptr_t)p.getXfermode() |
243 (intptr_t)p.getMaskFilter() |
244 (intptr_t)p.getColorFilter() |
245 (intptr_t)p.getRasterizer() |
246 (intptr_t)p.getLooper() |
247 (intptr_t)p.getImageFilter();
248 return 0 == orAccum;
249 }
250
251 // CommandInfos are fed to the 'match' method and filled in with command
252 // information.
253 struct CommandInfo {
254 DrawType fActualOp;
255 uint32_t fOffset;
256 uint32_t fSize;
257 };
258
259 /*
260 * Attempt to match the provided pattern of commands starting at 'offset'
261 * in the byte stream and stopping at the end of the stream. Upon success,
262 * return true with all the pattern information filled out in the result
263 * array (i.e., actual ops, offsets and sizes).
264 * Note this method skips any NOOPs seen in the stream
265 */
266 static bool match(SkWriter32* writer, uint32_t offset,
267 int* pattern, CommandInfo* result, int numCommands) {
268 SkASSERT(offset < writer->bytesWritten());
269
270 uint32_t curOffset = offset;
271 uint32_t curSize = 0;
272 int numMatched;
273 for (numMatched = 0; numMatched < numCommands && curOffset < writer->bytesWr itten(); ++numMatched) {
274 DrawType op = peek_op_and_size(writer, curOffset, &curSize);
275 while (NOOP == op) {
276 curOffset += curSize;
277 if (curOffset >= writer->bytesWritten()) {
278 return false;
279 }
280 op = peek_op_and_size(writer, curOffset, &curSize);
281 }
282
283 if (kDRAW_BITMAP_FLAVOR == pattern[numMatched]) {
284 if (DRAW_BITMAP != op && DRAW_BITMAP_MATRIX != op &&
285 DRAW_BITMAP_NINE != op && DRAW_BITMAP_RECT_TO_RECT != op) {
286 return false;
287 }
288 } else if (op != pattern[numMatched]) {
289 return false;
290 }
291
292 result[numMatched].fActualOp = op;
293 result[numMatched].fOffset = curOffset;
294 result[numMatched].fSize = curSize;
295
296 curOffset += curSize;
297 }
298
299 if (numMatched != numCommands) {
300 return false;
301 }
302
303 if (curOffset < writer->bytesWritten()) {
304 // Something else between the last command and the end of the stream
305 return false;
306 }
307
308 return true;
309 }
310
311 // temporarily here to make code review easier
312 static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
313 SkPaintDictionary* paintDict,
314 const CommandInfo& saveLayerInf o,
315 const CommandInfo& dbmInfo);
316
317 /*
318 * Restore has just been called (but not recorded), look back at the
319 * matching save* and see if we are in the configuration:
320 * SAVE_LAYER
321 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_REC T
322 * RESTORE
323 * where the saveLayer's color can be moved into the drawBitmap*'s paint
324 */
325 static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
326 SkPaintDictionary* paintDict) {
327 // back up to the save block
328 // TODO: add a stack to track save*/restore offsets rather than searching ba ckwards
329 while (offset > 0) {
330 offset = writer->readTAt<uint32_t>(offset);
331 }
332
333 int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ };
334 CommandInfo result[SK_ARRAY_COUNT(pattern)];
335
336 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) {
337 return false;
338 }
339
340 if (kSaveLayerWithBoundsSize == result[0].fSize) {
341 // The saveLayer's bound can offset where the dbm is drawn
342 return false;
343 }
344
345 return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
346 result[0], result[1]);
347 }
348
349 /*
350 * Convert the command code located at 'offset' to a NOOP. Leave the size
351 * field alone so the NOOP can be skipped later.
352 */
353 static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) {
354 uint32_t command = writer->readTAt<uint32_t>(offset);
355 writer->overwriteTAt(offset, (command & MASK_24) | (NOOP << 24));
356 }
357
358 /*
359 * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint.
360 * Return true on success; false otherwise.
361 */
362 static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
363 SkPaintDictionary* paintDict,
364 const CommandInfo& saveLayerInf o,
365 const CommandInfo& dbmInfo) {
366 SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp);
367 SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp ||
368 DRAW_BITMAP_MATRIX == dbmInfo.fActualOp ||
369 DRAW_BITMAP_NINE == dbmInfo.fActualOp ||
370 DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp);
371
372 size_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
373 size_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
374
375 // we have a match, now we need to get the paints involved
376 uint32_t dbmPaintId = writer->readTAt<uint32_t>(dbmInfo.fOffset + dbmPaintOf fset);
377 uint32_t saveLayerPaintId = writer->readTAt<uint32_t>(saveLayerInfo.fOffset + slPaintOffset);
378
379 if (0 == saveLayerPaintId) {
380 // In this case the saveLayer/restore isn't needed at all - just kill th e saveLayer
381 // and signal the caller (by returning true) to not add the RESTORE op
382 convert_command_to_noop(writer, saveLayerInfo.fOffset);
383 return true;
384 }
385
386 if (0 == dbmPaintId) {
387 // In this case just make the DBM* use the saveLayer's paint, kill the s aveLayer
388 // and signal the caller (by returning true) to not add the RESTORE op
389 convert_command_to_noop(writer, saveLayerInfo.fOffset);
390 writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, saveLayerPaintId) ;
391 return true;
392 }
393
394 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId) );
395 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) {
396 return false;
397 }
398
399 // For this optimization we only fold the saveLayer and drawBitmapRect
400 // together if the saveLayer's draw is simple (i.e., no fancy effects) and
401 // and the only difference in the colors is that the saveLayer's can have
402 // an alpha while the drawBitmapRect's is opaque.
403 // TODO: it should be possible to fold them together even if they both
404 // have different non-255 alphas
405 SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaqu e
406
407 SkAutoTDelete<SkPaint> dbmPaint(paintDict->unflatten(dbmPaintId));
408 if (NULL == dbmPaint.get() || dbmPaint->getColor() != layerColor || !is_simp le(*dbmPaint)) {
409 return false;
410 }
411
412 SkColor newColor = SkColorSetA(dbmPaint->getColor(),
413 SkColorGetA(saveLayerPaint->getColor()));
414 dbmPaint->setColor(newColor);
415
416 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint);
417 if (NULL == data) {
418 return false;
419 }
420
421 // kill the saveLayer and alter the DBMR2R's paint to be the modified one
422 convert_command_to_noop(writer, saveLayerInfo.fOffset);
423 writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, data->index());
424 return true;
425 }
426
427 /*
428 * Restore has just been called (but not recorded), look back at the
429 * matching save* and see if we are in the configuration:
430 * SAVE_LAYER (with NULL == bounds)
431 * SAVE
432 * CLIP_RECT
433 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R ECT
434 * RESTORE
435 * RESTORE
436 * where the saveLayer's color can be moved into the drawBitmap*'s paint
437 */
438 static bool remove_save_layer2(SkWriter32* writer, int32_t offset,
439 SkPaintDictionary* paintDict) {
440 // back up to the save block
441 // TODO: add a stack to track save*/restore offsets rather than searching ba ckwards
442 while (offset > 0) {
443 offset = writer->readTAt<uint32_t>(offset);
444 }
445
446 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ };
447 CommandInfo result[SK_ARRAY_COUNT(pattern)];
448
449 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) {
450 return false;
451 }
452
453 if (kSaveLayerWithBoundsSize == result[0].fSize) {
454 // The saveLayer's bound can offset where the dbm is drawn
455 return false;
456 }
457
458 return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
459 result[0], result[3]);
460 }
461
462 static bool is_drawing_op(DrawType op) {
463
464 // FIXME: yuck. convert to a lookup table?
465 return (op > CONCAT && op < ROTATE)
466 || DRAW_DRRECT == op
467 || DRAW_PATCH == op
468 || DRAW_PICTURE_MATRIX_PAINT == op
469 || DRAW_TEXT_BLOB == op;
470 }
471
472 /*
473 * Restore has just been called (but not recorded), so look back at the
474 * matching save(), and see if we can eliminate the pair of them, due to no
475 * intervening matrix/clip calls.
476 *
477 * If so, update the writer and return true, in which case we won't even record
478 * the restore() call. If we still need the restore(), return false.
479 */
480 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
481 SkPaintDictionary* paintDict) {
482 int32_t restoreOffset = (int32_t)writer->bytesWritten();
483
484 // back up to the save block
485 while (offset > 0) {
486 offset = writer->readTAt<uint32_t>(offset);
487 }
488
489 // now offset points to a save
490 offset = -offset;
491 uint32_t opSize;
492 DrawType op = peek_op_and_size(writer, offset, &opSize);
493 if (SAVE_LAYER == op) {
494 // not ready to cull these out yet (mrr)
495 return false;
496 }
497 SkASSERT(SAVE == op);
498 SkASSERT(kSaveSize == opSize);
499
500 // Walk forward until we get back to either a draw-verb (abort) or we hit
501 // our restore (success).
502 int32_t saveOffset = offset;
503
504 offset += opSize;
505 while (offset < restoreOffset) {
506 op = peek_op_and_size(writer, offset, &opSize);
507 if (is_drawing_op(op) || (SAVE_LAYER == op)) {
508 // drawing verb, abort
509 return false;
510 }
511 offset += opSize;
512 }
513
514 writer->rewindToOffset(saveOffset);
515 return true;
516 }
517
518 typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset,
519 SkPaintDictionary* paintDict);
520 enum PictureRecordOptType {
521 kRewind_OptType, // Optimization rewinds the command stream
522 kCollapseSaveLayer_OptType, // Optimization eliminates a save/restore pair
523 };
524
525 enum PictureRecordOptFlags {
526 kSkipIfBBoxHierarchy_Flag = 0x1, // Optimization should be skipped if the
527 // SkPicture has a bounding box hierarchy .
528 kRescindLastSave_Flag = 0x2,
529 kRescindLastSaveLayer_Flag = 0x4,
530 };
531
532 struct PictureRecordOpt {
533 PictureRecordOptProc fProc;
534 PictureRecordOptType fType;
535 unsigned fFlags;
536 };
537 /*
538 * A list of the optimizations that are tried upon seeing a restore
539 * TODO: add a real API for such optimizations
540 * Add the ability to fire optimizations on any op (not just RESTORE)
541 */
542 static const PictureRecordOpt gPictureRecordOpts[] = {
543 // 'collapse_save_clip_restore' is skipped if there is a BBoxHierarchy
544 // because it is redundant with the state traversal optimization in
545 // SkPictureStateTree, and applying the optimization introduces significant
546 // record time overhead because it requires rewinding contents that were
547 // recorded into the BBoxHierarchy.
548 { collapse_save_clip_restore, kRewind_OptType,
549 kSkipIfBBoxHierarchy_Flag|kResci ndLastSave_Flag },
550 { remove_save_layer1, kCollapseSaveLayer_OptType, kRescindLastSaveLa yer_Flag },
551 { remove_save_layer2, kCollapseSaveLayer_OptType, kRescindLastSaveLa yer_Flag }
552 };
553
554 // This is called after an optimization has been applied to the command stream
555 // in order to adjust the contents and state of the bounding box hierarchy and
556 // state tree to reflect the optimization.
557 static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTr ee* stateTree,
558 SkBBoxHierarchy* boundingHierarchy) {
559 switch (opt) {
560 case kCollapseSaveLayer_OptType:
561 if (stateTree) {
562 stateTree->saveCollapsed();
563 }
564 break;
565 case kRewind_OptType:
566 if (boundingHierarchy) {
567 boundingHierarchy->rewindInserts();
568 }
569 // Note: No need to touch the state tree for this to work correctly.
570 // Unused branches do not burden the playback, and pruning the tree
571 // would be O(N^2), so it is best to leave it alone.
572 break;
573 default:
574 SkASSERT(0);
575 }
576 }
577 214
578 void SkPictureRecord::willRestore() { 215 void SkPictureRecord::willRestore() {
579 // FIXME: SkDeferredCanvas needs to be refactored to respect 216 // FIXME: SkDeferredCanvas needs to be refactored to respect
580 // save/restore balancing so that the following test can be 217 // save/restore balancing so that the following test can be
581 // turned on permanently. 218 // turned on permanently.
582 #if 0 219 #if 0
583 SkASSERT(fRestoreOffsetStack.count() > 1); 220 SkASSERT(fRestoreOffsetStack.count() > 1);
584 #endif 221 #endif
585 222
586 // check for underflow 223 // check for underflow
587 if (fRestoreOffsetStack.count() == 0) { 224 if (fRestoreOffsetStack.count() == 0) {
588 return; 225 return;
589 } 226 }
590 227
591 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) { 228 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
592 fFirstSavedLayerIndex = kNoSavedLayerIndex; 229 fFirstSavedLayerIndex = kNoSavedLayerIndex;
593 } 230 }
594 231
595 size_t opt = 0; 232 this->recordRestore();
596 if (fOptsEnabled) {
597 for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) {
598 if (0 != (gPictureRecordOpts[opt].fFlags & kSkipIfBBoxHierarchy_Flag )
599 && fBoundingHierarchy) {
600 continue;
601 }
602 if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.t op(), &fPaints)) {
603 // Some optimization fired so don't add the RESTORE
604 apply_optimization_to_bbh(gPictureRecordOpts[opt].fType,
605 fStateTree, fBoundingHierarchy);
606 if (gPictureRecordOpts[opt].fFlags & kRescindLastSave_Flag) {
607 fContentInfo.rescindLastSave();
608 } else if (gPictureRecordOpts[opt].fFlags & kRescindLastSaveLaye r_Flag) {
609 fContentInfo.rescindLastSaveLayer();
610 }
611 break;
612 }
613 }
614 }
615
616 if (!fOptsEnabled || SK_ARRAY_COUNT(gPictureRecordOpts) == opt) {
617 // No optimization fired so add the RESTORE
618 this->recordRestore();
619 }
620 233
621 fRestoreOffsetStack.pop(); 234 fRestoreOffsetStack.pop();
622 235
623 this->INHERITED::willRestore(); 236 this->INHERITED::willRestore();
624 } 237 }
625 238
626 void SkPictureRecord::recordRestore(bool fillInSkips) { 239 void SkPictureRecord::recordRestore(bool fillInSkips) {
627 fContentInfo.onRestore(); 240 fContentInfo.onRestore();
628 241
629 if (fillInSkips) { 242 if (fillInSkips) {
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 // op + paint index + rect 511 // op + paint index + rect
899 size_t size = 2 * kUInt32Size + sizeof(rect); 512 size_t size = 2 * kUInt32Size + sizeof(rect);
900 size_t initialOffset = this->addDraw(DRAW_RECT, &size); 513 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
901 SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.bytesWritt en()); 514 SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.bytesWritt en());
902 this->addPaint(paint); 515 this->addPaint(paint);
903 this->addRect(rect); 516 this->addRect(rect);
904 this->validate(initialOffset, size); 517 this->validate(initialOffset, size);
905 } 518 }
906 519
907 void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 520 void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
908 if (rrect.isRect() && kBeClever) { 521 // op + paint index + rrect
909 this->SkPictureRecord::drawRect(rrect.getBounds(), paint); 522 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
910 } else if (rrect.isOval() && kBeClever) { 523 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
911 this->SkPictureRecord::drawOval(rrect.getBounds(), paint); 524 SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytesWrit ten());
912 } else { 525 this->addPaint(paint);
913 // op + paint index + rrect 526 this->addRRect(rrect);
914 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory; 527 this->validate(initialOffset, size);
915 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
916 SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytes Written());
917 this->addPaint(paint);
918 this->addRRect(rrect);
919 this->validate(initialOffset, size);
920 }
921 } 528 }
922 529
923 void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 530 void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
924 const SkPaint& paint) { 531 const SkPaint& paint) {
925 // op + paint index + rrects 532 // op + paint index + rrects
926 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2; 533 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
927 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size); 534 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
928 SkASSERT(initialOffset+getPaintOffset(DRAW_DRRECT, size) == fWriter.bytesWri tten()); 535 SkASSERT(initialOffset+getPaintOffset(DRAW_DRRECT, size) == fWriter.bytesWri tten());
929 this->addPaint(paint); 536 this->addPaint(paint);
930 this->addRRect(outer); 537 this->addRRect(outer);
931 this->addRRect(inner); 538 this->addRRect(inner);
932 this->validate(initialOffset, size); 539 this->validate(initialOffset, size);
933 } 540 }
934 541
935 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) { 542 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
936 fContentInfo.onDrawPath(path, paint); 543 fContentInfo.onDrawPath(path, paint);
937 544
938 // op + paint index + path index 545 // op + paint index + path index
939 size_t size = 3 * kUInt32Size; 546 size_t size = 3 * kUInt32Size;
940 size_t initialOffset = this->addDraw(DRAW_PATH, &size); 547 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
941 SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.bytesWritt en()); 548 SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.bytesWritt en());
942 this->addPaint(paint); 549 this->addPaint(paint);
943 this->addPath(path); 550 this->addPath(path);
944 this->validate(initialOffset, size); 551 this->validate(initialOffset, size);
945 } 552 }
946 553
947 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, 554 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
948 const SkPaint* paint = NULL) { 555 const SkPaint* paint = NULL) {
949 if (bitmap.drawsNothing() && kBeClever) {
950 return;
951 }
952
953 // op + paint index + bitmap index + left + top 556 // op + paint index + bitmap index + left + top
954 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); 557 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
955 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size); 558 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
956 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.bytesWri tten()); 559 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.bytesWri tten());
957 this->addPaintPtr(paint); 560 this->addPaintPtr(paint);
958 this->addBitmap(bitmap); 561 this->addBitmap(bitmap);
959 this->addScalar(left); 562 this->addScalar(left);
960 this->addScalar(top); 563 this->addScalar(top);
961 this->validate(initialOffset, size); 564 this->validate(initialOffset, size);
962 } 565 }
963 566
964 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 567 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
965 const SkRect& dst, const SkPaint* pai nt, 568 const SkRect& dst, const SkPaint* pai nt,
966 DrawBitmapRectFlags flags) { 569 DrawBitmapRectFlags flags) {
967 if (bitmap.drawsNothing() && kBeClever) {
968 return;
969 }
970
971 // id + paint index + bitmap index + bool for 'src' + flags 570 // id + paint index + bitmap index + bool for 'src' + flags
972 size_t size = 5 * kUInt32Size; 571 size_t size = 5 * kUInt32Size;
973 if (src) { 572 if (src) {
974 size += sizeof(*src); // + rect 573 size += sizeof(*src); // + rect
975 } 574 }
976 size += sizeof(dst); // + rect 575 size += sizeof(dst); // + rect
977 576
978 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size); 577 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
979 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size) 578 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size)
980 == fWriter.bytesWritten()); 579 == fWriter.bytesWritten());
981 this->addPaintPtr(paint); 580 this->addPaintPtr(paint);
982 this->addBitmap(bitmap); 581 this->addBitmap(bitmap);
983 this->addRectPtr(src); // may be null 582 this->addRectPtr(src); // may be null
984 this->addRect(dst); 583 this->addRect(dst);
985 this->addInt(flags); 584 this->addInt(flags);
986 this->validate(initialOffset, size); 585 this->validate(initialOffset, size);
987 } 586 }
988 587
989 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m atrix, 588 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m atrix,
990 const SkPaint* paint) { 589 const SkPaint* paint) {
991 if (bitmap.drawsNothing() && kBeClever) {
992 return;
993 }
994
995 // id + paint index + bitmap index + matrix 590 // id + paint index + bitmap index + matrix
996 size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL); 591 size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
997 size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size); 592 size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
998 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.b ytesWritten()); 593 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.b ytesWritten());
999 this->addPaintPtr(paint); 594 this->addPaintPtr(paint);
1000 this->addBitmap(bitmap); 595 this->addBitmap(bitmap);
1001 this->addMatrix(matrix); 596 this->addMatrix(matrix);
1002 this->validate(initialOffset, size); 597 this->validate(initialOffset, size);
1003 } 598 }
1004 599
1005 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& cent er, 600 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& cent er,
1006 const SkRect& dst, const SkPaint* paint) { 601 const SkRect& dst, const SkPaint* paint) {
1007 if (bitmap.drawsNothing() && kBeClever) {
1008 return;
1009 }
1010
1011 // op + paint index + bitmap id + center + dst rect 602 // op + paint index + bitmap id + center + dst rect
1012 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst); 603 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
1013 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size); 604 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
1014 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.byt esWritten()); 605 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.byt esWritten());
1015 this->addPaintPtr(paint); 606 this->addPaintPtr(paint);
1016 this->addBitmap(bitmap); 607 this->addBitmap(bitmap);
1017 this->addIRect(center); 608 this->addIRect(center);
1018 this->addRect(dst); 609 this->addRect(dst);
1019 this->validate(initialOffset, size); 610 this->validate(initialOffset, size);
1020 } 611 }
1021 612
1022 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top, 613 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
1023 const SkPaint* paint = NULL) { 614 const SkPaint* paint = NULL) {
1024 if (bitmap.drawsNothing() && kBeClever) {
1025 return;
1026 }
1027
1028 // op + paint index + bitmap index + left + top 615 // op + paint index + bitmap index + left + top
1029 size_t size = 5 * kUInt32Size; 616 size_t size = 5 * kUInt32Size;
1030 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size); 617 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
1031 SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.bytesWri tten()); 618 SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.bytesWri tten());
1032 this->addPaintPtr(paint); 619 this->addPaintPtr(paint);
1033 this->addBitmap(bitmap); 620 this->addBitmap(bitmap);
1034 this->addInt(left); 621 this->addInt(left);
1035 this->addInt(top); 622 this->addInt(top);
1036 this->validate(initialOffset, size); 623 this->validate(initialOffset, size);
1037 } 624 }
1038 625
1039 void SkPictureRecord::ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]) {
1040 SkPaint::FontMetrics metrics;
1041 paint.getFontMetrics(&metrics);
1042 SkRect bounds;
1043 // construct a rect so we can see any adjustments from the paint.
1044 // we use 0,1 for left,right, just so the rect isn't empty
1045 bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom);
1046 (void)paint.computeFastBounds(bounds, &bounds);
1047 topbot[0] = bounds.fTop;
1048 topbot[1] = bounds.fBottom;
1049 }
1050
1051 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlat Data& flat,
1052 SkScalar minY, SkScalar maxY) {
1053 WriteTopBot(paint, flat);
1054 this->addScalar(flat.topBot()[0] + minY);
1055 this->addScalar(flat.topBot()[1] + maxY);
1056 }
1057
1058 void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x , SkScalar y, 626 void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x , SkScalar y,
1059 const SkPaint& paint) { 627 const SkPaint& paint) {
1060 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeCl ever;
1061
1062 // op + paint index + length + 'length' worth of chars + x + y 628 // op + paint index + length + 'length' worth of chars + x + y
1063 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar); 629 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
1064 if (fast) {
1065 size += 2 * sizeof(SkScalar); // + top & bottom
1066 }
1067 630
1068 DrawType op = fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT; 631 DrawType op = DRAW_TEXT;
1069 size_t initialOffset = this->addDraw(op, &size); 632 size_t initialOffset = this->addDraw(op, &size);
1070 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten()); 633 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
1071 const SkFlatData* flatPaintData = addPaint(paint); 634 this->addPaint(paint);
1072 SkASSERT(flatPaintData);
1073 this->addText(text, byteLength); 635 this->addText(text, byteLength);
1074 this->addScalar(x); 636 this->addScalar(x);
1075 this->addScalar(y); 637 this->addScalar(y);
1076 if (fast) {
1077 this->addFontMetricsTopBottom(paint, *flatPaintData, y, y);
1078 }
1079 this->validate(initialOffset, size); 638 this->validate(initialOffset, size);
1080 } 639 }
1081 640
1082 void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const S kPoint pos[], 641 void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const S kPoint pos[],
1083 const SkPaint& paint) { 642 const SkPaint& paint) {
1084 int points = paint.countText(text, byteLength); 643 int points = paint.countText(text, byteLength);
1085 if (0 == points)
1086 return;
1087 644
1088 bool canUseDrawH = true; 645 // op + paint index + length + 'length' worth of data + num points + x&y poi nt data
1089 SkScalar minY = pos[0].fY; 646 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
1090 SkScalar maxY = pos[0].fY;
1091 // check if the caller really should have used drawPosTextH()
1092 {
1093 const SkScalar firstY = pos[0].fY;
1094 for (int index = 1; index < points; index++) {
1095 if (pos[index].fY != firstY) {
1096 canUseDrawH = false;
1097 if (pos[index].fY < minY) {
1098 minY = pos[index].fY;
1099 } else if (pos[index].fY > maxY) {
1100 maxY = pos[index].fY;
1101 }
1102 }
1103 }
1104 }
1105 647
1106 bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever; 648 DrawType op = DRAW_POS_TEXT;
1107 bool fast = canUseDrawH && fastBounds && kBeClever;
1108 649
1109 // op + paint index + length + 'length' worth of data + num points
1110 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
1111 if (canUseDrawH) {
1112 if (fast) {
1113 size += 2 * sizeof(SkScalar); // + top & bottom
1114 }
1115 // + y-pos + actual x-point data
1116 size += sizeof(SkScalar) + points * sizeof(SkScalar);
1117 } else {
1118 // + x&y point data
1119 size += points * sizeof(SkPoint);
1120 if (fastBounds) {
1121 size += 2 * sizeof(SkScalar); // + top & bottom
1122 }
1123 }
1124
1125 DrawType op;
1126 if (fast) {
1127 op = DRAW_POS_TEXT_H_TOP_BOTTOM;
1128 } else if (canUseDrawH) {
1129 op = DRAW_POS_TEXT_H;
1130 } else if (fastBounds) {
1131 op = DRAW_POS_TEXT_TOP_BOTTOM;
1132 } else {
1133 op = DRAW_POS_TEXT;
1134 }
1135 size_t initialOffset = this->addDraw(op, &size); 650 size_t initialOffset = this->addDraw(op, &size);
1136 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten()); 651 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
1137 const SkFlatData* flatPaintData = this->addPaint(paint); 652 this->addPaint(paint);
1138 SkASSERT(flatPaintData);
1139 this->addText(text, byteLength); 653 this->addText(text, byteLength);
1140 this->addInt(points); 654 this->addInt(points);
1141 655 fWriter.writeMul4(pos, points * sizeof(SkPoint));
1142 if (canUseDrawH) {
1143 if (fast) {
1144 this->addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[ 0].fY);
1145 }
1146 this->addScalar(pos[0].fY);
1147 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
1148 for (int index = 0; index < points; index++)
1149 *xptr++ = pos[index].fX;
1150 } else {
1151 fWriter.writeMul4(pos, points * sizeof(SkPoint));
1152 if (fastBounds) {
1153 this->addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY);
1154 }
1155 }
1156 this->validate(initialOffset, size); 656 this->validate(initialOffset, size);
1157 } 657 }
1158 658
1159 void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 659 void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
1160 SkScalar constY, const SkPaint& paint) { 660 SkScalar constY, const SkPaint& paint) {
1161 const SkFlatData* flatPaintData = this->getFlatPaintData(paint);
1162 this->drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData) ;
1163 }
1164
1165 void SkPictureRecord::drawPosTextHImpl(const void* text, size_t byteLength,
1166 const SkScalar xpos[], SkScalar constY,
1167 const SkPaint& paint, const SkFlatData* flatPaintData) {
1168 int points = paint.countText(text, byteLength); 661 int points = paint.countText(text, byteLength);
1169 if (0 == points && kBeClever) {
1170 return;
1171 }
1172
1173 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeCl ever;
1174 662
1175 // op + paint index + length + 'length' worth of data + num points 663 // op + paint index + length + 'length' worth of data + num points
1176 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size; 664 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
1177 if (fast) {
1178 size += 2 * sizeof(SkScalar); // + top & bottom
1179 }
1180 // + y + the actual points 665 // + y + the actual points
1181 size += 1 * kUInt32Size + points * sizeof(SkScalar); 666 size += 1 * kUInt32Size + points * sizeof(SkScalar);
1182 size_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRA W_POS_TEXT_H,
1183 &size);
1184 SkASSERT(flatPaintData);
1185 this->addFlatPaint(flatPaintData);
1186 667
668 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
669 this->addPaint(paint);
1187 this->addText(text, byteLength); 670 this->addText(text, byteLength);
1188 this->addInt(points); 671 this->addInt(points);
1189
1190 if (fast) {
1191 this->addFontMetricsTopBottom(paint, *flatPaintData, constY, constY);
1192 }
1193 this->addScalar(constY); 672 this->addScalar(constY);
1194 fWriter.writeMul4(xpos, points * sizeof(SkScalar)); 673 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
1195 this->validate(initialOffset, size); 674 this->validate(initialOffset, size);
1196 } 675 }
1197 676
1198 void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, cons t SkPath& path, 677 void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, cons t SkPath& path,
1199 const SkMatrix* matrix, const SkPaint& pa int) { 678 const SkMatrix* matrix, const SkPaint& pa int) {
1200 // op + paint index + length + 'length' worth of data + path index + matrix 679 // op + paint index + length + 'length' worth of data + path index + matrix
1201 const SkMatrix& m = matrix ? *matrix : SkMatrix::I(); 680 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
1202 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.write ToMemory(NULL); 681 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.write ToMemory(NULL);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 flag |= DRAW_VERTICES_HAS_TEXS; 803 flag |= DRAW_VERTICES_HAS_TEXS;
1325 size += SkPatchUtils::kNumCorners * sizeof(SkPoint); 804 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
1326 } 805 }
1327 if (xmode) { 806 if (xmode) {
1328 SkXfermode::Mode mode; 807 SkXfermode::Mode mode;
1329 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) { 808 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
1330 flag |= DRAW_VERTICES_HAS_XFER; 809 flag |= DRAW_VERTICES_HAS_XFER;
1331 size += kUInt32Size; 810 size += kUInt32Size;
1332 } 811 }
1333 } 812 }
1334 813
1335 size_t initialOffset = this->addDraw(DRAW_PATCH, &size); 814 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
1336 SkASSERT(initialOffset+getPaintOffset(DRAW_PATCH, size) == fWriter.bytesWrit ten()); 815 SkASSERT(initialOffset+getPaintOffset(DRAW_PATCH, size) == fWriter.bytesWrit ten());
1337 this->addPaint(paint); 816 this->addPaint(paint);
1338 this->addPatch(cubics); 817 this->addPatch(cubics);
1339 this->addInt(flag); 818 this->addInt(flag);
1340 819
1341 // write optional parameters 820 // write optional parameters
1342 if (colors) { 821 if (colors) {
1343 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor)); 822 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
1344 } 823 }
1345 if (texCoords) { 824 if (texCoords) {
1346 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint)); 825 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
1347 } 826 }
1348 if (flag & DRAW_VERTICES_HAS_XFER) { 827 if (flag & DRAW_VERTICES_HAS_XFER) {
1349 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; 828 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
1350 xmode->asMode(&mode); 829 xmode->asMode(&mode);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 this->addInt(0); 881 this->addInt(0);
1403 this->validate(initialOffset, size); 882 this->validate(initialOffset, size);
1404 } 883 }
1405 884
1406 void SkPictureRecord::onPopCull() { 885 void SkPictureRecord::onPopCull() {
1407 SkASSERT(!fCullOffsetStack.isEmpty()); 886 SkASSERT(!fCullOffsetStack.isEmpty());
1408 887
1409 uint32_t cullSkipOffset = fCullOffsetStack.top(); 888 uint32_t cullSkipOffset = fCullOffsetStack.top();
1410 fCullOffsetStack.pop(); 889 fCullOffsetStack.pop();
1411 890
1412 // Collapse empty push/pop pairs.
1413 if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten() && kBeC lever) {
1414 SkASSERT(fWriter.bytesWritten() >= kPushCullOpSize);
1415 SkASSERT(PUSH_CULL == peek_op(&fWriter, fWriter.bytesWritten() - kPushCu llOpSize));
1416 fWriter.rewindToOffset(fWriter.bytesWritten() - kPushCullOpSize);
1417 return;
1418 }
1419
1420 // op only 891 // op only
1421 size_t size = kUInt32Size; 892 size_t size = kUInt32Size;
1422 size_t initialOffset = this->addDraw(POP_CULL, &size); 893 size_t initialOffset = this->addDraw(POP_CULL, &size);
1423 894
1424 // update the cull skip offset to point past this op. 895 // update the cull skip offset to point past this op.
1425 fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten( ))); 896 fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten( )));
1426 897
1427 this->validate(initialOffset, size); 898 this->validate(initialOffset, size);
1428 } 899 }
1429 900
(...skipping 10 matching lines...) Expand all
1440 // was a problem. 911 // was a problem.
1441 SkASSERT(index != SkBitmapHeap::INVALID_SLOT); 912 SkASSERT(index != SkBitmapHeap::INVALID_SLOT);
1442 this->addInt(index); 913 this->addInt(index);
1443 return index; 914 return index;
1444 } 915 }
1445 916
1446 void SkPictureRecord::addMatrix(const SkMatrix& matrix) { 917 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
1447 fWriter.writeMatrix(matrix); 918 fWriter.writeMatrix(matrix);
1448 } 919 }
1449 920
1450 const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) { 921 void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
1451 return fPaints.findAndReturnFlat(paint);
1452 }
1453
1454 const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
1455 fContentInfo.onAddPaintPtr(paint); 922 fContentInfo.onAddPaintPtr(paint);
1456 923
1457 const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL; 924 if (paint) {
1458 this->addFlatPaint(data); 925 const SkFlatData* flat = fPaints.findAndReturnFlat(*paint);
1459 return data; 926 SkASSERT(flat && flat->index() != 0);
1460 } 927 this->addInt(flat->index());
1461 928 } else {
1462 void SkPictureRecord::addFlatPaint(const SkFlatData* flatPaint) { 929 this->addInt(0);
1463 int index = flatPaint ? flatPaint->index() : 0; 930 }
1464 this->addInt(index);
1465 } 931 }
1466 932
1467 int SkPictureRecord::addPathToHeap(const SkPath& path) { 933 int SkPictureRecord::addPathToHeap(const SkPath& path) {
1468 if (NULL == fPathHeap) { 934 if (NULL == fPathHeap) {
1469 fPathHeap.reset(SkNEW(SkPathHeap)); 935 fPathHeap.reset(SkNEW(SkPathHeap));
1470 } 936 }
1471 #ifdef SK_DEDUP_PICTURE_PATHS 937 #ifdef SK_DEDUP_PICTURE_PATHS
1472 return fPathHeap->insert(path); 938 return fPathHeap->insert(path);
1473 #else 939 #else
1474 return fPathHeap->append(path); 940 return fPathHeap->append(path);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 void SkPictureRecord::addTextBlob(const SkTextBlob *blob) { 1010 void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
1545 int index = fTextBlobRefs.count(); 1011 int index = fTextBlobRefs.count();
1546 *fTextBlobRefs.append() = blob; 1012 *fTextBlobRefs.append() = blob;
1547 blob->ref(); 1013 blob->ref();
1548 // follow the convention of recording a 1-based index 1014 // follow the convention of recording a 1-based index
1549 this->addInt(index + 1); 1015 this->addInt(index + 1);
1550 } 1016 }
1551 1017
1552 /////////////////////////////////////////////////////////////////////////////// 1018 ///////////////////////////////////////////////////////////////////////////////
1553 1019
OLDNEW
« no previous file with comments | « src/core/SkPictureRecord.h ('k') | src/core/SkPictureRecorder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698