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::clear(SkColor color) {
    170     addDraw(DRAW_CLEAR);
    171     addInt(color);
    172     validate();
    173 }
    174 
    175 void SkPictureRecord::drawPaint(const SkPaint& paint) {
    176     addDraw(DRAW_PAINT);
    177     addPaint(paint);
    178     validate();
    179 }
    180 
    181 void 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 
    191 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
    192     addDraw(DRAW_RECT);
    193     addPaint(paint);
    194     addRect(rect);
    195     validate();
    196 }
    197 
    198 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
    199     addDraw(DRAW_PATH);
    200     addPaint(paint);
    201     addPath(path);
    202     validate();
    203 }
    204 
    205 void 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 
    215 void 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 
    225 void 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 
    234 void 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 
    244 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
    245                                               SkScalar minY, SkScalar maxY) {
    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 + minY,
    252                SK_Scalar1, metrics.fBottom + maxY);
    253     (void)paint.computeFastBounds(bounds, &bounds);
    254     // now record the top and bottom
    255     addScalar(bounds.fTop);
    256     addScalar(bounds.fBottom);
    257 }
    258 
    259 void 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, y);
    270     }
    271     validate();
    272 }
    273 
    274 void 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     SkScalar minY = pos[0].fY;
    282     SkScalar maxY = pos[0].fY;
    283     // check if the caller really should have used drawPosTextH()
    284     {
    285         const SkScalar firstY = pos[0].fY;
    286         for (size_t index = 1; index < points; index++) {
    287             if (pos[index].fY != firstY) {
    288                 canUseDrawH = false;
    289                 if (pos[index].fY < minY) {
    290                     minY = pos[index].fY;
    291                 } else if (pos[index].fY > maxY) {
    292                     maxY = pos[index].fY;
    293                 }
    294             }
    295         }
    296     }
    297 
    298     bool fastBounds = paint.canComputeFastBounds();
    299     bool fast = canUseDrawH && fastBounds;
    300 
    301     if (fast) {
    302         addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
    303     } else if (canUseDrawH) {
    304         addDraw(DRAW_POS_TEXT_H);
    305     } else if (fastBounds) {
    306         addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
    307     } else {
    308         addDraw(DRAW_POS_TEXT);
    309     }
    310     addPaint(paint);
    311     addText(text, byteLength);
    312     addInt(points);
    313 
    314 #ifdef SK_DEBUG_SIZE
    315     size_t start = fWriter.size();
    316 #endif
    317     if (canUseDrawH) {
    318         if (fast) {
    319             addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
    320         }
    321         addScalar(pos[0].fY);
    322         SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
    323         for (size_t index = 0; index < points; index++)
    324             *xptr++ = pos[index].fX;
    325     }
    326     else {
    327         fWriter.writeMul4(pos, points * sizeof(SkPoint));
    328         if (fastBounds) {
    329             addFontMetricsTopBottom(paint, minY, maxY);
    330         }
    331     }
    332 #ifdef SK_DEBUG_SIZE
    333     fPointBytes += fWriter.size() - start;
    334     fPointWrites += points;
    335 #endif
    336     validate();
    337 }
    338 
    339 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
    340                           const SkScalar xpos[], SkScalar constY,
    341                           const SkPaint& paint) {
    342     size_t points = paint.countText(text, byteLength);
    343     if (0 == points)
    344         return;
    345 
    346     bool fast = paint.canComputeFastBounds();
    347 
    348     addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
    349     addPaint(paint);
    350     addText(text, byteLength);
    351     addInt(points);
    352 
    353 #ifdef SK_DEBUG_SIZE
    354     size_t start = fWriter.size();
    355 #endif
    356     if (fast) {
    357         addFontMetricsTopBottom(paint, constY, constY);
    358     }
    359     addScalar(constY);
    360     fWriter.writeMul4(xpos, points * sizeof(SkScalar));
    361 #ifdef SK_DEBUG_SIZE
    362     fPointBytes += fWriter.size() - start;
    363     fPointWrites += points;
    364 #endif
    365     validate();
    366 }
    367 
    368 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
    369                             const SkPath& path, const SkMatrix* matrix,
    370                             const SkPaint& paint) {
    371     addDraw(DRAW_TEXT_ON_PATH);
    372     addPaint(paint);
    373     addText(text, byteLength);
    374     addPath(path);
    375     addMatrixPtr(matrix);
    376     validate();
    377 }
    378 
    379 void SkPictureRecord::drawPicture(SkPicture& picture) {
    380     addDraw(DRAW_PICTURE);
    381     addPicture(picture);
    382     validate();
    383 }
    384 
    385 void SkPictureRecord::drawShape(SkShape* shape) {
    386     addDraw(DRAW_SHAPE);
    387 
    388     int index = fShapes.find(shape);
    389     if (index < 0) {    // not found
    390         index = fShapes.count();
    391         *fShapes.append() = shape;
    392         shape->ref();
    393     }
    394     // follow the convention of recording a 1-based index
    395     addInt(index + 1);
    396     validate();
    397 }
    398 
    399 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
    400                           const SkPoint vertices[], const SkPoint texs[],
    401                           const SkColor colors[], SkXfermode*,
    402                           const uint16_t indices[], int indexCount,
    403                           const SkPaint& paint) {
    404     uint32_t flags = 0;
    405     if (texs) {
    406         flags |= DRAW_VERTICES_HAS_TEXS;
    407     }
    408     if (colors) {
    409         flags |= DRAW_VERTICES_HAS_COLORS;
    410     }
    411     if (indexCount > 0) {
    412         flags |= DRAW_VERTICES_HAS_INDICES;
    413     }
    414 
    415     addDraw(DRAW_VERTICES);
    416     addPaint(paint);
    417     addInt(flags);
    418     addInt(vmode);
    419     addInt(vertexCount);
    420     addPoints(vertices, vertexCount);
    421     if (flags & DRAW_VERTICES_HAS_TEXS) {
    422         addPoints(texs, vertexCount);
    423     }
    424     if (flags & DRAW_VERTICES_HAS_COLORS) {
    425         fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
    426     }
    427     if (flags & DRAW_VERTICES_HAS_INDICES) {
    428         addInt(indexCount);
    429         fWriter.writePad(indices, indexCount * sizeof(uint16_t));
    430     }
    431 }
    432 
    433 void SkPictureRecord::drawData(const void* data, size_t length) {
    434     addDraw(DRAW_DATA);
    435     addInt(length);
    436     fWriter.writePad(data, length);
    437 }
    438 
    439 ///////////////////////////////////////////////////////////////////////////////
    440 
    441 void SkPictureRecord::reset() {
    442     SkSafeUnref(fPathHeap);
    443     fPathHeap = NULL;
    444 
    445     fBitmaps.reset();
    446     fMatrices.reset();
    447     fPaints.reset();
    448     fPictureRefs.unrefAll();
    449     fRegions.reset();
    450     fShapes.safeUnrefAll();
    451     fWriter.reset();
    452     fHeap.reset();
    453 
    454     fRestoreOffsetStack.setCount(1);
    455     fRestoreOffsetStack.top() = 0;
    456 
    457     fRCSet.reset();
    458     fTFSet.reset();
    459 }
    460 
    461 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
    462     addInt(find(fBitmaps, bitmap));
    463 }
    464 
    465 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
    466     addMatrixPtr(&matrix);
    467 }
    468 
    469 void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
    470     addInt(find(fMatrices, matrix));
    471 }
    472 
    473 void SkPictureRecord::addPaint(const SkPaint& paint) {
    474     addPaintPtr(&paint);
    475 }
    476 
    477 void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
    478     addInt(find(fPaints, paint));
    479 }
    480 
    481 void SkPictureRecord::addPath(const SkPath& path) {
    482     if (NULL == fPathHeap) {
    483         fPathHeap = SkNEW(SkPathHeap);
    484     }
    485     addInt(fPathHeap->append(path));
    486 }
    487 
    488 void SkPictureRecord::addPicture(SkPicture& picture) {
    489     int index = fPictureRefs.find(&picture);
    490     if (index < 0) {    // not found
    491         index = fPictureRefs.count();
    492         *fPictureRefs.append() = &picture;
    493         picture.ref();
    494     }
    495     // follow the convention of recording a 1-based index
    496     addInt(index + 1);
    497 }
    498 
    499 void SkPictureRecord::addPoint(const SkPoint& point) {
    500 #ifdef SK_DEBUG_SIZE
    501     size_t start = fWriter.size();
    502 #endif
    503     fWriter.writePoint(point);
    504 #ifdef SK_DEBUG_SIZE
    505     fPointBytes += fWriter.size() - start;
    506     fPointWrites++;
    507 #endif
    508 }
    509 
    510 void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
    511     fWriter.writeMul4(pts, count * sizeof(SkPoint));
    512 #ifdef SK_DEBUG_SIZE
    513     fPointBytes += count * sizeof(SkPoint);
    514     fPointWrites++;
    515 #endif
    516 }
    517 
    518 void SkPictureRecord::addRect(const SkRect& rect) {
    519 #ifdef SK_DEBUG_SIZE
    520     size_t start = fWriter.size();
    521 #endif
    522     fWriter.writeRect(rect);
    523 #ifdef SK_DEBUG_SIZE
    524     fRectBytes += fWriter.size() - start;
    525     fRectWrites++;
    526 #endif
    527 }
    528 
    529 void SkPictureRecord::addRectPtr(const SkRect* rect) {
    530     if (fWriter.writeBool(rect != NULL)) {
    531         fWriter.writeRect(*rect);
    532     }
    533 }
    534 
    535 void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
    536     if (fWriter.writeBool(rect != NULL)) {
    537         *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
    538     }
    539 }
    540 
    541 void SkPictureRecord::addRegion(const SkRegion& region) {
    542     addInt(find(fRegions, region));
    543 }
    544 
    545 void SkPictureRecord::addText(const void* text, size_t byteLength) {
    546 #ifdef SK_DEBUG_SIZE
    547     size_t start = fWriter.size();
    548 #endif
    549     addInt(byteLength);
    550     fWriter.writePad(text, byteLength);
    551 #ifdef SK_DEBUG_SIZE
    552     fTextBytes += fWriter.size() - start;
    553     fTextWrites++;
    554 #endif
    555 }
    556 
    557 ///////////////////////////////////////////////////////////////////////////////
    558 
    559 int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
    560     SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
    561                                                &fRCSet);
    562     int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
    563         bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    564     if (index >= 0) {
    565         (void)fHeap.unalloc(flat);
    566         return bitmaps[index]->index();
    567     }
    568     index = ~index;
    569     *bitmaps.insert(index) = flat;
    570     return fBitmapIndex++;
    571 }
    572 
    573 int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
    574     if (matrix == NULL)
    575         return 0;
    576     SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
    577     int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
    578         matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    579     if (index >= 0) {
    580         (void)fHeap.unalloc(flat);
    581         return matrices[index]->index();
    582     }
    583     index = ~index;
    584     *matrices.insert(index) = flat;
    585     return fMatrixIndex++;
    586 }
    587 
    588 int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
    589     if (paint == NULL) {
    590         return 0;
    591     }
    592 
    593     SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
    594                                              &fRCSet, &fTFSet);
    595     int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
    596         paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    597     if (index >= 0) {
    598         (void)fHeap.unalloc(flat);
    599         return paints[index]->index();
    600     }
    601 
    602     index = ~index;
    603     *paints.insert(index) = flat;
    604     return fPaintIndex++;
    605 }
    606 
    607 int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
    608     SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
    609     int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
    610         regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
    611     if (index >= 0) {
    612         (void)fHeap.unalloc(flat);
    613         return regions[index]->index();
    614     }
    615     index = ~index;
    616     *regions.insert(index) = flat;
    617     return fRegionIndex++;
    618 }
    619 
    620 #ifdef SK_DEBUG_DUMP
    621 void SkPictureRecord::dumpMatrices() {
    622     int count = fMatrices.count();
    623     SkMatrix defaultMatrix;
    624     defaultMatrix.reset();
    625     for (int index = 0; index < count; index++) {
    626         const SkFlatMatrix* flatMatrix = fMatrices[index];
    627         flatMatrix->dump();
    628     }
    629 }
    630 
    631 void SkPictureRecord::dumpPaints() {
    632     int count = fPaints.count();
    633     for (int index = 0; index < count; index++)
    634         fPaints[index]->dump();
    635 }
    636 #endif
    637 
    638 #ifdef SK_DEBUG_SIZE
    639 size_t SkPictureRecord::size() const {
    640     size_t result = 0;
    641     size_t sizeData;
    642     bitmaps(&sizeData);
    643     result += sizeData;
    644     matrices(&sizeData);
    645     result += sizeData;
    646     paints(&sizeData);
    647     result += sizeData;
    648     paths(&sizeData);
    649     result += sizeData;
    650     pictures(&sizeData);
    651     result += sizeData;
    652     regions(&sizeData);
    653     result += sizeData;
    654     result += streamlen();
    655     return result;
    656 }
    657 
    658 int SkPictureRecord::bitmaps(size_t* size) const {
    659     size_t result = 0;
    660     int count = fBitmaps.count();
    661     for (int index = 0; index < count; index++)
    662         result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
    663     *size = result;
    664     return count;
    665 }
    666 
    667 int SkPictureRecord::matrices(size_t* size) const {
    668     int count = fMatrices.count();
    669     *size = sizeof(fMatrices[0]) * count;
    670     return count;
    671 }
    672 
    673 int SkPictureRecord::paints(size_t* size) const {
    674     size_t result = 0;
    675     int count = fPaints.count();
    676     for (int index = 0; index < count; index++)
    677         result += sizeof(fPaints[index]) + fPaints[index]->size();
    678     *size = result;
    679     return count;
    680 }
    681 
    682 int SkPictureRecord::paths(size_t* size) const {
    683     size_t result = 0;
    684     int count = fPaths.count();
    685     for (int index = 0; index < count; index++)
    686         result += sizeof(fPaths[index]) + fPaths[index]->size();
    687     *size = result;
    688     return count;
    689 }
    690 
    691 int SkPictureRecord::regions(size_t* size) const {
    692     size_t result = 0;
    693     int count = fRegions.count();
    694     for (int index = 0; index < count; index++)
    695         result += sizeof(fRegions[index]) + fRegions[index]->size();
    696     *size = result;
    697     return count;
    698 }
    699 
    700 size_t SkPictureRecord::streamlen() const {
    701     return fWriter.size();
    702 }
    703 #endif
    704 
    705 #ifdef SK_DEBUG_VALIDATE
    706 void SkPictureRecord::validate() const {
    707     validateBitmaps();
    708     validateMatrices();
    709     validatePaints();
    710     validatePaths();
    711     validatePictures();
    712     validateRegions();
    713 }
    714 
    715 void SkPictureRecord::validateBitmaps() const {
    716     int count = fBitmaps.count();
    717     SkASSERT((unsigned) count < 0x1000);
    718     for (int index = 0; index < count; index++) {
    719         const SkFlatBitmap* bitPtr = fBitmaps[index];
    720         SkASSERT(bitPtr);
    721         bitPtr->validate();
    722     }
    723 }
    724 
    725 void SkPictureRecord::validateMatrices() const {
    726     int count = fMatrices.count();
    727     SkASSERT((unsigned) count < 0x1000);
    728     for (int index = 0; index < count; index++) {
    729         const SkFlatMatrix* matrix = fMatrices[index];
    730         SkASSERT(matrix);
    731         matrix->validate();
    732     }
    733 }
    734 
    735 void SkPictureRecord::validatePaints() const {
    736     int count = fPaints.count();
    737     SkASSERT((unsigned) count < 0x1000);
    738     for (int index = 0; index < count; index++) {
    739         const SkFlatPaint* paint = fPaints[index];
    740         SkASSERT(paint);
    741 //            paint->validate();
    742     }
    743 }
    744 
    745 void SkPictureRecord::validatePaths() const {
    746     int count = fPaths.count();
    747     SkASSERT((unsigned) count < 0x1000);
    748     for (int index = 0; index < count; index++) {
    749         const SkFlatPath* path = fPaths[index];
    750         SkASSERT(path);
    751         path->validate();
    752     }
    753 }
    754 
    755 void SkPictureRecord::validateRegions() const {
    756     int count = fRegions.count();
    757     SkASSERT((unsigned) count < 0x1000);
    758     for (int index = 0; index < count; index++) {
    759         const SkFlatRegion* region = fRegions[index];
    760         SkASSERT(region);
    761         region->validate();
    762     }
    763 }
    764 #endif
    765 
    766