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