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