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