blob: 8813ee6b0819f7ecae1ba626f72ebd680cfb35c5 [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@google.com45482d12011-08-29 19:02:39 +0000131static bool regionOpExpands(SkRegion::Op op) {
132 switch (op) {
133 case SkRegion::kUnion_Op:
134 case SkRegion::kXOR_Op:
135 case SkRegion::kReverseDifference_Op:
136 case SkRegion::kReplace_Op:
137 return true;
138 case SkRegion::kIntersect_Op:
139 case SkRegion::kDifference_Op:
140 return false;
141 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000142 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000143 return false;
144 }
145}
146
147void SkPictureRecord::recordOffsetForRestore(SkRegion::Op op) {
148 if (regionOpExpands(op)) {
149 // Run back through any previous clip ops, and mark their offset to
150 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
151 // they could hide this clips ability to expand the clip (i.e. go from
152 // empty to non-empty).
153 uint32_t offset = fRestoreOffsetStack.top();
154 while (offset) {
155 uint32_t* peek = fWriter.peek32(offset);
156 offset = *peek;
157 *peek = 0;
158 }
159 }
160
161 size_t offset = fWriter.size();
162 addInt(fRestoreOffsetStack.top());
163 fRestoreOffsetStack.top() = offset;
164}
165
reed@google.com071eef92011-10-12 11:52:53 +0000166bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167 addDraw(CLIP_RECT);
168 addRect(rect);
reed@google.com83ab4952011-11-11 21:34:54 +0000169 addInt(ClipParams_pack(op, doAA));
reed@google.com82065d62011-02-07 15:30:46 +0000170
reed@google.com45482d12011-08-29 19:02:39 +0000171 this->recordOffsetForRestore(op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172
173 validate();
reed@google.com071eef92011-10-12 11:52:53 +0000174 return this->INHERITED::clipRect(rect, op, doAA);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175}
176
reed@google.com071eef92011-10-12 11:52:53 +0000177bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178 addDraw(CLIP_PATH);
179 addPath(path);
reed@google.com83ab4952011-11-11 21:34:54 +0000180 addInt(ClipParams_pack(op, doAA));
reed@google.com82065d62011-02-07 15:30:46 +0000181
reed@google.com45482d12011-08-29 19:02:39 +0000182 this->recordOffsetForRestore(op);
reed@google.com82065d62011-02-07 15:30:46 +0000183
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 validate();
reed@google.com82065d62011-02-07 15:30:46 +0000185
reed@android.comae814c82009-02-13 14:56:09 +0000186 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
reed@google.com071eef92011-10-12 11:52:53 +0000187 return this->INHERITED::clipRect(path.getBounds(), op, doAA);
reed@android.comae814c82009-02-13 14:56:09 +0000188 } else {
reed@google.com071eef92011-10-12 11:52:53 +0000189 return this->INHERITED::clipPath(path, op, doAA);
reed@android.comae814c82009-02-13 14:56:09 +0000190 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191}
192
193bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
reed@google.com82065d62011-02-07 15:30:46 +0000194 addDraw(CLIP_REGION);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195 addRegion(region);
reed@google.com83ab4952011-11-11 21:34:54 +0000196 addInt(ClipParams_pack(op, false));
reed@google.com82065d62011-02-07 15:30:46 +0000197
reed@google.com45482d12011-08-29 19:02:39 +0000198 this->recordOffsetForRestore(op);
reed@google.com82065d62011-02-07 15:30:46 +0000199
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200 validate();
201 return this->INHERITED::clipRegion(region, op);
202}
203
reed@google.com2a981812011-04-14 18:59:28 +0000204void SkPictureRecord::clear(SkColor color) {
205 addDraw(DRAW_CLEAR);
206 addInt(color);
207 validate();
208}
209
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210void SkPictureRecord::drawPaint(const SkPaint& paint) {
211 addDraw(DRAW_PAINT);
212 addPaint(paint);
213 validate();
214}
215
216void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
217 const SkPaint& paint) {
218 addDraw(DRAW_POINTS);
219 addPaint(paint);
220 addInt(mode);
221 addInt(count);
222 fWriter.writeMul4(pts, count * sizeof(SkPoint));
223 validate();
224}
225
226void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
227 addDraw(DRAW_RECT);
228 addPaint(paint);
229 addRect(rect);
230 validate();
231}
232
233void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
234 addDraw(DRAW_PATH);
235 addPaint(paint);
236 addPath(path);
237 validate();
238}
239
240void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
241 const SkPaint* paint = NULL) {
242 addDraw(DRAW_BITMAP);
243 addPaintPtr(paint);
244 addBitmap(bitmap);
245 addScalar(left);
246 addScalar(top);
247 validate();
248}
249
250void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
251 const SkRect& dst, const SkPaint* paint) {
252 addDraw(DRAW_BITMAP_RECT);
253 addPaintPtr(paint);
254 addBitmap(bitmap);
255 addIRectPtr(src); // may be null
256 addRect(dst);
257 validate();
258}
259
260void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
reed@google.comf0b5e112011-09-07 11:57:34 +0000261 const SkPaint* paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262 addDraw(DRAW_BITMAP_MATRIX);
263 addPaintPtr(paint);
264 addBitmap(bitmap);
265 addMatrix(matrix);
266 validate();
267}
268
reed@google.comf0b5e112011-09-07 11:57:34 +0000269void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
270 const SkRect& dst, const SkPaint* paint) {
271 addDraw(DRAW_BITMAP_NINE);
272 addPaintPtr(paint);
273 addBitmap(bitmap);
274 addIRect(center);
275 addRect(dst);
276 validate();
277}
278
reed@android.com8a1c16f2008-12-17 15:59:43 +0000279void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
280 const SkPaint* paint = NULL) {
281 addDraw(DRAW_SPRITE);
282 addPaintPtr(paint);
283 addBitmap(bitmap);
284 addInt(left);
285 addInt(top);
286 validate();
287}
288
289void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
290 SkScalar baselineY) {
291 SkPaint::FontMetrics metrics;
292 paint.getFontMetrics(&metrics);
293 SkRect bounds;
294 // construct a rect so we can see any adjustments from the paint.
295 // we use 0,1 for left,right, just so the rect isn't empty
296 bounds.set(0, metrics.fTop + baselineY,
297 SK_Scalar1, metrics.fBottom + baselineY);
298 (void)paint.computeFastBounds(bounds, &bounds);
299 // now record the top and bottom
300 addScalar(bounds.fTop);
301 addScalar(bounds.fBottom);
302}
303
reed@google.com82065d62011-02-07 15:30:46 +0000304void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 SkScalar y, const SkPaint& paint) {
306 bool fast = paint.canComputeFastBounds();
reed@google.com82065d62011-02-07 15:30:46 +0000307
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
309 addPaint(paint);
310 addText(text, byteLength);
311 addScalar(x);
312 addScalar(y);
313 if (fast) {
314 addFontMetricsTopBottom(paint, y);
315 }
316 validate();
317}
318
reed@google.com82065d62011-02-07 15:30:46 +0000319void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320 const SkPoint pos[], const SkPaint& paint) {
321 size_t points = paint.countText(text, byteLength);
322 if (0 == points)
323 return;
324
325 bool canUseDrawH = true;
326 // check if the caller really should have used drawPosTextH()
327 {
328 const SkScalar firstY = pos[0].fY;
329 for (size_t index = 1; index < points; index++) {
330 if (pos[index].fY != firstY) {
331 canUseDrawH = false;
332 break;
333 }
334 }
335 }
reed@google.com82065d62011-02-07 15:30:46 +0000336
reed@android.com8a1c16f2008-12-17 15:59:43 +0000337 bool fast = canUseDrawH && paint.canComputeFastBounds();
338
339 if (fast) {
340 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
341 } else {
342 addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
343 }
344 addPaint(paint);
345 addText(text, byteLength);
346 addInt(points);
347
348#ifdef SK_DEBUG_SIZE
349 size_t start = fWriter.size();
350#endif
351 if (canUseDrawH) {
352 if (fast) {
353 addFontMetricsTopBottom(paint, pos[0].fY);
354 }
355 addScalar(pos[0].fY);
356 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
reed@google.com82065d62011-02-07 15:30:46 +0000357 for (size_t index = 0; index < points; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358 *xptr++ = pos[index].fX;
359 }
360 else {
361 fWriter.writeMul4(pos, points * sizeof(SkPoint));
362 }
363#ifdef SK_DEBUG_SIZE
364 fPointBytes += fWriter.size() - start;
365 fPointWrites += points;
366#endif
367 validate();
368}
369
370void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
371 const SkScalar xpos[], SkScalar constY,
372 const SkPaint& paint) {
373 size_t points = paint.countText(text, byteLength);
374 if (0 == points)
375 return;
reed@google.com82065d62011-02-07 15:30:46 +0000376
reed@android.com8a1c16f2008-12-17 15:59:43 +0000377 bool fast = paint.canComputeFastBounds();
378
379 addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
380 addPaint(paint);
381 addText(text, byteLength);
382 addInt(points);
reed@google.com82065d62011-02-07 15:30:46 +0000383
reed@android.com8a1c16f2008-12-17 15:59:43 +0000384#ifdef SK_DEBUG_SIZE
385 size_t start = fWriter.size();
386#endif
387 if (fast) {
388 addFontMetricsTopBottom(paint, constY);
389 }
390 addScalar(constY);
391 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
392#ifdef SK_DEBUG_SIZE
393 fPointBytes += fWriter.size() - start;
394 fPointWrites += points;
395#endif
396 validate();
397}
398
reed@google.com82065d62011-02-07 15:30:46 +0000399void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
400 const SkPath& path, const SkMatrix* matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401 const SkPaint& paint) {
402 addDraw(DRAW_TEXT_ON_PATH);
403 addPaint(paint);
404 addText(text, byteLength);
405 addPath(path);
406 addMatrixPtr(matrix);
407 validate();
408}
409
410void SkPictureRecord::drawPicture(SkPicture& picture) {
411 addDraw(DRAW_PICTURE);
412 addPicture(picture);
413 validate();
414}
415
416void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
417 const SkPoint vertices[], const SkPoint texs[],
418 const SkColor colors[], SkXfermode*,
419 const uint16_t indices[], int indexCount,
420 const SkPaint& paint) {
421 uint32_t flags = 0;
422 if (texs) {
423 flags |= DRAW_VERTICES_HAS_TEXS;
424 }
425 if (colors) {
426 flags |= DRAW_VERTICES_HAS_COLORS;
427 }
428 if (indexCount > 0) {
429 flags |= DRAW_VERTICES_HAS_INDICES;
430 }
431
432 addDraw(DRAW_VERTICES);
433 addPaint(paint);
434 addInt(flags);
435 addInt(vmode);
436 addInt(vertexCount);
437 addPoints(vertices, vertexCount);
438 if (flags & DRAW_VERTICES_HAS_TEXS) {
439 addPoints(texs, vertexCount);
440 }
441 if (flags & DRAW_VERTICES_HAS_COLORS) {
442 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
443 }
444 if (flags & DRAW_VERTICES_HAS_INDICES) {
445 addInt(indexCount);
446 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
447 }
448}
449
reed@android.comcb608442009-12-04 21:32:27 +0000450void SkPictureRecord::drawData(const void* data, size_t length) {
451 addDraw(DRAW_DATA);
452 addInt(length);
453 fWriter.writePad(data, length);
454}
455
reed@android.com8a1c16f2008-12-17 15:59:43 +0000456///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000457
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458void SkPictureRecord::reset() {
reed@google.com82065d62011-02-07 15:30:46 +0000459 SkSafeUnref(fPathHeap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460 fPathHeap = NULL;
461
462 fBitmaps.reset();
463 fMatrices.reset();
464 fPaints.reset();
465 fPictureRefs.unrefAll();
466 fRegions.reset();
467 fWriter.reset();
468 fHeap.reset();
reed@google.com82065d62011-02-07 15:30:46 +0000469
reed@android.com8a1c16f2008-12-17 15:59:43 +0000470 fRestoreOffsetStack.setCount(1);
471 fRestoreOffsetStack.top() = 0;
reed@google.com82065d62011-02-07 15:30:46 +0000472
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000473 fRCSet.reset();
474 fTFSet.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475}
476
477void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
478 addInt(find(fBitmaps, bitmap));
479}
480
481void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
482 addMatrixPtr(&matrix);
483}
484
485void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
486 addInt(find(fMatrices, matrix));
487}
488
489void SkPictureRecord::addPaint(const SkPaint& paint) {
490 addPaintPtr(&paint);
491}
492
493void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
494 addInt(find(fPaints, paint));
495}
496
497void SkPictureRecord::addPath(const SkPath& path) {
498 if (NULL == fPathHeap) {
499 fPathHeap = SkNEW(SkPathHeap);
500 }
501 addInt(fPathHeap->append(path));
502}
503
504void SkPictureRecord::addPicture(SkPicture& picture) {
505 int index = fPictureRefs.find(&picture);
506 if (index < 0) { // not found
507 index = fPictureRefs.count();
508 *fPictureRefs.append() = &picture;
509 picture.ref();
510 }
511 // follow the convention of recording a 1-based index
512 addInt(index + 1);
513}
514
515void SkPictureRecord::addPoint(const SkPoint& point) {
516#ifdef SK_DEBUG_SIZE
517 size_t start = fWriter.size();
518#endif
519 fWriter.writePoint(point);
520#ifdef SK_DEBUG_SIZE
521 fPointBytes += fWriter.size() - start;
522 fPointWrites++;
523#endif
524}
reed@google.com82065d62011-02-07 15:30:46 +0000525
reed@android.com8a1c16f2008-12-17 15:59:43 +0000526void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
527 fWriter.writeMul4(pts, count * sizeof(SkPoint));
528#ifdef SK_DEBUG_SIZE
529 fPointBytes += count * sizeof(SkPoint);
530 fPointWrites++;
531#endif
532}
533
534void SkPictureRecord::addRect(const SkRect& rect) {
535#ifdef SK_DEBUG_SIZE
536 size_t start = fWriter.size();
537#endif
538 fWriter.writeRect(rect);
539#ifdef SK_DEBUG_SIZE
540 fRectBytes += fWriter.size() - start;
541 fRectWrites++;
542#endif
543}
544
545void SkPictureRecord::addRectPtr(const SkRect* rect) {
546 if (fWriter.writeBool(rect != NULL)) {
547 fWriter.writeRect(*rect);
548 }
549}
550
reed@google.comf0b5e112011-09-07 11:57:34 +0000551void SkPictureRecord::addIRect(const SkIRect& rect) {
552 fWriter.write(&rect, sizeof(rect));
553}
554
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
556 if (fWriter.writeBool(rect != NULL)) {
557 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
558 }
559}
560
561void SkPictureRecord::addRegion(const SkRegion& region) {
562 addInt(find(fRegions, region));
563}
564
565void SkPictureRecord::addText(const void* text, size_t byteLength) {
566#ifdef SK_DEBUG_SIZE
567 size_t start = fWriter.size();
568#endif
569 addInt(byteLength);
570 fWriter.writePad(text, byteLength);
571#ifdef SK_DEBUG_SIZE
572 fTextBytes += fWriter.size() - start;
573 fTextWrites++;
574#endif
575}
576
577///////////////////////////////////////////////////////////////////////////////
578
579int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
580 SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000581 &fRCSet);
reed@google.com82065d62011-02-07 15:30:46 +0000582 int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000583 bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
584 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000585 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000586 return bitmaps[index]->index();
587 }
588 index = ~index;
589 *bitmaps.insert(index) = flat;
590 return fBitmapIndex++;
591}
592
593int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
594 if (matrix == NULL)
595 return 0;
596 SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000597 int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598 matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000599 if (index >= 0) {
600 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000601 return matrices[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000602 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000603 index = ~index;
604 *matrices.insert(index) = flat;
605 return fMatrixIndex++;
606}
607
608int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
609 if (paint == NULL) {
610 return 0;
611 }
reed@google.com82065d62011-02-07 15:30:46 +0000612
reed@android.com8a1c16f2008-12-17 15:59:43 +0000613 SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000614 &fRCSet, &fTFSet);
reed@google.com82065d62011-02-07 15:30:46 +0000615 int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616 paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
617 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000618 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000619 return paints[index]->index();
620 }
621
622 index = ~index;
623 *paints.insert(index) = flat;
624 return fPaintIndex++;
625}
626
627int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
628 SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000629 int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000630 regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000631 if (index >= 0) {
632 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000633 return regions[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000634 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000635 index = ~index;
636 *regions.insert(index) = flat;
637 return fRegionIndex++;
638}
639
640#ifdef SK_DEBUG_DUMP
641void SkPictureRecord::dumpMatrices() {
642 int count = fMatrices.count();
643 SkMatrix defaultMatrix;
644 defaultMatrix.reset();
645 for (int index = 0; index < count; index++) {
646 const SkFlatMatrix* flatMatrix = fMatrices[index];
647 flatMatrix->dump();
648 }
649}
650
651void SkPictureRecord::dumpPaints() {
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 fPaints[index]->dump();
655}
656#endif
657
658#ifdef SK_DEBUG_SIZE
659size_t SkPictureRecord::size() const {
660 size_t result = 0;
661 size_t sizeData;
662 bitmaps(&sizeData);
663 result += sizeData;
664 matrices(&sizeData);
665 result += sizeData;
666 paints(&sizeData);
667 result += sizeData;
668 paths(&sizeData);
669 result += sizeData;
670 pictures(&sizeData);
671 result += sizeData;
672 regions(&sizeData);
673 result += sizeData;
674 result += streamlen();
675 return result;
676}
677
678int SkPictureRecord::bitmaps(size_t* size) const {
679 size_t result = 0;
680 int count = fBitmaps.count();
reed@google.com82065d62011-02-07 15:30:46 +0000681 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000682 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
683 *size = result;
684 return count;
685}
686
687int SkPictureRecord::matrices(size_t* size) const {
688 int count = fMatrices.count();
689 *size = sizeof(fMatrices[0]) * count;
690 return count;
691}
692
693int SkPictureRecord::paints(size_t* size) const {
694 size_t result = 0;
695 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000696 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000697 result += sizeof(fPaints[index]) + fPaints[index]->size();
698 *size = result;
699 return count;
700}
701
702int SkPictureRecord::paths(size_t* size) const {
703 size_t result = 0;
704 int count = fPaths.count();
reed@google.com82065d62011-02-07 15:30:46 +0000705 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000706 result += sizeof(fPaths[index]) + fPaths[index]->size();
707 *size = result;
708 return count;
709}
710
711int SkPictureRecord::regions(size_t* size) const {
712 size_t result = 0;
713 int count = fRegions.count();
reed@google.com82065d62011-02-07 15:30:46 +0000714 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000715 result += sizeof(fRegions[index]) + fRegions[index]->size();
716 *size = result;
717 return count;
718}
719
720size_t SkPictureRecord::streamlen() const {
721 return fWriter.size();
722}
723#endif
724
725#ifdef SK_DEBUG_VALIDATE
726void SkPictureRecord::validate() const {
727 validateBitmaps();
728 validateMatrices();
729 validatePaints();
730 validatePaths();
731 validatePictures();
732 validateRegions();
733}
734
735void SkPictureRecord::validateBitmaps() const {
736 int count = fBitmaps.count();
737 SkASSERT((unsigned) count < 0x1000);
738 for (int index = 0; index < count; index++) {
739 const SkFlatBitmap* bitPtr = fBitmaps[index];
740 SkASSERT(bitPtr);
741 bitPtr->validate();
742 }
743}
744
745void SkPictureRecord::validateMatrices() const {
746 int count = fMatrices.count();
747 SkASSERT((unsigned) count < 0x1000);
748 for (int index = 0; index < count; index++) {
749 const SkFlatMatrix* matrix = fMatrices[index];
750 SkASSERT(matrix);
reed@google.com82065d62011-02-07 15:30:46 +0000751 matrix->validate();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752 }
753}
754
755void SkPictureRecord::validatePaints() const {
756 int count = fPaints.count();
757 SkASSERT((unsigned) count < 0x1000);
758 for (int index = 0; index < count; index++) {
759 const SkFlatPaint* paint = fPaints[index];
760 SkASSERT(paint);
761// paint->validate();
762 }
763}
764
765void SkPictureRecord::validatePaths() const {
766 int count = fPaths.count();
767 SkASSERT((unsigned) count < 0x1000);
768 for (int index = 0; index < count; index++) {
769 const SkFlatPath* path = fPaths[index];
770 SkASSERT(path);
771 path->validate();
772 }
773}
774
775void SkPictureRecord::validateRegions() const {
776 int count = fRegions.count();
777 SkASSERT((unsigned) count < 0x1000);
778 for (int index = 0; index < count; index++) {
779 const SkFlatRegion* region = fRegions[index];
780 SkASSERT(region);
781 region->validate();
782 }
783}
784#endif
785