Home | History | Annotate | Download | only in core
      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 
      8 SkPictureRecord::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 
     22 SkPictureRecord::~SkPictureRecord() {
     23     reset();
     24 }
     25 
     26 ///////////////////////////////////////////////////////////////////////////////
     27 
     28 int 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 
     38 int 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 
     57 void 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 
     78 bool 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 
     86 bool 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 
     94 bool SkPictureRecord::rotate(SkScalar degrees) {
     95     addDraw(ROTATE);
     96     addScalar(degrees);
     97     validate();
     98     return this->INHERITED::rotate(degrees);
     99 }
    100 
    101 bool 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 
    109 bool SkPictureRecord::concat(const SkMatrix& matrix) {
    110     validate();
    111     addDraw(CONCAT);
    112     addMatrix(matrix);
    113     validate();
    114     return this->INHERITED::concat(matrix);
    115 }
    116 
    117 void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
    118     validate();
    119     addDraw(SET_MATRIX);
    120     addMatrix(matrix);
    121     validate();
    122     this->INHERITED::setMatrix(matrix);
    123 }
    124 
    125 bool 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 
    138 bool 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 
    156 bool 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 
    169 void SkPictureRecord::drawPaint(const SkPaint& paint) {
    170     addDraw(DRAW_PAINT);
    171     addPaint(paint);
    172     validate();
    173 }
    174 
    175 void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
    176                         const SkPaint& paint) {
    177     addDraw(DRAW_POINTS);
    178     addPaint(paint);
    179     addInt(mode);
    180     addInt(count);
    181     fWriter.writeMul4(pts, count * sizeof(SkPoint));
    182     validate();
    183 }
    184 
    185 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    186     addDraw(DRAW_RECT);
    187     addPaint(paint);
    188     addRect(rect);
    189     validate();
    190 }
    191 
    192 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    193     addDraw(DRAW_PATH);
    194     addPaint(paint);
    195     addPath(path);
    196     validate();
    197 }
    198 
    199 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
    200                         const SkPaint* paint = NULL) {
    201     addDraw(DRAW_BITMAP);
    202     addPaintPtr(paint);
    203     addBitmap(bitmap);
    204     addScalar(left);
    205     addScalar(top);
    206     validate();
    207 }
    208 
    209 void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
    210                             const SkRect& dst, const SkPaint* paint) {
    211     addDraw(DRAW_BITMAP_RECT);
    212     addPaintPtr(paint);
    213     addBitmap(bitmap);
    214     addIRectPtr(src);  // may be null
    215     addRect(dst);
    216     validate();
    217 }
    218 
    219 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
    220                               const SkPaint* paint) {
    221     addDraw(DRAW_BITMAP_MATRIX);
    222     addPaintPtr(paint);
    223     addBitmap(bitmap);
    224     addMatrix(matrix);
    225     validate();
    226 }
    227 
    228 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
    229                         const SkPaint* paint = NULL) {
    230     addDraw(DRAW_SPRITE);
    231     addPaintPtr(paint);
    232     addBitmap(bitmap);
    233     addInt(left);
    234     addInt(top);
    235     validate();
    236 }
    237 
    238 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
    239                                               SkScalar baselineY) {
    240     SkPaint::FontMetrics metrics;
    241     paint.getFontMetrics(&metrics);
    242     SkRect bounds;
    243     // construct a rect so we can see any adjustments from the paint.
    244     // we use 0,1 for left,right, just so the rect isn't empty
    245     bounds.set(0, metrics.fTop + baselineY,
    246                SK_Scalar1, metrics.fBottom + baselineY);
    247     (void)paint.computeFastBounds(bounds, &bounds);
    248     // now record the top and bottom
    249     addScalar(bounds.fTop);
    250     addScalar(bounds.fBottom);
    251 }
    252 
    253 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
    254                       SkScalar y, const SkPaint& paint) {
    255     bool fast = paint.canComputeFastBounds();
    256 
    257     addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
    258     addPaint(paint);
    259     addText(text, byteLength);
    260     addScalar(x);
    261     addScalar(y);
    262     if (fast) {
    263         addFontMetricsTopBottom(paint, y);
    264     }
    265     validate();
    266 }
    267 
    268 void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
    269                          const SkPoint pos[], const SkPaint& paint) {
    270     size_t points = paint.countText(text, byteLength);
    271     if (0 == points)
    272         return;
    273 
    274     bool canUseDrawH = true;
    275     // check if the caller really should have used drawPosTextH()
    276     {
    277         const SkScalar firstY = pos[0].fY;
    278         for (size_t index = 1; index < points; index++) {
    279             if (pos[index].fY != firstY) {
    280                 canUseDrawH = false;
    281                 break;
    282             }
    283         }
    284     }
    285 
    286     bool fast = canUseDrawH && paint.canComputeFastBounds();
    287 
    288     if (fast) {
    289         addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
    290     } else {
    291         addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
    292     }
    293     addPaint(paint);
    294     addText(text, byteLength);
    295     addInt(points);
    296 
    297 #ifdef SK_DEBUG_SIZE
    298     size_t start = fWriter.size();
    299 #endif
    300     if (canUseDrawH) {
    301         if (fast) {
    302             addFontMetricsTopBottom(paint, pos[0].fY);
    303         }
    304         addScalar(pos[0].fY);
    305         SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
    306         for (size_t index = 0; index < points; index++)
    307             *xptr++ = pos[index].fX;
    308     }
    309     else {
    310         fWriter.writeMul4(pos, points * sizeof(SkPoint));
    311     }
    312 #ifdef SK_DEBUG_SIZE
    313     fPointBytes += fWriter.size() - start;
    314     fPointWrites += points;
    315 #endif
    316     validate();
    317 }
    318 
    319 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
    320                           const SkScalar xpos[], SkScalar constY,
    321                           const SkPaint& paint) {
    322     size_t points = paint.countText(text, byteLength);
    323     if (0 == points)
    324         return;
    325 
    326     bool fast = paint.canComputeFastBounds();
    327 
    328     addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
    329     addPaint(paint);
    330     addText(text, byteLength);
    331     addInt(points);
    332 
    333 #ifdef SK_DEBUG_SIZE
    334     size_t start = fWriter.size();
    335 #endif
    336     if (fast) {
    337         addFontMetricsTopBottom(paint, constY);
    338     }
    339     addScalar(constY);
    340     fWriter.writeMul4(xpos, points * sizeof(SkScalar));
    341 #ifdef SK_DEBUG_SIZE
    342     fPointBytes += fWriter.size() - start;
    343     fPointWrites += points;
    344 #endif
    345     validate();
    346 }
    347 
    348 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
    349                             const SkPath& path, const SkMatrix* matrix,
    350                             const SkPaint& paint) {
    351     addDraw(DRAW_TEXT_ON_PATH);
    352     addPaint(paint);
    353     addText(text, byteLength);
    354     addPath(path);
    355     addMatrixPtr(matrix);
    356     validate();
    357 }
    358 
    359 void SkPictureRecord::drawPicture(SkPicture& picture) {
    360     addDraw(DRAW_PICTURE);
    361     addPicture(picture);
    362     validate();
    363 }
    364 
    365 void SkPictureRecord::drawShape(SkShape* shape) {
    366     addDraw(DRAW_SHAPE);
    367 
    368     int index = fShapes.find(shape);
    369     if (index < 0) {    // not found
    370         index = fShapes.count();
    371         *fShapes.append() = shape;
    372         shape->ref();
    373     }
    374     // follow the convention of recording a 1-based index
    375     addInt(index + 1);
    376     validate();
    377 }
    378 
    379 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
    380                           const SkPoint vertices[], const SkPoint texs[],
    381                           const SkColor colors[], SkXfermode*,
    382                           const uint16_t indices[], int indexCount,
    383                           const SkPaint& paint) {
    384     uint32_t flags = 0;
    385     if (texs) {
    386         flags |= DRAW_VERTICES_HAS_TEXS;
    387     }
    388     if (colors) {
    389         flags |= DRAW_VERTICES_HAS_COLORS;
    390     }
    391     if (indexCount > 0) {
    392         flags |= DRAW_VERTICES_HAS_INDICES;
    393     }
    394 
    395     addDraw(DRAW_VERTICES);
    396     addPaint(paint);
    397     addInt(flags);
    398     addInt(vmode);
    399     addInt(vertexCount);
    400     addPoints(vertices, vertexCount);
    401     if (flags & DRAW_VERTICES_HAS_TEXS) {
    402         addPoints(texs, vertexCount);
    403     }
    404     if (flags & DRAW_VERTICES_HAS_COLORS) {
    405         fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
    406     }
    407     if (flags & DRAW_VERTICES_HAS_INDICES) {
    408         addInt(indexCount);
    409         fWriter.writePad(indices, indexCount * sizeof(uint16_t));
    410     }
    411 }
    412 
    413 void SkPictureRecord::drawData(const void* data, size_t length) {
    414     addDraw(DRAW_DATA);
    415     addInt(length);
    416     fWriter.writePad(data, length);
    417 }
    418 
    419 ///////////////////////////////////////////////////////////////////////////////
    420 
    421 void SkPictureRecord::reset() {
    422     fPathHeap->safeUnref();
    423     fPathHeap = NULL;
    424 
    425     fBitmaps.reset();
    426     fMatrices.reset();
    427     fPaints.reset();
    428     fPictureRefs.unrefAll();
    429     fRegions.reset();
    430     fShapes.safeUnrefAll();
    431     fWriter.reset();
    432     fHeap.reset();
    433 
    434     fRestoreOffsetStack.setCount(1);
    435     fRestoreOffsetStack.top() = 0;
    436 
    437     fRCRecorder.reset();
    438     fTFRecorder.reset();
    439 }
    440 
    441 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
    442     addInt(find(fBitmaps, bitmap));
    443 }
    444 
    445 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
    446     addMatrixPtr(&matrix);
    447 }
    448 
    449 void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
    450     addInt(find(fMatrices, matrix));
    451 }
    452 
    453 void SkPictureRecord::addPaint(const SkPaint& paint) {
    454     addPaintPtr(&paint);
    455 }
    456 
    457 void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
    458     addInt(find(fPaints, paint));
    459 }
    460 
    461 void SkPictureRecord::addPath(const SkPath& path) {
    462     if (NULL == fPathHeap) {
    463         fPathHeap = SkNEW(SkPathHeap);
    464     }
    465     addInt(fPathHeap->append(path));
    466 }
    467 
    468 void SkPictureRecord::addPicture(SkPicture& picture) {
    469     int index = fPictureRefs.find(&picture);
    470     if (index < 0) {    // not found
    471         index = fPictureRefs.count();
    472         *fPictureRefs.append() = &picture;
    473         picture.ref();
    474     }
    475     // follow the convention of recording a 1-based index
    476     addInt(index + 1);
    477 }
    478 
    479 void SkPictureRecord::addPoint(const SkPoint& point) {
    480 #ifdef SK_DEBUG_SIZE
    481     size_t start = fWriter.size();
    482 #endif
    483     fWriter.writePoint(point);
    484 #ifdef SK_DEBUG_SIZE
    485     fPointBytes += fWriter.size() - start;
    486     fPointWrites++;
    487 #endif
    488 }
    489 
    490 void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
    491     fWriter.writeMul4(pts, count * sizeof(SkPoint));
    492 #ifdef SK_DEBUG_SIZE
    493     fPointBytes += count * sizeof(SkPoint);
    494     fPointWrites++;
    495 #endif
    496 }
    497 
    498 void SkPictureRecord::addRect(const SkRect& rect) {
    499 #ifdef SK_DEBUG_SIZE
    500     size_t start = fWriter.size();
    501 #endif
    502     fWriter.writeRect(rect);
    503 #ifdef SK_DEBUG_SIZE
    504     fRectBytes += fWriter.size() - start;
    505     fRectWrites++;
    506 #endif
    507 }
    508 
    509 void SkPictureRecord::addRectPtr(const SkRect* rect) {
    510     if (fWriter.writeBool(rect != NULL)) {
    511         fWriter.writeRect(*rect);
    512     }
    513 }
    514 
    515 void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
    516     if (fWriter.writeBool(rect != NULL)) {
    517         *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
    518     }
    519 }
    520 
    521 void SkPictureRecord::addRegion(const SkRegion& region) {
    522     addInt(find(fRegions, region));
    523 }
    524 
    525 void SkPictureRecord::addText(const void* text, size_t byteLength) {
    526 #ifdef SK_DEBUG_SIZE
    527     size_t start = fWriter.size();
    528 #endif
    529     addInt(byteLength);
    530     fWriter.writePad(text, byteLength);
    531 #ifdef SK_DEBUG_SIZE
    532     fTextBytes += fWriter.size() - start;
    533     fTextWrites++;
    534 #endif
    535 }
    536 
    537 ///////////////////////////////////////////////////////////////////////////////
    538 
    539 int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
    540     SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
    541                                                &fRCRecorder);
    542     int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
    543         bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    544     if (index >= 0) {
    545         (void)fHeap.unalloc(flat);
    546         return bitmaps[index]->index();
    547     }
    548     index = ~index;
    549     *bitmaps.insert(index) = flat;
    550     return fBitmapIndex++;
    551 }
    552 
    553 int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
    554     if (matrix == NULL)
    555         return 0;
    556     SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
    557     int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
    558         matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    559     if (index >= 0) {
    560         (void)fHeap.unalloc(flat);
    561         return matrices[index]->index();
    562     }
    563     index = ~index;
    564     *matrices.insert(index) = flat;
    565     return fMatrixIndex++;
    566 }
    567 
    568 int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
    569     if (paint == NULL) {
    570         return 0;
    571     }
    572 
    573     SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
    574                                              &fRCRecorder, &fTFRecorder);
    575     int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
    576         paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    577     if (index >= 0) {
    578         (void)fHeap.unalloc(flat);
    579         return paints[index]->index();
    580     }
    581 
    582     index = ~index;
    583     *paints.insert(index) = flat;
    584     return fPaintIndex++;
    585 }
    586 
    587 int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
    588     SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
    589     int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
    590         regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    591     if (index >= 0) {
    592         (void)fHeap.unalloc(flat);
    593         return regions[index]->index();
    594     }
    595     index = ~index;
    596     *regions.insert(index) = flat;
    597     return fRegionIndex++;
    598 }
    599 
    600 #ifdef SK_DEBUG_DUMP
    601 void SkPictureRecord::dumpMatrices() {
    602     int count = fMatrices.count();
    603     SkMatrix defaultMatrix;
    604     defaultMatrix.reset();
    605     for (int index = 0; index < count; index++) {
    606         const SkFlatMatrix* flatMatrix = fMatrices[index];
    607         flatMatrix->dump();
    608     }
    609 }
    610 
    611 void SkPictureRecord::dumpPaints() {
    612     int count = fPaints.count();
    613     for (int index = 0; index < count; index++)
    614         fPaints[index]->dump();
    615 }
    616 #endif
    617 
    618 #ifdef SK_DEBUG_SIZE
    619 size_t SkPictureRecord::size() const {
    620     size_t result = 0;
    621     size_t sizeData;
    622     bitmaps(&sizeData);
    623     result += sizeData;
    624     matrices(&sizeData);
    625     result += sizeData;
    626     paints(&sizeData);
    627     result += sizeData;
    628     paths(&sizeData);
    629     result += sizeData;
    630     pictures(&sizeData);
    631     result += sizeData;
    632     regions(&sizeData);
    633     result += sizeData;
    634     result += streamlen();
    635     return result;
    636 }
    637 
    638 int SkPictureRecord::bitmaps(size_t* size) const {
    639     size_t result = 0;
    640     int count = fBitmaps.count();
    641     for (int index = 0; index < count; index++)
    642         result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
    643     *size = result;
    644     return count;
    645 }
    646 
    647 int SkPictureRecord::matrices(size_t* size) const {
    648     int count = fMatrices.count();
    649     *size = sizeof(fMatrices[0]) * count;
    650     return count;
    651 }
    652 
    653 int SkPictureRecord::paints(size_t* size) const {
    654     size_t result = 0;
    655     int count = fPaints.count();
    656     for (int index = 0; index < count; index++)
    657         result += sizeof(fPaints[index]) + fPaints[index]->size();
    658     *size = result;
    659     return count;
    660 }
    661 
    662 int SkPictureRecord::paths(size_t* size) const {
    663     size_t result = 0;
    664     int count = fPaths.count();
    665     for (int index = 0; index < count; index++)
    666         result += sizeof(fPaths[index]) + fPaths[index]->size();
    667     *size = result;
    668     return count;
    669 }
    670 
    671 int SkPictureRecord::regions(size_t* size) const {
    672     size_t result = 0;
    673     int count = fRegions.count();
    674     for (int index = 0; index < count; index++)
    675         result += sizeof(fRegions[index]) + fRegions[index]->size();
    676     *size = result;
    677     return count;
    678 }
    679 
    680 size_t SkPictureRecord::streamlen() const {
    681     return fWriter.size();
    682 }
    683 #endif
    684 
    685 #ifdef SK_DEBUG_VALIDATE
    686 void SkPictureRecord::validate() const {
    687     validateBitmaps();
    688     validateMatrices();
    689     validatePaints();
    690     validatePaths();
    691     validatePictures();
    692     validateRegions();
    693 }
    694 
    695 void SkPictureRecord::validateBitmaps() const {
    696     int count = fBitmaps.count();
    697     SkASSERT((unsigned) count < 0x1000);
    698     for (int index = 0; index < count; index++) {
    699         const SkFlatBitmap* bitPtr = fBitmaps[index];
    700         SkASSERT(bitPtr);
    701         bitPtr->validate();
    702     }
    703 }
    704 
    705 void SkPictureRecord::validateMatrices() const {
    706     int count = fMatrices.count();
    707     SkASSERT((unsigned) count < 0x1000);
    708     for (int index = 0; index < count; index++) {
    709         const SkFlatMatrix* matrix = fMatrices[index];
    710         SkASSERT(matrix);
    711         matrix->validate();
    712     }
    713 }
    714 
    715 void SkPictureRecord::validatePaints() const {
    716     int count = fPaints.count();
    717     SkASSERT((unsigned) count < 0x1000);
    718     for (int index = 0; index < count; index++) {
    719         const SkFlatPaint* paint = fPaints[index];
    720         SkASSERT(paint);
    721 //            paint->validate();
    722     }
    723 }
    724 
    725 void SkPictureRecord::validatePaths() const {
    726     int count = fPaths.count();
    727     SkASSERT((unsigned) count < 0x1000);
    728     for (int index = 0; index < count; index++) {
    729         const SkFlatPath* path = fPaths[index];
    730         SkASSERT(path);
    731         path->validate();
    732     }
    733 }
    734 
    735 void SkPictureRecord::validateRegions() const {
    736     int count = fRegions.count();
    737     SkASSERT((unsigned) count < 0x1000);
    738     for (int index = 0; index < count; index++) {
    739         const SkFlatRegion* region = fRegions[index];
    740         SkASSERT(region);
    741         region->validate();
    742     }
    743 }
    744 #endif
    745 
    746