• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SkPictureRecord.h"
9 #include "SkTSearch.h"
10 #include "SkPixelRef.h"
11 #include "SkRRect.h"
12 #include "SkBBoxHierarchy.h"
13 #include "SkPictureStateTree.h"
14 
15 #define MIN_WRITER_SIZE 16384
16 #define HEAP_BLOCK_SIZE 4096
17 
18 enum {
19     // just need a value that save or getSaveCount would never return
20     kNoInitialSave = -1,
21 };
22 
SkPictureRecord(uint32_t flags,SkDevice * device)23 SkPictureRecord::SkPictureRecord(uint32_t flags, SkDevice* device) :
24         INHERITED(device),
25         fBoundingHierarchy(NULL),
26         fStateTree(NULL),
27         fFlattenableHeap(HEAP_BLOCK_SIZE),
28         fMatrices(&fFlattenableHeap),
29         fPaints(&fFlattenableHeap),
30         fRegions(&fFlattenableHeap),
31         fWriter(MIN_WRITER_SIZE),
32         fRecordFlags(flags) {
33 #ifdef SK_DEBUG_SIZE
34     fPointBytes = fRectBytes = fTextBytes = 0;
35     fPointWrites = fRectWrites = fTextWrites = 0;
36 #endif
37 
38     fRestoreOffsetStack.setReserve(32);
39 
40     fBitmapHeap = SkNEW(SkBitmapHeap);
41     fFlattenableHeap.setBitmapStorage(fBitmapHeap);
42     fPathHeap = NULL;   // lazy allocate
43     fFirstSavedLayerIndex = kNoSavedLayerIndex;
44 
45     fInitialSaveCount = kNoInitialSave;
46 }
47 
~SkPictureRecord()48 SkPictureRecord::~SkPictureRecord() {
49     SkSafeUnref(fBitmapHeap);
50     SkSafeUnref(fPathHeap);
51     SkSafeUnref(fBoundingHierarchy);
52     SkSafeUnref(fStateTree);
53     fFlattenableHeap.setBitmapStorage(NULL);
54     fPictureRefs.unrefAll();
55 }
56 
57 ///////////////////////////////////////////////////////////////////////////////
58 
setDevice(SkDevice * device)59 SkDevice* SkPictureRecord::setDevice(SkDevice* device) {
60     SkASSERT(!"eeek, don't try to change the device on a recording canvas");
61     return this->INHERITED::setDevice(device);
62 }
63 
save(SaveFlags flags)64 int SkPictureRecord::save(SaveFlags flags) {
65     // record the offset to us, making it non-positive to distinguish a save
66     // from a clip entry.
67     fRestoreOffsetStack.push(-(int32_t)fWriter.size());
68 
69     addDraw(SAVE);
70     addInt(flags);
71 
72     validate();
73     return this->INHERITED::save(flags);
74 }
75 
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)76 int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
77                                SaveFlags flags) {
78     // record the offset to us, making it non-positive to distinguish a save
79     // from a clip entry.
80     fRestoreOffsetStack.push(-(int32_t)fWriter.size());
81 
82     addDraw(SAVE_LAYER);
83     addRectPtr(bounds);
84     addPaintPtr(paint);
85     addInt(flags);
86 
87     if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
88         fFirstSavedLayerIndex = fRestoreOffsetStack.count();
89     }
90 
91     validate();
92     /*  Don't actually call saveLayer, because that will try to allocate an
93         offscreen device (potentially very big) which we don't actually need
94         at this time (and may not be able to afford since during record our
95         clip starts out the size of the picture, which is often much larger
96         than the size of the actual device we'll use during playback).
97      */
98     int count = this->INHERITED::save(flags);
99     this->clipRectBounds(bounds, flags, NULL);
100     return count;
101 }
102 
isDrawingToLayer() const103 bool SkPictureRecord::isDrawingToLayer() const {
104     return fFirstSavedLayerIndex != kNoSavedLayerIndex;
105 }
106 
107 // Return the size of the specified drawType's recorded block, or 0 if this verb
108 // is variable sized, and therefore not known.
getSkipableSize(unsigned drawType)109 static inline uint32_t getSkipableSize(unsigned drawType) {
110     static const uint8_t gSizes[LAST_DRAWTYPE_ENUM + 1] = {
111         0,  // UNUSED,
112         4,  // CLIP_PATH,
113         4,  // CLIP_REGION,
114         7,  // CLIP_RECT,
115         15, // CLIP_RRECT,
116         2,  // CONCAT,
117         0,  // DRAW_BITMAP,
118         0,  // DRAW_BITMAP_MATRIX,
119         0,  // DRAW_BITMAP_NINE,
120         0,  // DRAW_BITMAP_RECT,
121         0,  // DRAW_CLEAR,
122         0,  // DRAW_DATA,
123         0,  // DRAW_OVAL,
124         0,  // DRAW_PAINT,
125         0,  // DRAW_PATH,
126         0,  // DRAW_PICTURE,
127         0,  // DRAW_POINTS,
128         0,  // DRAW_POS_TEXT,
129         0,  // DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
130         0,  // DRAW_POS_TEXT_H,
131         0,  // DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
132         0,  // DRAW_RECT,
133         0,  // DRAW_RRECT,
134         0,  // DRAW_SPRITE,
135         0,  // DRAW_TEXT,
136         0,  // DRAW_TEXT_ON_PATH,
137         0,  // DRAW_TEXT_TOP_BOTTOM,   // fast variant of DRAW_TEXT
138         0,  // DRAW_VERTICES,
139         0,  // RESTORE,
140         2,  // ROTATE,
141         2,  // SAVE,
142         0,  // SAVE_LAYER,
143         3,  // SCALE,
144         2,  // SET_MATRIX,
145         3,  // SKEW,
146         3,  // TRANSLATE,
147     };
148 
149     SkASSERT(sizeof(gSizes) == LAST_DRAWTYPE_ENUM + 1);
150     SkASSERT((unsigned)drawType <= (unsigned)LAST_DRAWTYPE_ENUM);
151     return gSizes[drawType] * sizeof(uint32_t);
152 }
153 
154 #ifdef TRACK_COLLAPSE_STATS
155     static int gCollapseCount, gCollapseCalls;
156 #endif
157 
158 /*
159  *  Restore has just been called (but not recoreded), so look back at the
160  *  matching save(), and see if we can eliminate the pair of them, due to no
161  *  intervening matrix/clip calls.
162  *
163  *  If so, update the writer and return true, in which case we won't even record
164  *  the restore() call. If we still need the restore(), return false.
165  */
collapseSaveClipRestore(SkWriter32 * writer,int32_t offset)166 static bool collapseSaveClipRestore(SkWriter32* writer, int32_t offset) {
167 #ifdef TRACK_COLLAPSE_STATS
168     gCollapseCalls += 1;
169 #endif
170 
171     int32_t restoreOffset = (int32_t)writer->size();
172 
173     // back up to the save block
174     while (offset > 0) {
175         offset = *writer->peek32(offset);
176     }
177 
178     // now offset points to a save
179     offset = -offset;
180     if (SAVE_LAYER == *writer->peek32(offset)) {
181         // not ready to cull these out yet (mrr)
182         return false;
183     }
184     SkASSERT(SAVE == *writer->peek32(offset));
185 
186     // Walk forward until we get back to either a draw-verb (abort) or we hit
187     // our restore (success).
188     int32_t saveOffset = offset;
189 
190     offset += getSkipableSize(SAVE);
191     while (offset < restoreOffset) {
192         uint32_t* block = writer->peek32(offset);
193         uint32_t op = *block;
194         uint32_t opSize = getSkipableSize(op);
195         if (0 == opSize) {
196             // drawing verb, abort
197             return false;
198         }
199         offset += opSize;
200     }
201 
202 #ifdef TRACK_COLLAPSE_STATS
203     gCollapseCount += 1;
204     SkDebugf("Collapse [%d out of %d] %g%spn", gCollapseCount, gCollapseCalls,
205              (double)gCollapseCount / gCollapseCalls, "%");
206 #endif
207 
208     writer->rewindToOffset(saveOffset);
209     return true;
210 }
211 
restore()212 void SkPictureRecord::restore() {
213     // FIXME: SkDeferredCanvas needs to be refactored to respect
214     // save/restore balancing so that the following test can be
215     // turned on permanently.
216 #if 0
217     SkASSERT(fRestoreOffsetStack.count() > 1);
218 #endif
219 
220     // check for underflow
221     if (fRestoreOffsetStack.count() == 0) {
222         return;
223     }
224 
225     if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
226         fFirstSavedLayerIndex = kNoSavedLayerIndex;
227     }
228 
229     if (!collapseSaveClipRestore(&fWriter, fRestoreOffsetStack.top())) {
230         fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size());
231         this->addDraw(RESTORE);
232     }
233 
234     fRestoreOffsetStack.pop();
235 
236     validate();
237     return this->INHERITED::restore();
238 }
239 
translate(SkScalar dx,SkScalar dy)240 bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
241     addDraw(TRANSLATE);
242     addScalar(dx);
243     addScalar(dy);
244     validate();
245     return this->INHERITED::translate(dx, dy);
246 }
247 
scale(SkScalar sx,SkScalar sy)248 bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
249     addDraw(SCALE);
250     addScalar(sx);
251     addScalar(sy);
252     validate();
253     return this->INHERITED::scale(sx, sy);
254 }
255 
rotate(SkScalar degrees)256 bool SkPictureRecord::rotate(SkScalar degrees) {
257     addDraw(ROTATE);
258     addScalar(degrees);
259     validate();
260     return this->INHERITED::rotate(degrees);
261 }
262 
skew(SkScalar sx,SkScalar sy)263 bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
264     addDraw(SKEW);
265     addScalar(sx);
266     addScalar(sy);
267     validate();
268     return this->INHERITED::skew(sx, sy);
269 }
270 
concat(const SkMatrix & matrix)271 bool SkPictureRecord::concat(const SkMatrix& matrix) {
272     validate();
273     addDraw(CONCAT);
274     addMatrix(matrix);
275     validate();
276     return this->INHERITED::concat(matrix);
277 }
278 
setMatrix(const SkMatrix & matrix)279 void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
280     validate();
281     addDraw(SET_MATRIX);
282     addMatrix(matrix);
283     validate();
284     this->INHERITED::setMatrix(matrix);
285 }
286 
regionOpExpands(SkRegion::Op op)287 static bool regionOpExpands(SkRegion::Op op) {
288     switch (op) {
289         case SkRegion::kUnion_Op:
290         case SkRegion::kXOR_Op:
291         case SkRegion::kReverseDifference_Op:
292         case SkRegion::kReplace_Op:
293             return true;
294         case SkRegion::kIntersect_Op:
295         case SkRegion::kDifference_Op:
296             return false;
297         default:
298             SkDEBUGFAIL("unknown region op");
299             return false;
300     }
301 }
302 
fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset)303 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(
304     uint32_t restoreOffset) {
305     int32_t offset = fRestoreOffsetStack.top();
306     while (offset > 0) {
307         uint32_t* peek = fWriter.peek32(offset);
308         offset = *peek;
309         *peek = restoreOffset;
310     }
311 
312 #ifdef SK_DEBUG
313     // assert that the final offset value points to a save verb
314     uint32_t drawOp = *fWriter.peek32(-offset);
315     SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
316 #endif
317 }
318 
beginRecording()319 void SkPictureRecord::beginRecording() {
320     // we have to call this *after* our constructor, to ensure that it gets
321     // recorded. This is balanced by restoreToCount() call from endRecording,
322     // which in-turn calls our overridden restore(), so those get recorded too.
323     fInitialSaveCount = this->save(kMatrixClip_SaveFlag);
324 }
325 
endRecording()326 void SkPictureRecord::endRecording() {
327     SkASSERT(kNoInitialSave != fInitialSaveCount);
328     this->restoreToCount(fInitialSaveCount);
329 }
330 
recordRestoreOffsetPlaceholder(SkRegion::Op op)331 void SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
332     if (fRestoreOffsetStack.isEmpty()) {
333         return;
334     }
335 
336     if (regionOpExpands(op)) {
337         // Run back through any previous clip ops, and mark their offset to
338         // be 0, disabling their ability to trigger a jump-to-restore, otherwise
339         // they could hide this clips ability to expand the clip (i.e. go from
340         // empty to non-empty).
341         fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
342     }
343 
344     size_t offset = fWriter.size();
345     // The RestoreOffset field is initially filled with a placeholder
346     // value that points to the offset of the previous RestoreOffset
347     // in the current stack level, thus forming a linked list so that
348     // the restore offsets can be filled in when the corresponding
349     // restore command is recorded.
350     addInt(fRestoreOffsetStack.top());
351     fRestoreOffsetStack.top() = offset;
352 }
353 
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)354 bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
355     addDraw(CLIP_RECT);
356     addRect(rect);
357     addInt(ClipParams_pack(op, doAA));
358     recordRestoreOffsetPlaceholder(op);
359 
360     validate();
361     return this->INHERITED::clipRect(rect, op, doAA);
362 }
363 
clipRRect(const SkRRect & rrect,SkRegion::Op op,bool doAA)364 bool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
365     if (rrect.isRect()) {
366         return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA);
367     }
368 
369     addDraw(CLIP_RRECT);
370     addRRect(rrect);
371     addInt(ClipParams_pack(op, doAA));
372     recordRestoreOffsetPlaceholder(op);
373 
374     validate();
375 
376     if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
377         return this->INHERITED::clipRect(rrect.getBounds(), op, doAA);
378     } else {
379         return this->INHERITED::clipRRect(rrect, op, doAA);
380     }
381 }
382 
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)383 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
384 
385     SkRect r;
386     if (!path.isInverseFillType() && path.isRect(&r)) {
387         return this->clipRect(r, op, doAA);
388     }
389 
390     addDraw(CLIP_PATH);
391     addPath(path);
392     addInt(ClipParams_pack(op, doAA));
393     recordRestoreOffsetPlaceholder(op);
394 
395     validate();
396 
397     if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
398         return this->INHERITED::clipRect(path.getBounds(), op, doAA);
399     } else {
400         return this->INHERITED::clipPath(path, op, doAA);
401     }
402 }
403 
clipRegion(const SkRegion & region,SkRegion::Op op)404 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
405     addDraw(CLIP_REGION);
406     addRegion(region);
407     addInt(ClipParams_pack(op, false));
408     recordRestoreOffsetPlaceholder(op);
409 
410     validate();
411     return this->INHERITED::clipRegion(region, op);
412 }
413 
clear(SkColor color)414 void SkPictureRecord::clear(SkColor color) {
415     addDraw(DRAW_CLEAR);
416     addInt(color);
417     validate();
418 }
419 
drawPaint(const SkPaint & paint)420 void SkPictureRecord::drawPaint(const SkPaint& paint) {
421     addDraw(DRAW_PAINT);
422     addPaint(paint);
423     validate();
424 }
425 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)426 void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
427                         const SkPaint& paint) {
428     addDraw(DRAW_POINTS);
429     addPaint(paint);
430     addInt(mode);
431     addInt(count);
432     fWriter.writeMul4(pts, count * sizeof(SkPoint));
433     validate();
434 }
435 
drawOval(const SkRect & oval,const SkPaint & paint)436 void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
437     addDraw(DRAW_OVAL);
438     addPaint(paint);
439     addRect(oval);
440     validate();
441 }
442 
drawRect(const SkRect & rect,const SkPaint & paint)443 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
444     addDraw(DRAW_RECT);
445     addPaint(paint);
446     addRect(rect);
447     validate();
448 }
449 
drawRRect(const SkRRect & rrect,const SkPaint & paint)450 void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
451     if (rrect.isRect()) {
452         addDraw(DRAW_RECT);
453         addPaint(paint);
454         addRect(rrect.getBounds());
455     } else if (rrect.isOval()) {
456         addDraw(DRAW_OVAL);
457         addPaint(paint);
458         addRect(rrect.getBounds());
459     } else {
460         addDraw(DRAW_RRECT);
461         addPaint(paint);
462         addRRect(rrect);
463     }
464     validate();
465 }
466 
drawPath(const SkPath & path,const SkPaint & paint)467 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
468     addDraw(DRAW_PATH);
469     addPaint(paint);
470     addPath(path);
471     validate();
472 }
473 
drawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint=NULL)474 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
475                         const SkPaint* paint = NULL) {
476     addDraw(DRAW_BITMAP);
477     addPaintPtr(paint);
478     addBitmap(bitmap);
479     addScalar(left);
480     addScalar(top);
481     validate();
482 }
483 
drawBitmapRectToRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint)484 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
485                             const SkRect& dst, const SkPaint* paint) {
486     addDraw(DRAW_BITMAP_RECT_TO_RECT);
487     addPaintPtr(paint);
488     addBitmap(bitmap);
489     addRectPtr(src);  // may be null
490     addRect(dst);
491     validate();
492 }
493 
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)494 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
495                                        const SkPaint* paint) {
496     addDraw(DRAW_BITMAP_MATRIX);
497     addPaintPtr(paint);
498     addBitmap(bitmap);
499     addMatrix(matrix);
500     validate();
501 }
502 
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)503 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
504                                      const SkRect& dst, const SkPaint* paint) {
505     addDraw(DRAW_BITMAP_NINE);
506     addPaintPtr(paint);
507     addBitmap(bitmap);
508     addIRect(center);
509     addRect(dst);
510     validate();
511 }
512 
drawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint=NULL)513 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
514                         const SkPaint* paint = NULL) {
515     addDraw(DRAW_SPRITE);
516     addPaintPtr(paint);
517     addBitmap(bitmap);
518     addInt(left);
519     addInt(top);
520     validate();
521 }
522 
523 // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been
524 // tweaked by paint.computeFastBounds().
525 //
computeFontMetricsTopBottom(const SkPaint & paint,SkScalar topbot[2])526 static void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]) {
527     SkPaint::FontMetrics metrics;
528     paint.getFontMetrics(&metrics);
529     SkRect bounds;
530     // construct a rect so we can see any adjustments from the paint.
531     // we use 0,1 for left,right, just so the rect isn't empty
532     bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom);
533     (void)paint.computeFastBounds(bounds, &bounds);
534     topbot[0] = bounds.fTop;
535     topbot[1] = bounds.fBottom;
536 }
537 
addFontMetricsTopBottom(const SkPaint & paint,const SkFlatData & flat,SkScalar minY,SkScalar maxY)538 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData& flat,
539                                               SkScalar minY, SkScalar maxY) {
540     if (!flat.isTopBotWritten()) {
541         computeFontMetricsTopBottom(paint, flat.writableTopBot());
542         SkASSERT(flat.isTopBotWritten());
543     }
544     addScalar(flat.topBot()[0] + minY);
545     addScalar(flat.topBot()[1] + maxY);
546 }
547 
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)548 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
549                       SkScalar y, const SkPaint& paint) {
550     bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
551 
552     addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
553     const SkFlatData* flatPaintData = addPaint(paint);
554     SkASSERT(flatPaintData);
555     addText(text, byteLength);
556     addScalar(x);
557     addScalar(y);
558     if (fast) {
559         addFontMetricsTopBottom(paint, *flatPaintData, y, y);
560     }
561     validate();
562 }
563 
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)564 void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
565                          const SkPoint pos[], const SkPaint& paint) {
566     size_t points = paint.countText(text, byteLength);
567     if (0 == points)
568         return;
569 
570     bool canUseDrawH = true;
571     SkScalar minY = pos[0].fY;
572     SkScalar maxY = pos[0].fY;
573     // check if the caller really should have used drawPosTextH()
574     {
575         const SkScalar firstY = pos[0].fY;
576         for (size_t index = 1; index < points; index++) {
577             if (pos[index].fY != firstY) {
578                 canUseDrawH = false;
579                 if (pos[index].fY < minY) {
580                     minY = pos[index].fY;
581                 } else if (pos[index].fY > maxY) {
582                     maxY = pos[index].fY;
583                 }
584             }
585         }
586     }
587 
588     bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
589     bool fast = canUseDrawH && fastBounds;
590 
591     if (fast) {
592         addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
593     } else if (canUseDrawH) {
594         addDraw(DRAW_POS_TEXT_H);
595     } else if (fastBounds) {
596         addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
597     } else {
598         addDraw(DRAW_POS_TEXT);
599     }
600     const SkFlatData* flatPaintData = addPaint(paint);
601     SkASSERT(flatPaintData);
602     addText(text, byteLength);
603     addInt(points);
604 
605 #ifdef SK_DEBUG_SIZE
606     size_t start = fWriter.size();
607 #endif
608     if (canUseDrawH) {
609         if (fast) {
610             addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY);
611         }
612         addScalar(pos[0].fY);
613         SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
614         for (size_t index = 0; index < points; index++)
615             *xptr++ = pos[index].fX;
616     }
617     else {
618         fWriter.writeMul4(pos, points * sizeof(SkPoint));
619         if (fastBounds) {
620             addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY);
621         }
622     }
623 #ifdef SK_DEBUG_SIZE
624     fPointBytes += fWriter.size() - start;
625     fPointWrites += points;
626 #endif
627     validate();
628 }
629 
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)630 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
631                           const SkScalar xpos[], SkScalar constY,
632                           const SkPaint& paint) {
633     size_t points = paint.countText(text, byteLength);
634     if (0 == points)
635         return;
636 
637     bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
638 
639     addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
640     const SkFlatData* flatPaintData = addPaint(paint);
641     SkASSERT(flatPaintData);
642     addText(text, byteLength);
643     addInt(points);
644 
645 #ifdef SK_DEBUG_SIZE
646     size_t start = fWriter.size();
647 #endif
648     if (fast) {
649         addFontMetricsTopBottom(paint, *flatPaintData, constY, constY);
650     }
651     addScalar(constY);
652     fWriter.writeMul4(xpos, points * sizeof(SkScalar));
653 #ifdef SK_DEBUG_SIZE
654     fPointBytes += fWriter.size() - start;
655     fPointWrites += points;
656 #endif
657     validate();
658 }
659 
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)660 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
661                             const SkPath& path, const SkMatrix* matrix,
662                             const SkPaint& paint) {
663     addDraw(DRAW_TEXT_ON_PATH);
664     addPaint(paint);
665     addText(text, byteLength);
666     addPath(path);
667     addMatrixPtr(matrix);
668     validate();
669 }
670 
drawPicture(SkPicture & picture)671 void SkPictureRecord::drawPicture(SkPicture& picture) {
672     addDraw(DRAW_PICTURE);
673     addPicture(picture);
674     validate();
675 }
676 
drawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode *,const uint16_t indices[],int indexCount,const SkPaint & paint)677 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
678                           const SkPoint vertices[], const SkPoint texs[],
679                           const SkColor colors[], SkXfermode*,
680                           const uint16_t indices[], int indexCount,
681                           const SkPaint& paint) {
682     uint32_t flags = 0;
683     if (texs) {
684         flags |= DRAW_VERTICES_HAS_TEXS;
685     }
686     if (colors) {
687         flags |= DRAW_VERTICES_HAS_COLORS;
688     }
689     if (indexCount > 0) {
690         flags |= DRAW_VERTICES_HAS_INDICES;
691     }
692 
693     addDraw(DRAW_VERTICES);
694     addPaint(paint);
695     addInt(flags);
696     addInt(vmode);
697     addInt(vertexCount);
698     addPoints(vertices, vertexCount);
699     if (flags & DRAW_VERTICES_HAS_TEXS) {
700         addPoints(texs, vertexCount);
701     }
702     if (flags & DRAW_VERTICES_HAS_COLORS) {
703         fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
704     }
705     if (flags & DRAW_VERTICES_HAS_INDICES) {
706         addInt(indexCount);
707         fWriter.writePad(indices, indexCount * sizeof(uint16_t));
708     }
709 }
710 
drawData(const void * data,size_t length)711 void SkPictureRecord::drawData(const void* data, size_t length) {
712     addDraw(DRAW_DATA);
713     addInt(length);
714     fWriter.writePad(data, length);
715 }
716 
717 ///////////////////////////////////////////////////////////////////////////////
718 
addBitmap(const SkBitmap & bitmap)719 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
720     const int index = fBitmapHeap->insert(bitmap);
721     // In debug builds, a bad return value from insert() will crash, allowing for debugging. In
722     // release builds, the invalid value will be recorded so that the reader will know that there
723     // was a problem.
724     SkASSERT(index != SkBitmapHeap::INVALID_SLOT);
725     addInt(index);
726 }
727 
addMatrix(const SkMatrix & matrix)728 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
729     addMatrixPtr(&matrix);
730 }
731 
addMatrixPtr(const SkMatrix * matrix)732 void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
733     this->addInt(matrix ? fMatrices.find(*matrix) : 0);
734 }
735 
addPaintPtr(const SkPaint * paint)736 const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
737     const SkFlatData* data = paint ? fPaints.findAndReturnFlat(*paint) : NULL;
738     int index = data ? data->index() : 0;
739     this->addInt(index);
740     return data;
741 }
742 
addPath(const SkPath & path)743 void SkPictureRecord::addPath(const SkPath& path) {
744     if (NULL == fPathHeap) {
745         fPathHeap = SkNEW(SkPathHeap);
746     }
747     addInt(fPathHeap->append(path));
748 }
749 
addPicture(SkPicture & picture)750 void SkPictureRecord::addPicture(SkPicture& picture) {
751     int index = fPictureRefs.find(&picture);
752     if (index < 0) {    // not found
753         index = fPictureRefs.count();
754         *fPictureRefs.append() = &picture;
755         picture.ref();
756     }
757     // follow the convention of recording a 1-based index
758     addInt(index + 1);
759 }
760 
addPoint(const SkPoint & point)761 void SkPictureRecord::addPoint(const SkPoint& point) {
762 #ifdef SK_DEBUG_SIZE
763     size_t start = fWriter.size();
764 #endif
765     fWriter.writePoint(point);
766 #ifdef SK_DEBUG_SIZE
767     fPointBytes += fWriter.size() - start;
768     fPointWrites++;
769 #endif
770 }
771 
addPoints(const SkPoint pts[],int count)772 void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
773     fWriter.writeMul4(pts, count * sizeof(SkPoint));
774 #ifdef SK_DEBUG_SIZE
775     fPointBytes += count * sizeof(SkPoint);
776     fPointWrites++;
777 #endif
778 }
779 
addRect(const SkRect & rect)780 void SkPictureRecord::addRect(const SkRect& rect) {
781 #ifdef SK_DEBUG_SIZE
782     size_t start = fWriter.size();
783 #endif
784     fWriter.writeRect(rect);
785 #ifdef SK_DEBUG_SIZE
786     fRectBytes += fWriter.size() - start;
787     fRectWrites++;
788 #endif
789 }
790 
addRectPtr(const SkRect * rect)791 void SkPictureRecord::addRectPtr(const SkRect* rect) {
792     if (fWriter.writeBool(rect != NULL)) {
793         fWriter.writeRect(*rect);
794     }
795 }
796 
addIRect(const SkIRect & rect)797 void SkPictureRecord::addIRect(const SkIRect& rect) {
798     fWriter.write(&rect, sizeof(rect));
799 }
800 
addIRectPtr(const SkIRect * rect)801 void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
802     if (fWriter.writeBool(rect != NULL)) {
803         *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
804     }
805 }
806 
addRRect(const SkRRect & rrect)807 void SkPictureRecord::addRRect(const SkRRect& rrect) {
808     fWriter.writeRRect(rrect);
809 }
810 
addRegion(const SkRegion & region)811 void SkPictureRecord::addRegion(const SkRegion& region) {
812     addInt(fRegions.find(region));
813 }
814 
addText(const void * text,size_t byteLength)815 void SkPictureRecord::addText(const void* text, size_t byteLength) {
816 #ifdef SK_DEBUG_SIZE
817     size_t start = fWriter.size();
818 #endif
819     addInt(byteLength);
820     fWriter.writePad(text, byteLength);
821 #ifdef SK_DEBUG_SIZE
822     fTextBytes += fWriter.size() - start;
823     fTextWrites++;
824 #endif
825 }
826 
827 ///////////////////////////////////////////////////////////////////////////////
828 
829 #ifdef SK_DEBUG_SIZE
size() const830 size_t SkPictureRecord::size() const {
831     size_t result = 0;
832     size_t sizeData;
833     bitmaps(&sizeData);
834     result += sizeData;
835     matrices(&sizeData);
836     result += sizeData;
837     paints(&sizeData);
838     result += sizeData;
839     paths(&sizeData);
840     result += sizeData;
841     pictures(&sizeData);
842     result += sizeData;
843     regions(&sizeData);
844     result += sizeData;
845     result += streamlen();
846     return result;
847 }
848 
bitmaps(size_t * size) const849 int SkPictureRecord::bitmaps(size_t* size) const {
850     size_t result = 0;
851     int count = fBitmaps.count();
852     for (int index = 0; index < count; index++)
853         result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
854     *size = result;
855     return count;
856 }
857 
matrices(size_t * size) const858 int SkPictureRecord::matrices(size_t* size) const {
859     int count = fMatrices.count();
860     *size = sizeof(fMatrices[0]) * count;
861     return count;
862 }
863 
paints(size_t * size) const864 int SkPictureRecord::paints(size_t* size) const {
865     size_t result = 0;
866     int count = fPaints.count();
867     for (int index = 0; index < count; index++)
868         result += sizeof(fPaints[index]) + fPaints[index]->size();
869     *size = result;
870     return count;
871 }
872 
paths(size_t * size) const873 int SkPictureRecord::paths(size_t* size) const {
874     size_t result = 0;
875     int count = fPaths.count();
876     for (int index = 0; index < count; index++)
877         result += sizeof(fPaths[index]) + fPaths[index]->size();
878     *size = result;
879     return count;
880 }
881 
regions(size_t * size) const882 int SkPictureRecord::regions(size_t* size) const {
883     size_t result = 0;
884     int count = fRegions.count();
885     for (int index = 0; index < count; index++)
886         result += sizeof(fRegions[index]) + fRegions[index]->size();
887     *size = result;
888     return count;
889 }
890 
streamlen() const891 size_t SkPictureRecord::streamlen() const {
892     return fWriter.size();
893 }
894 #endif
895 
896 #ifdef SK_DEBUG_VALIDATE
validate() const897 void SkPictureRecord::validate() const {
898     validateBitmaps();
899     validateMatrices();
900     validatePaints();
901     validatePaths();
902     validatePictures();
903     validateRegions();
904 }
905 
validateBitmaps() const906 void SkPictureRecord::validateBitmaps() const {
907     int count = fBitmaps.count();
908     SkASSERT((unsigned) count < 0x1000);
909     for (int index = 0; index < count; index++) {
910         const SkFlatBitmap* bitPtr = fBitmaps[index];
911         SkASSERT(bitPtr);
912         bitPtr->validate();
913     }
914 }
915 
validateMatrices() const916 void SkPictureRecord::validateMatrices() const {
917     int count = fMatrices.count();
918     SkASSERT((unsigned) count < 0x1000);
919     for (int index = 0; index < count; index++) {
920         const SkFlatMatrix* matrix = fMatrices[index];
921         SkASSERT(matrix);
922         matrix->validate();
923     }
924 }
925 
validatePaints() const926 void SkPictureRecord::validatePaints() const {
927     int count = fPaints.count();
928     SkASSERT((unsigned) count < 0x1000);
929     for (int index = 0; index < count; index++) {
930         const SkFlatPaint* paint = fPaints[index];
931         SkASSERT(paint);
932 //            paint->validate();
933     }
934 }
935 
validatePaths() const936 void SkPictureRecord::validatePaths() const {
937     int count = fPaths.count();
938     SkASSERT((unsigned) count < 0x1000);
939     for (int index = 0; index < count; index++) {
940         const SkFlatPath* path = fPaths[index];
941         SkASSERT(path);
942         path->validate();
943     }
944 }
945 
validateRegions() const946 void SkPictureRecord::validateRegions() const {
947     int count = fRegions.count();
948     SkASSERT((unsigned) count < 0x1000);
949     for (int index = 0; index < count; index++) {
950         const SkFlatRegion* region = fRegions[index];
951         SkASSERT(region);
952         region->validate();
953     }
954 }
955 #endif
956