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