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