blob: 00e4b600ef673bb55b9a0bb00b3608fedb8e6f88 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkPictureRecord.h"
reed@android.com09b84a02009-06-26 20:22:26 +00002#include "SkShape.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00003#include "SkTSearch.h"
4
5#define MIN_WRITER_SIZE 16384
6#define HEAP_BLOCK_SIZE 4096
7
reed@android.comae814c82009-02-13 14:56:09 +00008SkPictureRecord::SkPictureRecord(uint32_t flags) :
9 fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000010 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);
reed@google.com82065d62011-02-07 15:30:46 +000018
reed@android.com8a1c16f2008-12-17 15:59:43 +000019 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);
reed@google.com82065d62011-02-07 15:30:46 +000031
reed@android.com8a1c16f2008-12-17 15:59:43 +000032 fRestoreOffsetStack.push(0);
reed@google.com82065d62011-02-07 15:30:46 +000033
reed@android.com8a1c16f2008-12-17 15:59:43 +000034 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();
reed@android.com261ae4d2009-10-02 16:37:46 +000048 /* 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);
reed@android.com8a1c16f2008-12-17 15:59:43 +000055}
56
57void SkPictureRecord::restore() {
reed@android.comb4e22d62009-07-09 15:20:25 +000058 // check for underflow
59 if (fRestoreOffsetStack.count() == 0) {
60 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +000061 }
reed@android.comb4e22d62009-07-09 15:20:25 +000062
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();
reed@android.com32a42492009-07-10 03:33:52 +000072
reed@android.com8a1c16f2008-12-17 15:59:43 +000073 addDraw(RESTORE);
74 validate();
75 return this->INHERITED::restore();
76}
77
78bool 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
86bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
reed@google.com82065d62011-02-07 15:30:46 +000087 addDraw(SCALE);
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 addScalar(sx);
89 addScalar(sy);
90 validate();
91 return this->INHERITED::scale(sx, sy);
92}
93
94bool SkPictureRecord::rotate(SkScalar degrees) {
reed@google.com82065d62011-02-07 15:30:46 +000095 addDraw(ROTATE);
96 addScalar(degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +000097 validate();
98 return this->INHERITED::rotate(degrees);
99}
100
101bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
reed@google.com82065d62011-02-07 15:30:46 +0000102 addDraw(SKEW);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103 addScalar(sx);
104 addScalar(sy);
105 validate();
106 return this->INHERITED::skew(sx, sy);
107}
108
109bool SkPictureRecord::concat(const SkMatrix& matrix) {
110 validate();
111 addDraw(CONCAT);
112 addMatrix(matrix);
113 validate();
114 return this->INHERITED::concat(matrix);
115}
116
reed@android.com6e073b92009-01-06 15:03:30 +0000117void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
118 validate();
119 addDraw(SET_MATRIX);
120 addMatrix(matrix);
121 validate();
122 this->INHERITED::setMatrix(matrix);
123}
124
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op) {
126 addDraw(CLIP_RECT);
127 addRect(rect);
128 addInt(op);
reed@google.com82065d62011-02-07 15:30:46 +0000129
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 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
138bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op) {
139 addDraw(CLIP_PATH);
140 addPath(path);
141 addInt(op);
reed@google.com82065d62011-02-07 15:30:46 +0000142
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 size_t offset = fWriter.size();
144 addInt(fRestoreOffsetStack.top());
145 fRestoreOffsetStack.top() = offset;
reed@google.com82065d62011-02-07 15:30:46 +0000146
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147 validate();
reed@google.com82065d62011-02-07 15:30:46 +0000148
reed@android.comae814c82009-02-13 14:56:09 +0000149 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
reed@android.comd252db02009-04-01 18:31:44 +0000150 return this->INHERITED::clipRect(path.getBounds(), op);
reed@android.comae814c82009-02-13 14:56:09 +0000151 } else {
152 return this->INHERITED::clipPath(path, op);
153 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154}
155
156bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
reed@google.com82065d62011-02-07 15:30:46 +0000157 addDraw(CLIP_REGION);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158 addRegion(region);
159 addInt(op);
reed@google.com82065d62011-02-07 15:30:46 +0000160
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161 size_t offset = fWriter.size();
162 addInt(fRestoreOffsetStack.top());
163 fRestoreOffsetStack.top() = offset;
reed@google.com82065d62011-02-07 15:30:46 +0000164
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165 validate();
166 return this->INHERITED::clipRegion(region, op);
167}
168
169void SkPictureRecord::drawPaint(const SkPaint& paint) {
170 addDraw(DRAW_PAINT);
171 addPaint(paint);
172 validate();
173}
174
175void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
176 const SkPaint& paint) {
177 addDraw(DRAW_POINTS);
178 addPaint(paint);
179 addInt(mode);
180 addInt(count);
181 fWriter.writeMul4(pts, count * sizeof(SkPoint));
182 validate();
183}
184
185void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
186 addDraw(DRAW_RECT);
187 addPaint(paint);
188 addRect(rect);
189 validate();
190}
191
192void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
193 addDraw(DRAW_PATH);
194 addPaint(paint);
195 addPath(path);
196 validate();
197}
198
199void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
200 const SkPaint* paint = NULL) {
201 addDraw(DRAW_BITMAP);
202 addPaintPtr(paint);
203 addBitmap(bitmap);
204 addScalar(left);
205 addScalar(top);
206 validate();
207}
208
209void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
210 const SkRect& dst, const SkPaint* paint) {
211 addDraw(DRAW_BITMAP_RECT);
212 addPaintPtr(paint);
213 addBitmap(bitmap);
214 addIRectPtr(src); // may be null
215 addRect(dst);
216 validate();
217}
218
219void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
220 const SkPaint* paint) {
221 addDraw(DRAW_BITMAP_MATRIX);
222 addPaintPtr(paint);
223 addBitmap(bitmap);
224 addMatrix(matrix);
225 validate();
226}
227
228void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
229 const SkPaint* paint = NULL) {
230 addDraw(DRAW_SPRITE);
231 addPaintPtr(paint);
232 addBitmap(bitmap);
233 addInt(left);
234 addInt(top);
235 validate();
236}
237
238void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
239 SkScalar baselineY) {
240 SkPaint::FontMetrics metrics;
241 paint.getFontMetrics(&metrics);
242 SkRect bounds;
243 // construct a rect so we can see any adjustments from the paint.
244 // we use 0,1 for left,right, just so the rect isn't empty
245 bounds.set(0, metrics.fTop + baselineY,
246 SK_Scalar1, metrics.fBottom + baselineY);
247 (void)paint.computeFastBounds(bounds, &bounds);
248 // now record the top and bottom
249 addScalar(bounds.fTop);
250 addScalar(bounds.fBottom);
251}
252
reed@google.com82065d62011-02-07 15:30:46 +0000253void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254 SkScalar y, const SkPaint& paint) {
255 bool fast = paint.canComputeFastBounds();
reed@google.com82065d62011-02-07 15:30:46 +0000256
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
258 addPaint(paint);
259 addText(text, byteLength);
260 addScalar(x);
261 addScalar(y);
262 if (fast) {
263 addFontMetricsTopBottom(paint, y);
264 }
265 validate();
266}
267
reed@google.com82065d62011-02-07 15:30:46 +0000268void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269 const SkPoint pos[], const SkPaint& paint) {
270 size_t points = paint.countText(text, byteLength);
271 if (0 == points)
272 return;
273
274 bool canUseDrawH = true;
275 // check if the caller really should have used drawPosTextH()
276 {
277 const SkScalar firstY = pos[0].fY;
278 for (size_t index = 1; index < points; index++) {
279 if (pos[index].fY != firstY) {
280 canUseDrawH = false;
281 break;
282 }
283 }
284 }
reed@google.com82065d62011-02-07 15:30:46 +0000285
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286 bool fast = canUseDrawH && paint.canComputeFastBounds();
287
288 if (fast) {
289 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
290 } else {
291 addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
292 }
293 addPaint(paint);
294 addText(text, byteLength);
295 addInt(points);
296
297#ifdef SK_DEBUG_SIZE
298 size_t start = fWriter.size();
299#endif
300 if (canUseDrawH) {
301 if (fast) {
302 addFontMetricsTopBottom(paint, pos[0].fY);
303 }
304 addScalar(pos[0].fY);
305 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
reed@google.com82065d62011-02-07 15:30:46 +0000306 for (size_t index = 0; index < points; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307 *xptr++ = pos[index].fX;
308 }
309 else {
310 fWriter.writeMul4(pos, points * sizeof(SkPoint));
311 }
312#ifdef SK_DEBUG_SIZE
313 fPointBytes += fWriter.size() - start;
314 fPointWrites += points;
315#endif
316 validate();
317}
318
319void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
320 const SkScalar xpos[], SkScalar constY,
321 const SkPaint& paint) {
322 size_t points = paint.countText(text, byteLength);
323 if (0 == points)
324 return;
reed@google.com82065d62011-02-07 15:30:46 +0000325
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 bool fast = paint.canComputeFastBounds();
327
328 addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
329 addPaint(paint);
330 addText(text, byteLength);
331 addInt(points);
reed@google.com82065d62011-02-07 15:30:46 +0000332
reed@android.com8a1c16f2008-12-17 15:59:43 +0000333#ifdef SK_DEBUG_SIZE
334 size_t start = fWriter.size();
335#endif
336 if (fast) {
337 addFontMetricsTopBottom(paint, constY);
338 }
339 addScalar(constY);
340 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
341#ifdef SK_DEBUG_SIZE
342 fPointBytes += fWriter.size() - start;
343 fPointWrites += points;
344#endif
345 validate();
346}
347
reed@google.com82065d62011-02-07 15:30:46 +0000348void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
349 const SkPath& path, const SkMatrix* matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 const SkPaint& paint) {
351 addDraw(DRAW_TEXT_ON_PATH);
352 addPaint(paint);
353 addText(text, byteLength);
354 addPath(path);
355 addMatrixPtr(matrix);
356 validate();
357}
358
359void SkPictureRecord::drawPicture(SkPicture& picture) {
360 addDraw(DRAW_PICTURE);
361 addPicture(picture);
362 validate();
363}
364
reed@android.com09b84a02009-06-26 20:22:26 +0000365void SkPictureRecord::drawShape(SkShape* shape) {
366 addDraw(DRAW_SHAPE);
367
368 int index = fShapes.find(shape);
369 if (index < 0) { // not found
370 index = fShapes.count();
371 *fShapes.append() = shape;
372 shape->ref();
373 }
374 // follow the convention of recording a 1-based index
375 addInt(index + 1);
376 validate();
377}
378
reed@android.com8a1c16f2008-12-17 15:59:43 +0000379void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
380 const SkPoint vertices[], const SkPoint texs[],
381 const SkColor colors[], SkXfermode*,
382 const uint16_t indices[], int indexCount,
383 const SkPaint& paint) {
384 uint32_t flags = 0;
385 if (texs) {
386 flags |= DRAW_VERTICES_HAS_TEXS;
387 }
388 if (colors) {
389 flags |= DRAW_VERTICES_HAS_COLORS;
390 }
391 if (indexCount > 0) {
392 flags |= DRAW_VERTICES_HAS_INDICES;
393 }
394
395 addDraw(DRAW_VERTICES);
396 addPaint(paint);
397 addInt(flags);
398 addInt(vmode);
399 addInt(vertexCount);
400 addPoints(vertices, vertexCount);
401 if (flags & DRAW_VERTICES_HAS_TEXS) {
402 addPoints(texs, vertexCount);
403 }
404 if (flags & DRAW_VERTICES_HAS_COLORS) {
405 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
406 }
407 if (flags & DRAW_VERTICES_HAS_INDICES) {
408 addInt(indexCount);
409 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
410 }
411}
412
reed@android.comcb608442009-12-04 21:32:27 +0000413void SkPictureRecord::drawData(const void* data, size_t length) {
414 addDraw(DRAW_DATA);
415 addInt(length);
416 fWriter.writePad(data, length);
417}
418
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000420
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421void SkPictureRecord::reset() {
reed@google.com82065d62011-02-07 15:30:46 +0000422 SkSafeUnref(fPathHeap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 fPathHeap = NULL;
424
425 fBitmaps.reset();
426 fMatrices.reset();
427 fPaints.reset();
428 fPictureRefs.unrefAll();
429 fRegions.reset();
reed@android.com8433b5d2009-07-03 02:52:27 +0000430 fShapes.safeUnrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 fWriter.reset();
432 fHeap.reset();
reed@google.com82065d62011-02-07 15:30:46 +0000433
reed@android.com8a1c16f2008-12-17 15:59:43 +0000434 fRestoreOffsetStack.setCount(1);
435 fRestoreOffsetStack.top() = 0;
reed@google.com82065d62011-02-07 15:30:46 +0000436
reed@android.com8a1c16f2008-12-17 15:59:43 +0000437 fRCRecorder.reset();
438 fTFRecorder.reset();
439}
440
441void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
442 addInt(find(fBitmaps, bitmap));
443}
444
445void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
446 addMatrixPtr(&matrix);
447}
448
449void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
450 addInt(find(fMatrices, matrix));
451}
452
453void SkPictureRecord::addPaint(const SkPaint& paint) {
454 addPaintPtr(&paint);
455}
456
457void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
458 addInt(find(fPaints, paint));
459}
460
461void SkPictureRecord::addPath(const SkPath& path) {
462 if (NULL == fPathHeap) {
463 fPathHeap = SkNEW(SkPathHeap);
464 }
465 addInt(fPathHeap->append(path));
466}
467
468void SkPictureRecord::addPicture(SkPicture& picture) {
469 int index = fPictureRefs.find(&picture);
470 if (index < 0) { // not found
471 index = fPictureRefs.count();
472 *fPictureRefs.append() = &picture;
473 picture.ref();
474 }
475 // follow the convention of recording a 1-based index
476 addInt(index + 1);
477}
478
479void SkPictureRecord::addPoint(const SkPoint& point) {
480#ifdef SK_DEBUG_SIZE
481 size_t start = fWriter.size();
482#endif
483 fWriter.writePoint(point);
484#ifdef SK_DEBUG_SIZE
485 fPointBytes += fWriter.size() - start;
486 fPointWrites++;
487#endif
488}
reed@google.com82065d62011-02-07 15:30:46 +0000489
reed@android.com8a1c16f2008-12-17 15:59:43 +0000490void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
491 fWriter.writeMul4(pts, count * sizeof(SkPoint));
492#ifdef SK_DEBUG_SIZE
493 fPointBytes += count * sizeof(SkPoint);
494 fPointWrites++;
495#endif
496}
497
498void SkPictureRecord::addRect(const SkRect& rect) {
499#ifdef SK_DEBUG_SIZE
500 size_t start = fWriter.size();
501#endif
502 fWriter.writeRect(rect);
503#ifdef SK_DEBUG_SIZE
504 fRectBytes += fWriter.size() - start;
505 fRectWrites++;
506#endif
507}
508
509void SkPictureRecord::addRectPtr(const SkRect* rect) {
510 if (fWriter.writeBool(rect != NULL)) {
511 fWriter.writeRect(*rect);
512 }
513}
514
515void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
516 if (fWriter.writeBool(rect != NULL)) {
517 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
518 }
519}
520
521void SkPictureRecord::addRegion(const SkRegion& region) {
522 addInt(find(fRegions, region));
523}
524
525void SkPictureRecord::addText(const void* text, size_t byteLength) {
526#ifdef SK_DEBUG_SIZE
527 size_t start = fWriter.size();
528#endif
529 addInt(byteLength);
530 fWriter.writePad(text, byteLength);
531#ifdef SK_DEBUG_SIZE
532 fTextBytes += fWriter.size() - start;
533 fTextWrites++;
534#endif
535}
536
537///////////////////////////////////////////////////////////////////////////////
538
539int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
540 SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
541 &fRCRecorder);
reed@google.com82065d62011-02-07 15:30:46 +0000542 int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000543 bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
544 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000545 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000546 return bitmaps[index]->index();
547 }
548 index = ~index;
549 *bitmaps.insert(index) = flat;
550 return fBitmapIndex++;
551}
552
553int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
554 if (matrix == NULL)
555 return 0;
556 SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000557 int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000558 matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000559 if (index >= 0) {
560 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561 return matrices[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000562 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000563 index = ~index;
564 *matrices.insert(index) = flat;
565 return fMatrixIndex++;
566}
567
568int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
569 if (paint == NULL) {
570 return 0;
571 }
reed@google.com82065d62011-02-07 15:30:46 +0000572
reed@android.com8a1c16f2008-12-17 15:59:43 +0000573 SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
574 &fRCRecorder, &fTFRecorder);
reed@google.com82065d62011-02-07 15:30:46 +0000575 int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000576 paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
577 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000578 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000579 return paints[index]->index();
580 }
581
582 index = ~index;
583 *paints.insert(index) = flat;
584 return fPaintIndex++;
585}
586
587int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
588 SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000589 int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590 regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000591 if (index >= 0) {
592 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000593 return regions[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000594 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000595 index = ~index;
596 *regions.insert(index) = flat;
597 return fRegionIndex++;
598}
599
600#ifdef SK_DEBUG_DUMP
601void SkPictureRecord::dumpMatrices() {
602 int count = fMatrices.count();
603 SkMatrix defaultMatrix;
604 defaultMatrix.reset();
605 for (int index = 0; index < count; index++) {
606 const SkFlatMatrix* flatMatrix = fMatrices[index];
607 flatMatrix->dump();
608 }
609}
610
611void SkPictureRecord::dumpPaints() {
612 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000613 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000614 fPaints[index]->dump();
615}
616#endif
617
618#ifdef SK_DEBUG_SIZE
619size_t SkPictureRecord::size() const {
620 size_t result = 0;
621 size_t sizeData;
622 bitmaps(&sizeData);
623 result += sizeData;
624 matrices(&sizeData);
625 result += sizeData;
626 paints(&sizeData);
627 result += sizeData;
628 paths(&sizeData);
629 result += sizeData;
630 pictures(&sizeData);
631 result += sizeData;
632 regions(&sizeData);
633 result += sizeData;
634 result += streamlen();
635 return result;
636}
637
638int SkPictureRecord::bitmaps(size_t* size) const {
639 size_t result = 0;
640 int count = fBitmaps.count();
reed@google.com82065d62011-02-07 15:30:46 +0000641 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000642 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
643 *size = result;
644 return count;
645}
646
647int SkPictureRecord::matrices(size_t* size) const {
648 int count = fMatrices.count();
649 *size = sizeof(fMatrices[0]) * count;
650 return count;
651}
652
653int SkPictureRecord::paints(size_t* size) const {
654 size_t result = 0;
655 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000656 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000657 result += sizeof(fPaints[index]) + fPaints[index]->size();
658 *size = result;
659 return count;
660}
661
662int SkPictureRecord::paths(size_t* size) const {
663 size_t result = 0;
664 int count = fPaths.count();
reed@google.com82065d62011-02-07 15:30:46 +0000665 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000666 result += sizeof(fPaths[index]) + fPaths[index]->size();
667 *size = result;
668 return count;
669}
670
671int SkPictureRecord::regions(size_t* size) const {
672 size_t result = 0;
673 int count = fRegions.count();
reed@google.com82065d62011-02-07 15:30:46 +0000674 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675 result += sizeof(fRegions[index]) + fRegions[index]->size();
676 *size = result;
677 return count;
678}
679
680size_t SkPictureRecord::streamlen() const {
681 return fWriter.size();
682}
683#endif
684
685#ifdef SK_DEBUG_VALIDATE
686void SkPictureRecord::validate() const {
687 validateBitmaps();
688 validateMatrices();
689 validatePaints();
690 validatePaths();
691 validatePictures();
692 validateRegions();
693}
694
695void SkPictureRecord::validateBitmaps() const {
696 int count = fBitmaps.count();
697 SkASSERT((unsigned) count < 0x1000);
698 for (int index = 0; index < count; index++) {
699 const SkFlatBitmap* bitPtr = fBitmaps[index];
700 SkASSERT(bitPtr);
701 bitPtr->validate();
702 }
703}
704
705void SkPictureRecord::validateMatrices() const {
706 int count = fMatrices.count();
707 SkASSERT((unsigned) count < 0x1000);
708 for (int index = 0; index < count; index++) {
709 const SkFlatMatrix* matrix = fMatrices[index];
710 SkASSERT(matrix);
reed@google.com82065d62011-02-07 15:30:46 +0000711 matrix->validate();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712 }
713}
714
715void SkPictureRecord::validatePaints() const {
716 int count = fPaints.count();
717 SkASSERT((unsigned) count < 0x1000);
718 for (int index = 0; index < count; index++) {
719 const SkFlatPaint* paint = fPaints[index];
720 SkASSERT(paint);
721// paint->validate();
722 }
723}
724
725void SkPictureRecord::validatePaths() const {
726 int count = fPaths.count();
727 SkASSERT((unsigned) count < 0x1000);
728 for (int index = 0; index < count; index++) {
729 const SkFlatPath* path = fPaths[index];
730 SkASSERT(path);
731 path->validate();
732 }
733}
734
735void SkPictureRecord::validateRegions() const {
736 int count = fRegions.count();
737 SkASSERT((unsigned) count < 0x1000);
738 for (int index = 0; index < count; index++) {
739 const SkFlatRegion* region = fRegions[index];
740 SkASSERT(region);
741 region->validate();
742 }
743}
744#endif
745