blob: 5d35f74eddd0bb9c8a355d77bac166120d581fe8 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPictureRecord.h"
9#include "SkTSearch.h"
10
11#define MIN_WRITER_SIZE 16384
12#define HEAP_BLOCK_SIZE 4096
13
reed@android.comae814c82009-02-13 14:56:09 +000014SkPictureRecord::SkPictureRecord(uint32_t flags) :
15 fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000016 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);
reed@google.com82065d62011-02-07 15:30:46 +000024
reed@android.com8a1c16f2008-12-17 15:59:43 +000025 fPathHeap = NULL; // lazy allocate
26}
27
28SkPictureRecord::~SkPictureRecord() {
29 reset();
30}
31
32///////////////////////////////////////////////////////////////////////////////
33
34int SkPictureRecord::save(SaveFlags flags) {
35 addDraw(SAVE);
36 addInt(flags);
reed@google.com82065d62011-02-07 15:30:46 +000037
reed@android.com8a1c16f2008-12-17 15:59:43 +000038 fRestoreOffsetStack.push(0);
reed@google.com82065d62011-02-07 15:30:46 +000039
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 validate();
41 return this->INHERITED::save(flags);
42}
43
44int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
45 SaveFlags flags) {
46 addDraw(SAVE_LAYER);
47 addRectPtr(bounds);
48 addPaintPtr(paint);
49 addInt(flags);
50
51 fRestoreOffsetStack.push(0);
52
53 validate();
reed@android.com261ae4d2009-10-02 16:37:46 +000054 /* Don't actually call saveLayer, because that will try to allocate an
55 offscreen device (potentially very big) which we don't actually need
56 at this time (and may not be able to afford since during record our
57 clip starts out the size of the picture, which is often much larger
58 than the size of the actual device we'll use during playback).
59 */
60 return this->INHERITED::save(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000061}
62
63void SkPictureRecord::restore() {
reed@android.comb4e22d62009-07-09 15:20:25 +000064 // check for underflow
65 if (fRestoreOffsetStack.count() == 0) {
66 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 }
reed@android.comb4e22d62009-07-09 15:20:25 +000068
69 // patch up the clip offsets
70 uint32_t restoreOffset = (uint32_t)fWriter.size();
71 uint32_t offset = fRestoreOffsetStack.top();
72 while (offset) {
73 uint32_t* peek = fWriter.peek32(offset);
74 offset = *peek;
75 *peek = restoreOffset;
76 }
77 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +000078
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 addDraw(RESTORE);
80 validate();
81 return this->INHERITED::restore();
82}
83
84bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
85 addDraw(TRANSLATE);
86 addScalar(dx);
87 addScalar(dy);
88 validate();
89 return this->INHERITED::translate(dx, dy);
90}
91
92bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
reed@google.com82065d62011-02-07 15:30:46 +000093 addDraw(SCALE);
reed@android.com8a1c16f2008-12-17 15:59:43 +000094 addScalar(sx);
95 addScalar(sy);
96 validate();
97 return this->INHERITED::scale(sx, sy);
98}
99
100bool SkPictureRecord::rotate(SkScalar degrees) {
reed@google.com82065d62011-02-07 15:30:46 +0000101 addDraw(ROTATE);
102 addScalar(degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103 validate();
104 return this->INHERITED::rotate(degrees);
105}
106
107bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
reed@google.com82065d62011-02-07 15:30:46 +0000108 addDraw(SKEW);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 addScalar(sx);
110 addScalar(sy);
111 validate();
112 return this->INHERITED::skew(sx, sy);
113}
114
115bool SkPictureRecord::concat(const SkMatrix& matrix) {
116 validate();
117 addDraw(CONCAT);
118 addMatrix(matrix);
119 validate();
120 return this->INHERITED::concat(matrix);
121}
122
reed@android.com6e073b92009-01-06 15:03:30 +0000123void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
124 validate();
125 addDraw(SET_MATRIX);
126 addMatrix(matrix);
127 validate();
128 this->INHERITED::setMatrix(matrix);
129}
130
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op) {
132 addDraw(CLIP_RECT);
133 addRect(rect);
134 addInt(op);
reed@google.com82065d62011-02-07 15:30:46 +0000135
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 size_t offset = fWriter.size();
137 addInt(fRestoreOffsetStack.top());
138 fRestoreOffsetStack.top() = offset;
139
140 validate();
141 return this->INHERITED::clipRect(rect, op);
142}
143
144bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op) {
145 addDraw(CLIP_PATH);
146 addPath(path);
147 addInt(op);
reed@google.com82065d62011-02-07 15:30:46 +0000148
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149 size_t offset = fWriter.size();
150 addInt(fRestoreOffsetStack.top());
151 fRestoreOffsetStack.top() = offset;
reed@google.com82065d62011-02-07 15:30:46 +0000152
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153 validate();
reed@google.com82065d62011-02-07 15:30:46 +0000154
reed@android.comae814c82009-02-13 14:56:09 +0000155 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
reed@android.comd252db02009-04-01 18:31:44 +0000156 return this->INHERITED::clipRect(path.getBounds(), op);
reed@android.comae814c82009-02-13 14:56:09 +0000157 } else {
158 return this->INHERITED::clipPath(path, op);
159 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160}
161
162bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
reed@google.com82065d62011-02-07 15:30:46 +0000163 addDraw(CLIP_REGION);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 addRegion(region);
165 addInt(op);
reed@google.com82065d62011-02-07 15:30:46 +0000166
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167 size_t offset = fWriter.size();
168 addInt(fRestoreOffsetStack.top());
169 fRestoreOffsetStack.top() = offset;
reed@google.com82065d62011-02-07 15:30:46 +0000170
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171 validate();
172 return this->INHERITED::clipRegion(region, op);
173}
174
reed@google.com2a981812011-04-14 18:59:28 +0000175void SkPictureRecord::clear(SkColor color) {
176 addDraw(DRAW_CLEAR);
177 addInt(color);
178 validate();
179}
180
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181void SkPictureRecord::drawPaint(const SkPaint& paint) {
182 addDraw(DRAW_PAINT);
183 addPaint(paint);
184 validate();
185}
186
187void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
188 const SkPaint& paint) {
189 addDraw(DRAW_POINTS);
190 addPaint(paint);
191 addInt(mode);
192 addInt(count);
193 fWriter.writeMul4(pts, count * sizeof(SkPoint));
194 validate();
195}
196
197void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
198 addDraw(DRAW_RECT);
199 addPaint(paint);
200 addRect(rect);
201 validate();
202}
203
204void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
205 addDraw(DRAW_PATH);
206 addPaint(paint);
207 addPath(path);
208 validate();
209}
210
211void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
212 const SkPaint* paint = NULL) {
213 addDraw(DRAW_BITMAP);
214 addPaintPtr(paint);
215 addBitmap(bitmap);
216 addScalar(left);
217 addScalar(top);
218 validate();
219}
220
221void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
222 const SkRect& dst, const SkPaint* paint) {
223 addDraw(DRAW_BITMAP_RECT);
224 addPaintPtr(paint);
225 addBitmap(bitmap);
226 addIRectPtr(src); // may be null
227 addRect(dst);
228 validate();
229}
230
231void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
232 const SkPaint* paint) {
233 addDraw(DRAW_BITMAP_MATRIX);
234 addPaintPtr(paint);
235 addBitmap(bitmap);
236 addMatrix(matrix);
237 validate();
238}
239
240void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
241 const SkPaint* paint = NULL) {
242 addDraw(DRAW_SPRITE);
243 addPaintPtr(paint);
244 addBitmap(bitmap);
245 addInt(left);
246 addInt(top);
247 validate();
248}
249
250void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
251 SkScalar baselineY) {
252 SkPaint::FontMetrics metrics;
253 paint.getFontMetrics(&metrics);
254 SkRect bounds;
255 // construct a rect so we can see any adjustments from the paint.
256 // we use 0,1 for left,right, just so the rect isn't empty
257 bounds.set(0, metrics.fTop + baselineY,
258 SK_Scalar1, metrics.fBottom + baselineY);
259 (void)paint.computeFastBounds(bounds, &bounds);
260 // now record the top and bottom
261 addScalar(bounds.fTop);
262 addScalar(bounds.fBottom);
263}
264
reed@google.com82065d62011-02-07 15:30:46 +0000265void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266 SkScalar y, const SkPaint& paint) {
267 bool fast = paint.canComputeFastBounds();
reed@google.com82065d62011-02-07 15:30:46 +0000268
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
270 addPaint(paint);
271 addText(text, byteLength);
272 addScalar(x);
273 addScalar(y);
274 if (fast) {
275 addFontMetricsTopBottom(paint, y);
276 }
277 validate();
278}
279
reed@google.com82065d62011-02-07 15:30:46 +0000280void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 const SkPoint pos[], const SkPaint& paint) {
282 size_t points = paint.countText(text, byteLength);
283 if (0 == points)
284 return;
285
286 bool canUseDrawH = true;
287 // check if the caller really should have used drawPosTextH()
288 {
289 const SkScalar firstY = pos[0].fY;
290 for (size_t index = 1; index < points; index++) {
291 if (pos[index].fY != firstY) {
292 canUseDrawH = false;
293 break;
294 }
295 }
296 }
reed@google.com82065d62011-02-07 15:30:46 +0000297
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 bool fast = canUseDrawH && paint.canComputeFastBounds();
299
300 if (fast) {
301 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
302 } else {
303 addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
304 }
305 addPaint(paint);
306 addText(text, byteLength);
307 addInt(points);
308
309#ifdef SK_DEBUG_SIZE
310 size_t start = fWriter.size();
311#endif
312 if (canUseDrawH) {
313 if (fast) {
314 addFontMetricsTopBottom(paint, pos[0].fY);
315 }
316 addScalar(pos[0].fY);
317 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
reed@google.com82065d62011-02-07 15:30:46 +0000318 for (size_t index = 0; index < points; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000319 *xptr++ = pos[index].fX;
320 }
321 else {
322 fWriter.writeMul4(pos, points * sizeof(SkPoint));
323 }
324#ifdef SK_DEBUG_SIZE
325 fPointBytes += fWriter.size() - start;
326 fPointWrites += points;
327#endif
328 validate();
329}
330
331void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
332 const SkScalar xpos[], SkScalar constY,
333 const SkPaint& paint) {
334 size_t points = paint.countText(text, byteLength);
335 if (0 == points)
336 return;
reed@google.com82065d62011-02-07 15:30:46 +0000337
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 bool fast = paint.canComputeFastBounds();
339
340 addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
341 addPaint(paint);
342 addText(text, byteLength);
343 addInt(points);
reed@google.com82065d62011-02-07 15:30:46 +0000344
reed@android.com8a1c16f2008-12-17 15:59:43 +0000345#ifdef SK_DEBUG_SIZE
346 size_t start = fWriter.size();
347#endif
348 if (fast) {
349 addFontMetricsTopBottom(paint, constY);
350 }
351 addScalar(constY);
352 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
353#ifdef SK_DEBUG_SIZE
354 fPointBytes += fWriter.size() - start;
355 fPointWrites += points;
356#endif
357 validate();
358}
359
reed@google.com82065d62011-02-07 15:30:46 +0000360void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
361 const SkPath& path, const SkMatrix* matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000362 const SkPaint& paint) {
363 addDraw(DRAW_TEXT_ON_PATH);
364 addPaint(paint);
365 addText(text, byteLength);
366 addPath(path);
367 addMatrixPtr(matrix);
368 validate();
369}
370
371void SkPictureRecord::drawPicture(SkPicture& picture) {
372 addDraw(DRAW_PICTURE);
373 addPicture(picture);
374 validate();
375}
376
377void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
378 const SkPoint vertices[], const SkPoint texs[],
379 const SkColor colors[], SkXfermode*,
380 const uint16_t indices[], int indexCount,
381 const SkPaint& paint) {
382 uint32_t flags = 0;
383 if (texs) {
384 flags |= DRAW_VERTICES_HAS_TEXS;
385 }
386 if (colors) {
387 flags |= DRAW_VERTICES_HAS_COLORS;
388 }
389 if (indexCount > 0) {
390 flags |= DRAW_VERTICES_HAS_INDICES;
391 }
392
393 addDraw(DRAW_VERTICES);
394 addPaint(paint);
395 addInt(flags);
396 addInt(vmode);
397 addInt(vertexCount);
398 addPoints(vertices, vertexCount);
399 if (flags & DRAW_VERTICES_HAS_TEXS) {
400 addPoints(texs, vertexCount);
401 }
402 if (flags & DRAW_VERTICES_HAS_COLORS) {
403 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
404 }
405 if (flags & DRAW_VERTICES_HAS_INDICES) {
406 addInt(indexCount);
407 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
408 }
409}
410
reed@android.comcb608442009-12-04 21:32:27 +0000411void SkPictureRecord::drawData(const void* data, size_t length) {
412 addDraw(DRAW_DATA);
413 addInt(length);
414 fWriter.writePad(data, length);
415}
416
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000418
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419void SkPictureRecord::reset() {
reed@google.com82065d62011-02-07 15:30:46 +0000420 SkSafeUnref(fPathHeap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421 fPathHeap = NULL;
422
423 fBitmaps.reset();
424 fMatrices.reset();
425 fPaints.reset();
426 fPictureRefs.unrefAll();
427 fRegions.reset();
428 fWriter.reset();
429 fHeap.reset();
reed@google.com82065d62011-02-07 15:30:46 +0000430
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 fRestoreOffsetStack.setCount(1);
432 fRestoreOffsetStack.top() = 0;
reed@google.com82065d62011-02-07 15:30:46 +0000433
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000434 fRCSet.reset();
435 fTFSet.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000436}
437
438void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
439 addInt(find(fBitmaps, bitmap));
440}
441
442void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
443 addMatrixPtr(&matrix);
444}
445
446void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
447 addInt(find(fMatrices, matrix));
448}
449
450void SkPictureRecord::addPaint(const SkPaint& paint) {
451 addPaintPtr(&paint);
452}
453
454void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
455 addInt(find(fPaints, paint));
456}
457
458void SkPictureRecord::addPath(const SkPath& path) {
459 if (NULL == fPathHeap) {
460 fPathHeap = SkNEW(SkPathHeap);
461 }
462 addInt(fPathHeap->append(path));
463}
464
465void SkPictureRecord::addPicture(SkPicture& picture) {
466 int index = fPictureRefs.find(&picture);
467 if (index < 0) { // not found
468 index = fPictureRefs.count();
469 *fPictureRefs.append() = &picture;
470 picture.ref();
471 }
472 // follow the convention of recording a 1-based index
473 addInt(index + 1);
474}
475
476void SkPictureRecord::addPoint(const SkPoint& point) {
477#ifdef SK_DEBUG_SIZE
478 size_t start = fWriter.size();
479#endif
480 fWriter.writePoint(point);
481#ifdef SK_DEBUG_SIZE
482 fPointBytes += fWriter.size() - start;
483 fPointWrites++;
484#endif
485}
reed@google.com82065d62011-02-07 15:30:46 +0000486
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
488 fWriter.writeMul4(pts, count * sizeof(SkPoint));
489#ifdef SK_DEBUG_SIZE
490 fPointBytes += count * sizeof(SkPoint);
491 fPointWrites++;
492#endif
493}
494
495void SkPictureRecord::addRect(const SkRect& rect) {
496#ifdef SK_DEBUG_SIZE
497 size_t start = fWriter.size();
498#endif
499 fWriter.writeRect(rect);
500#ifdef SK_DEBUG_SIZE
501 fRectBytes += fWriter.size() - start;
502 fRectWrites++;
503#endif
504}
505
506void SkPictureRecord::addRectPtr(const SkRect* rect) {
507 if (fWriter.writeBool(rect != NULL)) {
508 fWriter.writeRect(*rect);
509 }
510}
511
512void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
513 if (fWriter.writeBool(rect != NULL)) {
514 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
515 }
516}
517
518void SkPictureRecord::addRegion(const SkRegion& region) {
519 addInt(find(fRegions, region));
520}
521
522void SkPictureRecord::addText(const void* text, size_t byteLength) {
523#ifdef SK_DEBUG_SIZE
524 size_t start = fWriter.size();
525#endif
526 addInt(byteLength);
527 fWriter.writePad(text, byteLength);
528#ifdef SK_DEBUG_SIZE
529 fTextBytes += fWriter.size() - start;
530 fTextWrites++;
531#endif
532}
533
534///////////////////////////////////////////////////////////////////////////////
535
536int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
537 SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000538 &fRCSet);
reed@google.com82065d62011-02-07 15:30:46 +0000539 int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000540 bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
541 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000542 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000543 return bitmaps[index]->index();
544 }
545 index = ~index;
546 *bitmaps.insert(index) = flat;
547 return fBitmapIndex++;
548}
549
550int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
551 if (matrix == NULL)
552 return 0;
553 SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000554 int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555 matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000556 if (index >= 0) {
557 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000558 return matrices[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000559 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000560 index = ~index;
561 *matrices.insert(index) = flat;
562 return fMatrixIndex++;
563}
564
565int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
566 if (paint == NULL) {
567 return 0;
568 }
reed@google.com82065d62011-02-07 15:30:46 +0000569
reed@android.com8a1c16f2008-12-17 15:59:43 +0000570 SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000571 &fRCSet, &fTFSet);
reed@google.com82065d62011-02-07 15:30:46 +0000572 int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000573 paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
574 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000575 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000576 return paints[index]->index();
577 }
578
579 index = ~index;
580 *paints.insert(index) = flat;
581 return fPaintIndex++;
582}
583
584int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
585 SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000586 int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587 regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000588 if (index >= 0) {
589 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590 return regions[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000591 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000592 index = ~index;
593 *regions.insert(index) = flat;
594 return fRegionIndex++;
595}
596
597#ifdef SK_DEBUG_DUMP
598void SkPictureRecord::dumpMatrices() {
599 int count = fMatrices.count();
600 SkMatrix defaultMatrix;
601 defaultMatrix.reset();
602 for (int index = 0; index < count; index++) {
603 const SkFlatMatrix* flatMatrix = fMatrices[index];
604 flatMatrix->dump();
605 }
606}
607
608void SkPictureRecord::dumpPaints() {
609 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000610 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000611 fPaints[index]->dump();
612}
613#endif
614
615#ifdef SK_DEBUG_SIZE
616size_t SkPictureRecord::size() const {
617 size_t result = 0;
618 size_t sizeData;
619 bitmaps(&sizeData);
620 result += sizeData;
621 matrices(&sizeData);
622 result += sizeData;
623 paints(&sizeData);
624 result += sizeData;
625 paths(&sizeData);
626 result += sizeData;
627 pictures(&sizeData);
628 result += sizeData;
629 regions(&sizeData);
630 result += sizeData;
631 result += streamlen();
632 return result;
633}
634
635int SkPictureRecord::bitmaps(size_t* size) const {
636 size_t result = 0;
637 int count = fBitmaps.count();
reed@google.com82065d62011-02-07 15:30:46 +0000638 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
640 *size = result;
641 return count;
642}
643
644int SkPictureRecord::matrices(size_t* size) const {
645 int count = fMatrices.count();
646 *size = sizeof(fMatrices[0]) * count;
647 return count;
648}
649
650int SkPictureRecord::paints(size_t* size) const {
651 size_t result = 0;
652 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000653 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000654 result += sizeof(fPaints[index]) + fPaints[index]->size();
655 *size = result;
656 return count;
657}
658
659int SkPictureRecord::paths(size_t* size) const {
660 size_t result = 0;
661 int count = fPaths.count();
reed@google.com82065d62011-02-07 15:30:46 +0000662 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000663 result += sizeof(fPaths[index]) + fPaths[index]->size();
664 *size = result;
665 return count;
666}
667
668int SkPictureRecord::regions(size_t* size) const {
669 size_t result = 0;
670 int count = fRegions.count();
reed@google.com82065d62011-02-07 15:30:46 +0000671 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000672 result += sizeof(fRegions[index]) + fRegions[index]->size();
673 *size = result;
674 return count;
675}
676
677size_t SkPictureRecord::streamlen() const {
678 return fWriter.size();
679}
680#endif
681
682#ifdef SK_DEBUG_VALIDATE
683void SkPictureRecord::validate() const {
684 validateBitmaps();
685 validateMatrices();
686 validatePaints();
687 validatePaths();
688 validatePictures();
689 validateRegions();
690}
691
692void SkPictureRecord::validateBitmaps() const {
693 int count = fBitmaps.count();
694 SkASSERT((unsigned) count < 0x1000);
695 for (int index = 0; index < count; index++) {
696 const SkFlatBitmap* bitPtr = fBitmaps[index];
697 SkASSERT(bitPtr);
698 bitPtr->validate();
699 }
700}
701
702void SkPictureRecord::validateMatrices() const {
703 int count = fMatrices.count();
704 SkASSERT((unsigned) count < 0x1000);
705 for (int index = 0; index < count; index++) {
706 const SkFlatMatrix* matrix = fMatrices[index];
707 SkASSERT(matrix);
reed@google.com82065d62011-02-07 15:30:46 +0000708 matrix->validate();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000709 }
710}
711
712void SkPictureRecord::validatePaints() const {
713 int count = fPaints.count();
714 SkASSERT((unsigned) count < 0x1000);
715 for (int index = 0; index < count; index++) {
716 const SkFlatPaint* paint = fPaints[index];
717 SkASSERT(paint);
718// paint->validate();
719 }
720}
721
722void SkPictureRecord::validatePaths() const {
723 int count = fPaths.count();
724 SkASSERT((unsigned) count < 0x1000);
725 for (int index = 0; index < count; index++) {
726 const SkFlatPath* path = fPaths[index];
727 SkASSERT(path);
728 path->validate();
729 }
730}
731
732void SkPictureRecord::validateRegions() const {
733 int count = fRegions.count();
734 SkASSERT((unsigned) count < 0x1000);
735 for (int index = 0; index < count; index++) {
736 const SkFlatRegion* region = fRegions[index];
737 SkASSERT(region);
738 region->validate();
739 }
740}
741#endif
742