• 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 
11 #define MIN_WRITER_SIZE 16384
12 #define HEAP_BLOCK_SIZE 4096
13 
SkPictureRecord(uint32_t flags)14 SkPictureRecord::SkPictureRecord(uint32_t flags) :
15         fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
16     fBitmapIndex = fMatrixIndex = fPaintIndex = fRegionIndex = 1;
17 #ifdef SK_DEBUG_SIZE
18     fPointBytes = fRectBytes = fTextBytes = 0;
19     fPointWrites = fRectWrites = fTextWrites = 0;
20 #endif
21 
22     fRestoreOffsetStack.setReserve(32);
23     fRestoreOffsetStack.push(0);
24 
25     fPathHeap = NULL;   // lazy allocate
26     fFirstSavedLayerIndex = kNoSavedLayerIndex;
27 }
28 
~SkPictureRecord()29 SkPictureRecord::~SkPictureRecord() {
30     reset();
31 }
32 
33 ///////////////////////////////////////////////////////////////////////////////
34 
save(SaveFlags flags)35 int SkPictureRecord::save(SaveFlags flags) {
36     addDraw(SAVE);
37     addInt(flags);
38 
39     fRestoreOffsetStack.push(0);
40 
41     validate();
42     return this->INHERITED::save(flags);
43 }
44 
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)45 int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
46                                SaveFlags flags) {
47     addDraw(SAVE_LAYER);
48     addRectPtr(bounds);
49     addPaintPtr(paint);
50     addInt(flags);
51 
52     fRestoreOffsetStack.push(0);
53 
54     if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
55         fFirstSavedLayerIndex = fRestoreOffsetStack.count();
56     }
57 
58     validate();
59     /*  Don't actually call saveLayer, because that will try to allocate an
60         offscreen device (potentially very big) which we don't actually need
61         at this time (and may not be able to afford since during record our
62         clip starts out the size of the picture, which is often much larger
63         than the size of the actual device we'll use during playback).
64      */
65     int count = this->INHERITED::save(flags);
66     this->clipRectBounds(bounds, flags, NULL);
67     return count;
68 }
69 
isDrawingToLayer() const70 bool SkPictureRecord::isDrawingToLayer() const {
71     return fFirstSavedLayerIndex != kNoSavedLayerIndex;
72 }
73 
restore()74 void SkPictureRecord::restore() {
75     // check for underflow
76     if (fRestoreOffsetStack.count() == 0) {
77         return;
78     }
79 
80     // patch up the clip offsets
81     uint32_t restoreOffset = (uint32_t)fWriter.size();
82     uint32_t offset = fRestoreOffsetStack.top();
83     while (offset) {
84         uint32_t* peek = fWriter.peek32(offset);
85         offset = *peek;
86         *peek = restoreOffset;
87     }
88 
89     if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
90         fFirstSavedLayerIndex = kNoSavedLayerIndex;
91     }
92 
93     fRestoreOffsetStack.pop();
94 
95     addDraw(RESTORE);
96     validate();
97     return this->INHERITED::restore();
98 }
99 
translate(SkScalar dx,SkScalar dy)100 bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
101     addDraw(TRANSLATE);
102     addScalar(dx);
103     addScalar(dy);
104     validate();
105     return this->INHERITED::translate(dx, dy);
106 }
107 
scale(SkScalar sx,SkScalar sy)108 bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
109     addDraw(SCALE);
110     addScalar(sx);
111     addScalar(sy);
112     validate();
113     return this->INHERITED::scale(sx, sy);
114 }
115 
rotate(SkScalar degrees)116 bool SkPictureRecord::rotate(SkScalar degrees) {
117     addDraw(ROTATE);
118     addScalar(degrees);
119     validate();
120     return this->INHERITED::rotate(degrees);
121 }
122 
skew(SkScalar sx,SkScalar sy)123 bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
124     addDraw(SKEW);
125     addScalar(sx);
126     addScalar(sy);
127     validate();
128     return this->INHERITED::skew(sx, sy);
129 }
130 
concat(const SkMatrix & matrix)131 bool SkPictureRecord::concat(const SkMatrix& matrix) {
132     validate();
133     addDraw(CONCAT);
134     addMatrix(matrix);
135     validate();
136     return this->INHERITED::concat(matrix);
137 }
138 
setMatrix(const SkMatrix & matrix)139 void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
140     validate();
141     addDraw(SET_MATRIX);
142     addMatrix(matrix);
143     validate();
144     this->INHERITED::setMatrix(matrix);
145 }
146 
regionOpExpands(SkRegion::Op op)147 static bool regionOpExpands(SkRegion::Op op) {
148     switch (op) {
149         case SkRegion::kUnion_Op:
150         case SkRegion::kXOR_Op:
151         case SkRegion::kReverseDifference_Op:
152         case SkRegion::kReplace_Op:
153             return true;
154         case SkRegion::kIntersect_Op:
155         case SkRegion::kDifference_Op:
156             return false;
157         default:
158             SkDEBUGFAIL("unknown region op");
159             return false;
160     }
161 }
162 
recordOffsetForRestore(SkRegion::Op op)163 void SkPictureRecord::recordOffsetForRestore(SkRegion::Op op) {
164     if (regionOpExpands(op)) {
165         // Run back through any previous clip ops, and mark their offset to
166         // be 0, disabling their ability to trigger a jump-to-restore, otherwise
167         // they could hide this clips ability to expand the clip (i.e. go from
168         // empty to non-empty).
169         uint32_t offset = fRestoreOffsetStack.top();
170         while (offset) {
171             uint32_t* peek = fWriter.peek32(offset);
172             offset = *peek;
173             *peek = 0;
174         }
175     }
176 
177     size_t offset = fWriter.size();
178     addInt(fRestoreOffsetStack.top());
179     fRestoreOffsetStack.top() = offset;
180 }
181 
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)182 bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
183     addDraw(CLIP_RECT);
184     addRect(rect);
185     addInt(ClipParams_pack(op, doAA));
186 
187     this->recordOffsetForRestore(op);
188 
189     validate();
190     return this->INHERITED::clipRect(rect, op, doAA);
191 }
192 
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)193 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
194     addDraw(CLIP_PATH);
195     addPath(path);
196     addInt(ClipParams_pack(op, doAA));
197 
198     this->recordOffsetForRestore(op);
199 
200     validate();
201 
202     if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
203         return this->INHERITED::clipRect(path.getBounds(), op, doAA);
204     } else {
205         return this->INHERITED::clipPath(path, op, doAA);
206     }
207 }
208 
clipRegion(const SkRegion & region,SkRegion::Op op)209 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
210     addDraw(CLIP_REGION);
211     addRegion(region);
212     addInt(ClipParams_pack(op, false));
213 
214     this->recordOffsetForRestore(op);
215 
216     validate();
217     return this->INHERITED::clipRegion(region, op);
218 }
219 
clear(SkColor color)220 void SkPictureRecord::clear(SkColor color) {
221     addDraw(DRAW_CLEAR);
222     addInt(color);
223     validate();
224 }
225 
drawPaint(const SkPaint & paint)226 void SkPictureRecord::drawPaint(const SkPaint& paint) {
227     addDraw(DRAW_PAINT);
228     addPaint(paint);
229     validate();
230 }
231 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)232 void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
233                         const SkPaint& paint) {
234     addDraw(DRAW_POINTS);
235     addPaint(paint);
236     addInt(mode);
237     addInt(count);
238     fWriter.writeMul4(pts, count * sizeof(SkPoint));
239     validate();
240 }
241 
drawRect(const SkRect & rect,const SkPaint & paint)242 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
243     addDraw(DRAW_RECT);
244     addPaint(paint);
245     addRect(rect);
246     validate();
247 }
248 
drawPath(const SkPath & path,const SkPaint & paint)249 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
250     addDraw(DRAW_PATH);
251     addPaint(paint);
252     addPath(path);
253     validate();
254 }
255 
drawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint=NULL)256 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
257                         const SkPaint* paint = NULL) {
258     addDraw(DRAW_BITMAP);
259     addPaintPtr(paint);
260     addBitmap(bitmap);
261     addScalar(left);
262     addScalar(top);
263     validate();
264 }
265 
drawBitmapRect(const SkBitmap & bitmap,const SkIRect * src,const SkRect & dst,const SkPaint * paint)266 void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
267                             const SkRect& dst, const SkPaint* paint) {
268     addDraw(DRAW_BITMAP_RECT);
269     addPaintPtr(paint);
270     addBitmap(bitmap);
271     addIRectPtr(src);  // may be null
272     addRect(dst);
273     validate();
274 }
275 
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)276 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
277                                        const SkPaint* paint) {
278     addDraw(DRAW_BITMAP_MATRIX);
279     addPaintPtr(paint);
280     addBitmap(bitmap);
281     addMatrix(matrix);
282     validate();
283 }
284 
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)285 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
286                                      const SkRect& dst, const SkPaint* paint) {
287     addDraw(DRAW_BITMAP_NINE);
288     addPaintPtr(paint);
289     addBitmap(bitmap);
290     addIRect(center);
291     addRect(dst);
292     validate();
293 }
294 
drawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint=NULL)295 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
296                         const SkPaint* paint = NULL) {
297     addDraw(DRAW_SPRITE);
298     addPaintPtr(paint);
299     addBitmap(bitmap);
300     addInt(left);
301     addInt(top);
302     validate();
303 }
304 
addFontMetricsTopBottom(const SkPaint & paint,SkScalar minY,SkScalar maxY)305 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
306                                               SkScalar minY, SkScalar maxY) {
307     SkPaint::FontMetrics metrics;
308     paint.getFontMetrics(&metrics);
309     SkRect bounds;
310     // construct a rect so we can see any adjustments from the paint.
311     // we use 0,1 for left,right, just so the rect isn't empty
312     bounds.set(0, metrics.fTop + minY,
313                SK_Scalar1, metrics.fBottom + maxY);
314     (void)paint.computeFastBounds(bounds, &bounds);
315     // now record the top and bottom
316     addScalar(bounds.fTop);
317     addScalar(bounds.fBottom);
318 }
319 
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)320 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
321                       SkScalar y, const SkPaint& paint) {
322     bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
323 
324     addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
325     addPaint(paint);
326     addText(text, byteLength);
327     addScalar(x);
328     addScalar(y);
329     if (fast) {
330         addFontMetricsTopBottom(paint, y, y);
331     }
332     validate();
333 }
334 
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)335 void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
336                          const SkPoint pos[], const SkPaint& paint) {
337     size_t points = paint.countText(text, byteLength);
338     if (0 == points)
339         return;
340 
341     bool canUseDrawH = true;
342     SkScalar minY = pos[0].fY;
343     SkScalar maxY = pos[0].fY;
344     // check if the caller really should have used drawPosTextH()
345     {
346         const SkScalar firstY = pos[0].fY;
347         for (size_t index = 1; index < points; index++) {
348             if (pos[index].fY != firstY) {
349                 canUseDrawH = false;
350                 if (pos[index].fY < minY) {
351                     minY = pos[index].fY;
352                 } else if (pos[index].fY > maxY) {
353                     maxY = pos[index].fY;
354                 }
355             }
356         }
357     }
358 
359     bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
360     bool fast = canUseDrawH && fastBounds;
361 
362     if (fast) {
363         addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
364     } else if (canUseDrawH) {
365         addDraw(DRAW_POS_TEXT_H);
366     } else if (fastBounds) {
367         addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
368     } else {
369         addDraw(DRAW_POS_TEXT);
370     }
371     addPaint(paint);
372     addText(text, byteLength);
373     addInt(points);
374 
375 #ifdef SK_DEBUG_SIZE
376     size_t start = fWriter.size();
377 #endif
378     if (canUseDrawH) {
379         if (fast) {
380             addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
381         }
382         addScalar(pos[0].fY);
383         SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
384         for (size_t index = 0; index < points; index++)
385             *xptr++ = pos[index].fX;
386     }
387     else {
388         fWriter.writeMul4(pos, points * sizeof(SkPoint));
389         if (fastBounds) {
390             addFontMetricsTopBottom(paint, minY, maxY);
391         }
392     }
393 #ifdef SK_DEBUG_SIZE
394     fPointBytes += fWriter.size() - start;
395     fPointWrites += points;
396 #endif
397     validate();
398 }
399 
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)400 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
401                           const SkScalar xpos[], SkScalar constY,
402                           const SkPaint& paint) {
403     size_t points = paint.countText(text, byteLength);
404     if (0 == points)
405         return;
406 
407     bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
408 
409     addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
410     addPaint(paint);
411     addText(text, byteLength);
412     addInt(points);
413 
414 #ifdef SK_DEBUG_SIZE
415     size_t start = fWriter.size();
416 #endif
417     if (fast) {
418         addFontMetricsTopBottom(paint, constY, constY);
419     }
420     addScalar(constY);
421     fWriter.writeMul4(xpos, points * sizeof(SkScalar));
422 #ifdef SK_DEBUG_SIZE
423     fPointBytes += fWriter.size() - start;
424     fPointWrites += points;
425 #endif
426     validate();
427 }
428 
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)429 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
430                             const SkPath& path, const SkMatrix* matrix,
431                             const SkPaint& paint) {
432     addDraw(DRAW_TEXT_ON_PATH);
433     addPaint(paint);
434     addText(text, byteLength);
435     addPath(path);
436     addMatrixPtr(matrix);
437     validate();
438 }
439 
drawPicture(SkPicture & picture)440 void SkPictureRecord::drawPicture(SkPicture& picture) {
441     addDraw(DRAW_PICTURE);
442     addPicture(picture);
443     validate();
444 }
445 
drawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode *,const uint16_t indices[],int indexCount,const SkPaint & paint)446 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
447                           const SkPoint vertices[], const SkPoint texs[],
448                           const SkColor colors[], SkXfermode*,
449                           const uint16_t indices[], int indexCount,
450                           const SkPaint& paint) {
451     uint32_t flags = 0;
452     if (texs) {
453         flags |= DRAW_VERTICES_HAS_TEXS;
454     }
455     if (colors) {
456         flags |= DRAW_VERTICES_HAS_COLORS;
457     }
458     if (indexCount > 0) {
459         flags |= DRAW_VERTICES_HAS_INDICES;
460     }
461 
462     addDraw(DRAW_VERTICES);
463     addPaint(paint);
464     addInt(flags);
465     addInt(vmode);
466     addInt(vertexCount);
467     addPoints(vertices, vertexCount);
468     if (flags & DRAW_VERTICES_HAS_TEXS) {
469         addPoints(texs, vertexCount);
470     }
471     if (flags & DRAW_VERTICES_HAS_COLORS) {
472         fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
473     }
474     if (flags & DRAW_VERTICES_HAS_INDICES) {
475         addInt(indexCount);
476         fWriter.writePad(indices, indexCount * sizeof(uint16_t));
477     }
478 }
479 
drawData(const void * data,size_t length)480 void SkPictureRecord::drawData(const void* data, size_t length) {
481     addDraw(DRAW_DATA);
482     addInt(length);
483     fWriter.writePad(data, length);
484 }
485 
486 ///////////////////////////////////////////////////////////////////////////////
487 
reset()488 void SkPictureRecord::reset() {
489     SkSafeUnref(fPathHeap);
490     fPathHeap = NULL;
491 
492     fBitmaps.reset();
493     fMatrices.reset();
494     fPaints.reset();
495     fPictureRefs.unrefAll();
496     fRegions.reset();
497     fWriter.reset();
498     fHeap.reset();
499 
500     fRestoreOffsetStack.setCount(1);
501     fRestoreOffsetStack.top() = 0;
502 
503     fRCSet.reset();
504     fTFSet.reset();
505 }
506 
addBitmap(const SkBitmap & bitmap)507 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
508     addInt(find(fBitmaps, bitmap));
509 }
510 
addMatrix(const SkMatrix & matrix)511 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
512     addMatrixPtr(&matrix);
513 }
514 
addMatrixPtr(const SkMatrix * matrix)515 void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
516     addInt(find(fMatrices, matrix));
517 }
518 
addPaint(const SkPaint & paint)519 void SkPictureRecord::addPaint(const SkPaint& paint) {
520     addPaintPtr(&paint);
521 }
522 
addPaintPtr(const SkPaint * paint)523 void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
524     addInt(find(fPaints, paint));
525 }
526 
addPath(const SkPath & path)527 void SkPictureRecord::addPath(const SkPath& path) {
528     if (NULL == fPathHeap) {
529         fPathHeap = SkNEW(SkPathHeap);
530     }
531     addInt(fPathHeap->append(path));
532 }
533 
addPicture(SkPicture & picture)534 void SkPictureRecord::addPicture(SkPicture& picture) {
535     int index = fPictureRefs.find(&picture);
536     if (index < 0) {    // not found
537         index = fPictureRefs.count();
538         *fPictureRefs.append() = &picture;
539         picture.ref();
540     }
541     // follow the convention of recording a 1-based index
542     addInt(index + 1);
543 }
544 
addPoint(const SkPoint & point)545 void SkPictureRecord::addPoint(const SkPoint& point) {
546 #ifdef SK_DEBUG_SIZE
547     size_t start = fWriter.size();
548 #endif
549     fWriter.writePoint(point);
550 #ifdef SK_DEBUG_SIZE
551     fPointBytes += fWriter.size() - start;
552     fPointWrites++;
553 #endif
554 }
555 
addPoints(const SkPoint pts[],int count)556 void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
557     fWriter.writeMul4(pts, count * sizeof(SkPoint));
558 #ifdef SK_DEBUG_SIZE
559     fPointBytes += count * sizeof(SkPoint);
560     fPointWrites++;
561 #endif
562 }
563 
addRect(const SkRect & rect)564 void SkPictureRecord::addRect(const SkRect& rect) {
565 #ifdef SK_DEBUG_SIZE
566     size_t start = fWriter.size();
567 #endif
568     fWriter.writeRect(rect);
569 #ifdef SK_DEBUG_SIZE
570     fRectBytes += fWriter.size() - start;
571     fRectWrites++;
572 #endif
573 }
574 
addRectPtr(const SkRect * rect)575 void SkPictureRecord::addRectPtr(const SkRect* rect) {
576     if (fWriter.writeBool(rect != NULL)) {
577         fWriter.writeRect(*rect);
578     }
579 }
580 
addIRect(const SkIRect & rect)581 void SkPictureRecord::addIRect(const SkIRect& rect) {
582     fWriter.write(&rect, sizeof(rect));
583 }
584 
addIRectPtr(const SkIRect * rect)585 void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
586     if (fWriter.writeBool(rect != NULL)) {
587         *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
588     }
589 }
590 
addRegion(const SkRegion & region)591 void SkPictureRecord::addRegion(const SkRegion& region) {
592     addInt(find(fRegions, region));
593 }
594 
addText(const void * text,size_t byteLength)595 void SkPictureRecord::addText(const void* text, size_t byteLength) {
596 #ifdef SK_DEBUG_SIZE
597     size_t start = fWriter.size();
598 #endif
599     addInt(byteLength);
600     fWriter.writePad(text, byteLength);
601 #ifdef SK_DEBUG_SIZE
602     fTextBytes += fWriter.size() - start;
603     fTextWrites++;
604 #endif
605 }
606 
607 ///////////////////////////////////////////////////////////////////////////////
608 
find(SkTDArray<const SkFlatBitmap * > & bitmaps,const SkBitmap & bitmap)609 int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
610     SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
611                                                &fRCSet);
612     int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
613         bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
614     if (index >= 0) {
615         (void)fHeap.unalloc(flat);
616         return bitmaps[index]->index();
617     }
618     index = ~index;
619     *bitmaps.insert(index) = flat;
620     return fBitmapIndex++;
621 }
622 
find(SkTDArray<const SkFlatMatrix * > & matrices,const SkMatrix * matrix)623 int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
624     if (matrix == NULL)
625         return 0;
626     SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
627     int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
628         matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
629     if (index >= 0) {
630         (void)fHeap.unalloc(flat);
631         return matrices[index]->index();
632     }
633     index = ~index;
634     *matrices.insert(index) = flat;
635     return fMatrixIndex++;
636 }
637 
find(SkTDArray<const SkFlatPaint * > & paints,const SkPaint * paint)638 int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
639     if (paint == NULL) {
640         return 0;
641     }
642 
643     SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
644                                              &fRCSet, &fTFSet);
645     int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
646         paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
647     if (index >= 0) {
648         (void)fHeap.unalloc(flat);
649         return paints[index]->index();
650     }
651 
652     index = ~index;
653     *paints.insert(index) = flat;
654     return fPaintIndex++;
655 }
656 
find(SkTDArray<const SkFlatRegion * > & regions,const SkRegion & region)657 int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
658     SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
659     int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
660         regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
661     if (index >= 0) {
662         (void)fHeap.unalloc(flat);
663         return regions[index]->index();
664     }
665     index = ~index;
666     *regions.insert(index) = flat;
667     return fRegionIndex++;
668 }
669 
670 #ifdef SK_DEBUG_DUMP
dumpMatrices()671 void SkPictureRecord::dumpMatrices() {
672     int count = fMatrices.count();
673     SkMatrix defaultMatrix;
674     defaultMatrix.reset();
675     for (int index = 0; index < count; index++) {
676         const SkFlatMatrix* flatMatrix = fMatrices[index];
677         flatMatrix->dump();
678     }
679 }
680 
dumpPaints()681 void SkPictureRecord::dumpPaints() {
682     int count = fPaints.count();
683     for (int index = 0; index < count; index++)
684         fPaints[index]->dump();
685 }
686 #endif
687 
688 #ifdef SK_DEBUG_SIZE
size() const689 size_t SkPictureRecord::size() const {
690     size_t result = 0;
691     size_t sizeData;
692     bitmaps(&sizeData);
693     result += sizeData;
694     matrices(&sizeData);
695     result += sizeData;
696     paints(&sizeData);
697     result += sizeData;
698     paths(&sizeData);
699     result += sizeData;
700     pictures(&sizeData);
701     result += sizeData;
702     regions(&sizeData);
703     result += sizeData;
704     result += streamlen();
705     return result;
706 }
707 
bitmaps(size_t * size) const708 int SkPictureRecord::bitmaps(size_t* size) const {
709     size_t result = 0;
710     int count = fBitmaps.count();
711     for (int index = 0; index < count; index++)
712         result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
713     *size = result;
714     return count;
715 }
716 
matrices(size_t * size) const717 int SkPictureRecord::matrices(size_t* size) const {
718     int count = fMatrices.count();
719     *size = sizeof(fMatrices[0]) * count;
720     return count;
721 }
722 
paints(size_t * size) const723 int SkPictureRecord::paints(size_t* size) const {
724     size_t result = 0;
725     int count = fPaints.count();
726     for (int index = 0; index < count; index++)
727         result += sizeof(fPaints[index]) + fPaints[index]->size();
728     *size = result;
729     return count;
730 }
731 
paths(size_t * size) const732 int SkPictureRecord::paths(size_t* size) const {
733     size_t result = 0;
734     int count = fPaths.count();
735     for (int index = 0; index < count; index++)
736         result += sizeof(fPaths[index]) + fPaths[index]->size();
737     *size = result;
738     return count;
739 }
740 
regions(size_t * size) const741 int SkPictureRecord::regions(size_t* size) const {
742     size_t result = 0;
743     int count = fRegions.count();
744     for (int index = 0; index < count; index++)
745         result += sizeof(fRegions[index]) + fRegions[index]->size();
746     *size = result;
747     return count;
748 }
749 
streamlen() const750 size_t SkPictureRecord::streamlen() const {
751     return fWriter.size();
752 }
753 #endif
754 
755 #ifdef SK_DEBUG_VALIDATE
validate() const756 void SkPictureRecord::validate() const {
757     validateBitmaps();
758     validateMatrices();
759     validatePaints();
760     validatePaths();
761     validatePictures();
762     validateRegions();
763 }
764 
validateBitmaps() const765 void SkPictureRecord::validateBitmaps() const {
766     int count = fBitmaps.count();
767     SkASSERT((unsigned) count < 0x1000);
768     for (int index = 0; index < count; index++) {
769         const SkFlatBitmap* bitPtr = fBitmaps[index];
770         SkASSERT(bitPtr);
771         bitPtr->validate();
772     }
773 }
774 
validateMatrices() const775 void SkPictureRecord::validateMatrices() const {
776     int count = fMatrices.count();
777     SkASSERT((unsigned) count < 0x1000);
778     for (int index = 0; index < count; index++) {
779         const SkFlatMatrix* matrix = fMatrices[index];
780         SkASSERT(matrix);
781         matrix->validate();
782     }
783 }
784 
validatePaints() const785 void SkPictureRecord::validatePaints() const {
786     int count = fPaints.count();
787     SkASSERT((unsigned) count < 0x1000);
788     for (int index = 0; index < count; index++) {
789         const SkFlatPaint* paint = fPaints[index];
790         SkASSERT(paint);
791 //            paint->validate();
792     }
793 }
794 
validatePaths() const795 void SkPictureRecord::validatePaths() const {
796     int count = fPaths.count();
797     SkASSERT((unsigned) count < 0x1000);
798     for (int index = 0; index < count; index++) {
799         const SkFlatPath* path = fPaths[index];
800         SkASSERT(path);
801         path->validate();
802     }
803 }
804 
validateRegions() const805 void SkPictureRecord::validateRegions() const {
806     int count = fRegions.count();
807     SkASSERT((unsigned) count < 0x1000);
808     for (int index = 0; index < count; index++) {
809         const SkFlatRegion* region = fRegions[index];
810         SkASSERT(region);
811         region->validate();
812     }
813 }
814 #endif
815 
816