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