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