blob: ba49b729dec5e6cf36a410c6614b0ee1e1883ac0 [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
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +000026 fFirstSavedLayerIndex = kNoSavedLayerIndex;
reed@android.com8a1c16f2008-12-17 15:59:43 +000027}
28
29SkPictureRecord::~SkPictureRecord() {
30 reset();
31}
32
33///////////////////////////////////////////////////////////////////////////////
34
35int SkPictureRecord::save(SaveFlags flags) {
36 addDraw(SAVE);
37 addInt(flags);
reed@google.com82065d62011-02-07 15:30:46 +000038
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 fRestoreOffsetStack.push(0);
reed@google.com82065d62011-02-07 15:30:46 +000040
reed@android.com8a1c16f2008-12-17 15:59:43 +000041 validate();
42 return this->INHERITED::save(flags);
43}
44
45int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
46 SaveFlags flags) {
47 addDraw(SAVE_LAYER);
48 addRectPtr(bounds);
49 addPaintPtr(paint);
50 addInt(flags);
51
52 fRestoreOffsetStack.push(0);
53
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +000054 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
55 fFirstSavedLayerIndex = fRestoreOffsetStack.count();
56 }
57
reed@android.com8a1c16f2008-12-17 15:59:43 +000058 validate();
reed@android.com261ae4d2009-10-02 16:37:46 +000059 /* Don't actually call saveLayer, because that will try to allocate an
60 offscreen device (potentially very big) which we don't actually need
61 at this time (and may not be able to afford since during record our
62 clip starts out the size of the picture, which is often much larger
63 than the size of the actual device we'll use during playback).
64 */
junov@chromium.orga907ac32012-02-24 21:54:07 +000065 int count = this->INHERITED::save(flags);
66 this->clipRectBounds(bounds, flags, NULL);
67 return count;
reed@android.com8a1c16f2008-12-17 15:59:43 +000068}
69
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +000070bool SkPictureRecord::isDrawingToLayer() const {
71 return fFirstSavedLayerIndex != kNoSavedLayerIndex;
72}
73
reed@android.com8a1c16f2008-12-17 15:59:43 +000074void SkPictureRecord::restore() {
reed@android.comb4e22d62009-07-09 15:20:25 +000075 // check for underflow
76 if (fRestoreOffsetStack.count() == 0) {
77 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +000078 }
reed@android.comb4e22d62009-07-09 15:20:25 +000079
80 // patch up the clip offsets
81 uint32_t restoreOffset = (uint32_t)fWriter.size();
82 uint32_t offset = fRestoreOffsetStack.top();
83 while (offset) {
84 uint32_t* peek = fWriter.peek32(offset);
85 offset = *peek;
86 *peek = restoreOffset;
87 }
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +000088
89 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
90 fFirstSavedLayerIndex = kNoSavedLayerIndex;
91 }
92
reed@android.comb4e22d62009-07-09 15:20:25 +000093 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +000094
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 addDraw(RESTORE);
96 validate();
97 return this->INHERITED::restore();
98}
99
100bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
101 addDraw(TRANSLATE);
102 addScalar(dx);
103 addScalar(dy);
104 validate();
105 return this->INHERITED::translate(dx, dy);
106}
107
108bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
reed@google.com82065d62011-02-07 15:30:46 +0000109 addDraw(SCALE);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000110 addScalar(sx);
111 addScalar(sy);
112 validate();
113 return this->INHERITED::scale(sx, sy);
114}
115
116bool SkPictureRecord::rotate(SkScalar degrees) {
reed@google.com82065d62011-02-07 15:30:46 +0000117 addDraw(ROTATE);
118 addScalar(degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119 validate();
120 return this->INHERITED::rotate(degrees);
121}
122
123bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
reed@google.com82065d62011-02-07 15:30:46 +0000124 addDraw(SKEW);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 addScalar(sx);
126 addScalar(sy);
127 validate();
128 return this->INHERITED::skew(sx, sy);
129}
130
131bool SkPictureRecord::concat(const SkMatrix& matrix) {
132 validate();
133 addDraw(CONCAT);
134 addMatrix(matrix);
135 validate();
136 return this->INHERITED::concat(matrix);
137}
138
reed@android.com6e073b92009-01-06 15:03:30 +0000139void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
140 validate();
141 addDraw(SET_MATRIX);
142 addMatrix(matrix);
143 validate();
144 this->INHERITED::setMatrix(matrix);
145}
146
reed@google.com45482d12011-08-29 19:02:39 +0000147static bool regionOpExpands(SkRegion::Op op) {
148 switch (op) {
149 case SkRegion::kUnion_Op:
150 case SkRegion::kXOR_Op:
151 case SkRegion::kReverseDifference_Op:
152 case SkRegion::kReplace_Op:
153 return true;
154 case SkRegion::kIntersect_Op:
155 case SkRegion::kDifference_Op:
156 return false;
157 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000158 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000159 return false;
160 }
161}
162
163void SkPictureRecord::recordOffsetForRestore(SkRegion::Op op) {
164 if (regionOpExpands(op)) {
165 // Run back through any previous clip ops, and mark their offset to
166 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
167 // they could hide this clips ability to expand the clip (i.e. go from
168 // empty to non-empty).
169 uint32_t offset = fRestoreOffsetStack.top();
170 while (offset) {
171 uint32_t* peek = fWriter.peek32(offset);
172 offset = *peek;
173 *peek = 0;
174 }
175 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000176
reed@google.com45482d12011-08-29 19:02:39 +0000177 size_t offset = fWriter.size();
178 addInt(fRestoreOffsetStack.top());
179 fRestoreOffsetStack.top() = offset;
180}
181
reed@google.com071eef92011-10-12 11:52:53 +0000182bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183 addDraw(CLIP_RECT);
184 addRect(rect);
reed@google.com83ab4952011-11-11 21:34:54 +0000185 addInt(ClipParams_pack(op, doAA));
reed@google.com82065d62011-02-07 15:30:46 +0000186
reed@google.com45482d12011-08-29 19:02:39 +0000187 this->recordOffsetForRestore(op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188
189 validate();
reed@google.com071eef92011-10-12 11:52:53 +0000190 return this->INHERITED::clipRect(rect, op, doAA);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191}
192
reed@google.com071eef92011-10-12 11:52:53 +0000193bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194 addDraw(CLIP_PATH);
195 addPath(path);
reed@google.com83ab4952011-11-11 21:34:54 +0000196 addInt(ClipParams_pack(op, doAA));
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();
reed@google.com82065d62011-02-07 15:30:46 +0000201
reed@android.comae814c82009-02-13 14:56:09 +0000202 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
reed@google.com071eef92011-10-12 11:52:53 +0000203 return this->INHERITED::clipRect(path.getBounds(), op, doAA);
reed@android.comae814c82009-02-13 14:56:09 +0000204 } else {
reed@google.com071eef92011-10-12 11:52:53 +0000205 return this->INHERITED::clipPath(path, op, doAA);
reed@android.comae814c82009-02-13 14:56:09 +0000206 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207}
208
209bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
reed@google.com82065d62011-02-07 15:30:46 +0000210 addDraw(CLIP_REGION);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211 addRegion(region);
reed@google.com83ab4952011-11-11 21:34:54 +0000212 addInt(ClipParams_pack(op, false));
reed@google.com82065d62011-02-07 15:30:46 +0000213
reed@google.com45482d12011-08-29 19:02:39 +0000214 this->recordOffsetForRestore(op);
reed@google.com82065d62011-02-07 15:30:46 +0000215
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 validate();
217 return this->INHERITED::clipRegion(region, op);
218}
219
reed@google.com2a981812011-04-14 18:59:28 +0000220void SkPictureRecord::clear(SkColor color) {
221 addDraw(DRAW_CLEAR);
222 addInt(color);
223 validate();
224}
225
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226void SkPictureRecord::drawPaint(const SkPaint& paint) {
227 addDraw(DRAW_PAINT);
228 addPaint(paint);
229 validate();
230}
231
232void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
233 const SkPaint& paint) {
234 addDraw(DRAW_POINTS);
235 addPaint(paint);
236 addInt(mode);
237 addInt(count);
238 fWriter.writeMul4(pts, count * sizeof(SkPoint));
239 validate();
240}
241
242void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
243 addDraw(DRAW_RECT);
244 addPaint(paint);
245 addRect(rect);
246 validate();
247}
248
249void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
250 addDraw(DRAW_PATH);
251 addPaint(paint);
252 addPath(path);
253 validate();
254}
255
256void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
257 const SkPaint* paint = NULL) {
258 addDraw(DRAW_BITMAP);
259 addPaintPtr(paint);
260 addBitmap(bitmap);
261 addScalar(left);
262 addScalar(top);
263 validate();
264}
265
266void SkPictureRecord::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
267 const SkRect& dst, const SkPaint* paint) {
268 addDraw(DRAW_BITMAP_RECT);
269 addPaintPtr(paint);
270 addBitmap(bitmap);
271 addIRectPtr(src); // may be null
272 addRect(dst);
273 validate();
274}
275
276void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
reed@google.comf0b5e112011-09-07 11:57:34 +0000277 const SkPaint* paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000278 addDraw(DRAW_BITMAP_MATRIX);
279 addPaintPtr(paint);
280 addBitmap(bitmap);
281 addMatrix(matrix);
282 validate();
283}
284
reed@google.comf0b5e112011-09-07 11:57:34 +0000285void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
286 const SkRect& dst, const SkPaint* paint) {
287 addDraw(DRAW_BITMAP_NINE);
288 addPaintPtr(paint);
289 addBitmap(bitmap);
290 addIRect(center);
291 addRect(dst);
292 validate();
293}
294
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
296 const SkPaint* paint = NULL) {
297 addDraw(DRAW_SPRITE);
298 addPaintPtr(paint);
299 addBitmap(bitmap);
300 addInt(left);
301 addInt(top);
302 validate();
303}
304
305void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
reed@google.com9efd9a02012-01-30 15:41:43 +0000306 SkScalar minY, SkScalar maxY) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307 SkPaint::FontMetrics metrics;
308 paint.getFontMetrics(&metrics);
309 SkRect bounds;
310 // construct a rect so we can see any adjustments from the paint.
311 // we use 0,1 for left,right, just so the rect isn't empty
reed@google.com9efd9a02012-01-30 15:41:43 +0000312 bounds.set(0, metrics.fTop + minY,
313 SK_Scalar1, metrics.fBottom + maxY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000314 (void)paint.computeFastBounds(bounds, &bounds);
315 // now record the top and bottom
316 addScalar(bounds.fTop);
317 addScalar(bounds.fBottom);
318}
319
reed@google.com82065d62011-02-07 15:30:46 +0000320void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321 SkScalar y, const SkPaint& paint) {
322 bool fast = paint.canComputeFastBounds();
reed@google.com82065d62011-02-07 15:30:46 +0000323
reed@android.com8a1c16f2008-12-17 15:59:43 +0000324 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
325 addPaint(paint);
326 addText(text, byteLength);
327 addScalar(x);
328 addScalar(y);
329 if (fast) {
reed@google.com9efd9a02012-01-30 15:41:43 +0000330 addFontMetricsTopBottom(paint, y, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331 }
332 validate();
333}
334
reed@google.com82065d62011-02-07 15:30:46 +0000335void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000336 const SkPoint pos[], const SkPaint& paint) {
337 size_t points = paint.countText(text, byteLength);
338 if (0 == points)
339 return;
340
341 bool canUseDrawH = true;
reed@google.com9efd9a02012-01-30 15:41:43 +0000342 SkScalar minY = pos[0].fY;
343 SkScalar maxY = pos[0].fY;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344 // check if the caller really should have used drawPosTextH()
345 {
346 const SkScalar firstY = pos[0].fY;
347 for (size_t index = 1; index < points; index++) {
348 if (pos[index].fY != firstY) {
349 canUseDrawH = false;
reed@google.com9efd9a02012-01-30 15:41:43 +0000350 if (pos[index].fY < minY) {
351 minY = pos[index].fY;
352 } else if (pos[index].fY > maxY) {
353 maxY = pos[index].fY;
354 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000355 }
356 }
357 }
reed@google.com82065d62011-02-07 15:30:46 +0000358
reed@google.com9efd9a02012-01-30 15:41:43 +0000359 bool fastBounds = paint.canComputeFastBounds();
360 bool fast = canUseDrawH && fastBounds;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000361
362 if (fast) {
363 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
reed@google.com9efd9a02012-01-30 15:41:43 +0000364 } else if (canUseDrawH) {
365 addDraw(DRAW_POS_TEXT_H);
366 } else if (fastBounds) {
367 addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000368 } else {
reed@google.com9efd9a02012-01-30 15:41:43 +0000369 addDraw(DRAW_POS_TEXT);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000370 }
371 addPaint(paint);
372 addText(text, byteLength);
373 addInt(points);
374
375#ifdef SK_DEBUG_SIZE
376 size_t start = fWriter.size();
377#endif
378 if (canUseDrawH) {
379 if (fast) {
reed@google.com9efd9a02012-01-30 15:41:43 +0000380 addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381 }
382 addScalar(pos[0].fY);
383 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
reed@google.com82065d62011-02-07 15:30:46 +0000384 for (size_t index = 0; index < points; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000385 *xptr++ = pos[index].fX;
386 }
387 else {
388 fWriter.writeMul4(pos, points * sizeof(SkPoint));
reed@google.com9efd9a02012-01-30 15:41:43 +0000389 if (fastBounds) {
390 addFontMetricsTopBottom(paint, minY, maxY);
391 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 }
393#ifdef SK_DEBUG_SIZE
394 fPointBytes += fWriter.size() - start;
395 fPointWrites += points;
396#endif
397 validate();
398}
399
400void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
401 const SkScalar xpos[], SkScalar constY,
402 const SkPaint& paint) {
403 size_t points = paint.countText(text, byteLength);
404 if (0 == points)
405 return;
reed@google.com82065d62011-02-07 15:30:46 +0000406
reed@android.com8a1c16f2008-12-17 15:59:43 +0000407 bool fast = paint.canComputeFastBounds();
408
409 addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
410 addPaint(paint);
411 addText(text, byteLength);
412 addInt(points);
reed@google.com82065d62011-02-07 15:30:46 +0000413
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414#ifdef SK_DEBUG_SIZE
415 size_t start = fWriter.size();
416#endif
417 if (fast) {
reed@google.com9efd9a02012-01-30 15:41:43 +0000418 addFontMetricsTopBottom(paint, constY, constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419 }
420 addScalar(constY);
421 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
422#ifdef SK_DEBUG_SIZE
423 fPointBytes += fWriter.size() - start;
424 fPointWrites += points;
425#endif
426 validate();
427}
428
reed@google.com82065d62011-02-07 15:30:46 +0000429void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
430 const SkPath& path, const SkMatrix* matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 const SkPaint& paint) {
432 addDraw(DRAW_TEXT_ON_PATH);
433 addPaint(paint);
434 addText(text, byteLength);
435 addPath(path);
436 addMatrixPtr(matrix);
437 validate();
438}
439
440void SkPictureRecord::drawPicture(SkPicture& picture) {
441 addDraw(DRAW_PICTURE);
442 addPicture(picture);
443 validate();
444}
445
446void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
447 const SkPoint vertices[], const SkPoint texs[],
448 const SkColor colors[], SkXfermode*,
449 const uint16_t indices[], int indexCount,
450 const SkPaint& paint) {
451 uint32_t flags = 0;
452 if (texs) {
453 flags |= DRAW_VERTICES_HAS_TEXS;
454 }
455 if (colors) {
456 flags |= DRAW_VERTICES_HAS_COLORS;
457 }
458 if (indexCount > 0) {
459 flags |= DRAW_VERTICES_HAS_INDICES;
460 }
461
462 addDraw(DRAW_VERTICES);
463 addPaint(paint);
464 addInt(flags);
465 addInt(vmode);
466 addInt(vertexCount);
467 addPoints(vertices, vertexCount);
468 if (flags & DRAW_VERTICES_HAS_TEXS) {
469 addPoints(texs, vertexCount);
470 }
471 if (flags & DRAW_VERTICES_HAS_COLORS) {
472 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
473 }
474 if (flags & DRAW_VERTICES_HAS_INDICES) {
475 addInt(indexCount);
476 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
477 }
478}
479
reed@android.comcb608442009-12-04 21:32:27 +0000480void SkPictureRecord::drawData(const void* data, size_t length) {
481 addDraw(DRAW_DATA);
482 addInt(length);
483 fWriter.writePad(data, length);
484}
485
reed@android.com8a1c16f2008-12-17 15:59:43 +0000486///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000487
reed@android.com8a1c16f2008-12-17 15:59:43 +0000488void SkPictureRecord::reset() {
reed@google.com82065d62011-02-07 15:30:46 +0000489 SkSafeUnref(fPathHeap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000490 fPathHeap = NULL;
491
492 fBitmaps.reset();
493 fMatrices.reset();
494 fPaints.reset();
495 fPictureRefs.unrefAll();
496 fRegions.reset();
497 fWriter.reset();
498 fHeap.reset();
reed@google.com82065d62011-02-07 15:30:46 +0000499
reed@android.com8a1c16f2008-12-17 15:59:43 +0000500 fRestoreOffsetStack.setCount(1);
501 fRestoreOffsetStack.top() = 0;
reed@google.com82065d62011-02-07 15:30:46 +0000502
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000503 fRCSet.reset();
504 fTFSet.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000505}
506
507void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
508 addInt(find(fBitmaps, bitmap));
509}
510
511void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
512 addMatrixPtr(&matrix);
513}
514
515void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
516 addInt(find(fMatrices, matrix));
517}
518
519void SkPictureRecord::addPaint(const SkPaint& paint) {
520 addPaintPtr(&paint);
521}
522
523void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
524 addInt(find(fPaints, paint));
525}
526
527void SkPictureRecord::addPath(const SkPath& path) {
528 if (NULL == fPathHeap) {
529 fPathHeap = SkNEW(SkPathHeap);
530 }
531 addInt(fPathHeap->append(path));
532}
533
534void SkPictureRecord::addPicture(SkPicture& picture) {
535 int index = fPictureRefs.find(&picture);
536 if (index < 0) { // not found
537 index = fPictureRefs.count();
538 *fPictureRefs.append() = &picture;
539 picture.ref();
540 }
541 // follow the convention of recording a 1-based index
542 addInt(index + 1);
543}
544
545void SkPictureRecord::addPoint(const SkPoint& point) {
546#ifdef SK_DEBUG_SIZE
547 size_t start = fWriter.size();
548#endif
549 fWriter.writePoint(point);
550#ifdef SK_DEBUG_SIZE
551 fPointBytes += fWriter.size() - start;
552 fPointWrites++;
553#endif
554}
reed@google.com82065d62011-02-07 15:30:46 +0000555
reed@android.com8a1c16f2008-12-17 15:59:43 +0000556void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
557 fWriter.writeMul4(pts, count * sizeof(SkPoint));
558#ifdef SK_DEBUG_SIZE
559 fPointBytes += count * sizeof(SkPoint);
560 fPointWrites++;
561#endif
562}
563
564void SkPictureRecord::addRect(const SkRect& rect) {
565#ifdef SK_DEBUG_SIZE
566 size_t start = fWriter.size();
567#endif
568 fWriter.writeRect(rect);
569#ifdef SK_DEBUG_SIZE
570 fRectBytes += fWriter.size() - start;
571 fRectWrites++;
572#endif
573}
574
575void SkPictureRecord::addRectPtr(const SkRect* rect) {
576 if (fWriter.writeBool(rect != NULL)) {
577 fWriter.writeRect(*rect);
578 }
579}
580
reed@google.comf0b5e112011-09-07 11:57:34 +0000581void SkPictureRecord::addIRect(const SkIRect& rect) {
582 fWriter.write(&rect, sizeof(rect));
583}
584
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
586 if (fWriter.writeBool(rect != NULL)) {
587 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
588 }
589}
590
591void SkPictureRecord::addRegion(const SkRegion& region) {
592 addInt(find(fRegions, region));
593}
594
595void SkPictureRecord::addText(const void* text, size_t byteLength) {
596#ifdef SK_DEBUG_SIZE
597 size_t start = fWriter.size();
598#endif
599 addInt(byteLength);
600 fWriter.writePad(text, byteLength);
601#ifdef SK_DEBUG_SIZE
602 fTextBytes += fWriter.size() - start;
603 fTextWrites++;
604#endif
605}
606
607///////////////////////////////////////////////////////////////////////////////
608
609int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
610 SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000611 &fRCSet);
reed@google.com82065d62011-02-07 15:30:46 +0000612 int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000613 bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
614 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000615 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616 return bitmaps[index]->index();
617 }
618 index = ~index;
619 *bitmaps.insert(index) = flat;
620 return fBitmapIndex++;
621}
622
623int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
624 if (matrix == NULL)
625 return 0;
626 SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000627 int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000628 matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000629 if (index >= 0) {
630 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000631 return matrices[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000632 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000633 index = ~index;
634 *matrices.insert(index) = flat;
635 return fMatrixIndex++;
636}
637
638int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
639 if (paint == NULL) {
640 return 0;
641 }
reed@google.com82065d62011-02-07 15:30:46 +0000642
reed@android.com8a1c16f2008-12-17 15:59:43 +0000643 SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000644 &fRCSet, &fTFSet);
reed@google.com82065d62011-02-07 15:30:46 +0000645 int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000646 paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
647 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000648 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000649 return paints[index]->index();
650 }
651
652 index = ~index;
653 *paints.insert(index) = flat;
654 return fPaintIndex++;
655}
656
657int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
658 SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000659 int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000660 regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000661 if (index >= 0) {
662 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000663 return regions[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000664 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000665 index = ~index;
666 *regions.insert(index) = flat;
667 return fRegionIndex++;
668}
669
670#ifdef SK_DEBUG_DUMP
671void SkPictureRecord::dumpMatrices() {
672 int count = fMatrices.count();
673 SkMatrix defaultMatrix;
674 defaultMatrix.reset();
675 for (int index = 0; index < count; index++) {
676 const SkFlatMatrix* flatMatrix = fMatrices[index];
677 flatMatrix->dump();
678 }
679}
680
681void SkPictureRecord::dumpPaints() {
682 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000683 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000684 fPaints[index]->dump();
685}
686#endif
687
688#ifdef SK_DEBUG_SIZE
689size_t SkPictureRecord::size() const {
690 size_t result = 0;
691 size_t sizeData;
692 bitmaps(&sizeData);
693 result += sizeData;
694 matrices(&sizeData);
695 result += sizeData;
696 paints(&sizeData);
697 result += sizeData;
698 paths(&sizeData);
699 result += sizeData;
700 pictures(&sizeData);
701 result += sizeData;
702 regions(&sizeData);
703 result += sizeData;
704 result += streamlen();
705 return result;
706}
707
708int SkPictureRecord::bitmaps(size_t* size) const {
709 size_t result = 0;
710 int count = fBitmaps.count();
reed@google.com82065d62011-02-07 15:30:46 +0000711 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
713 *size = result;
714 return count;
715}
716
717int SkPictureRecord::matrices(size_t* size) const {
718 int count = fMatrices.count();
719 *size = sizeof(fMatrices[0]) * count;
720 return count;
721}
722
723int SkPictureRecord::paints(size_t* size) const {
724 size_t result = 0;
725 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000726 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000727 result += sizeof(fPaints[index]) + fPaints[index]->size();
728 *size = result;
729 return count;
730}
731
732int SkPictureRecord::paths(size_t* size) const {
733 size_t result = 0;
734 int count = fPaths.count();
reed@google.com82065d62011-02-07 15:30:46 +0000735 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736 result += sizeof(fPaths[index]) + fPaths[index]->size();
737 *size = result;
738 return count;
739}
740
741int SkPictureRecord::regions(size_t* size) const {
742 size_t result = 0;
743 int count = fRegions.count();
reed@google.com82065d62011-02-07 15:30:46 +0000744 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000745 result += sizeof(fRegions[index]) + fRegions[index]->size();
746 *size = result;
747 return count;
748}
749
750size_t SkPictureRecord::streamlen() const {
751 return fWriter.size();
752}
753#endif
754
755#ifdef SK_DEBUG_VALIDATE
756void SkPictureRecord::validate() const {
757 validateBitmaps();
758 validateMatrices();
759 validatePaints();
760 validatePaths();
761 validatePictures();
762 validateRegions();
763}
764
765void SkPictureRecord::validateBitmaps() const {
766 int count = fBitmaps.count();
767 SkASSERT((unsigned) count < 0x1000);
768 for (int index = 0; index < count; index++) {
769 const SkFlatBitmap* bitPtr = fBitmaps[index];
770 SkASSERT(bitPtr);
771 bitPtr->validate();
772 }
773}
774
775void SkPictureRecord::validateMatrices() const {
776 int count = fMatrices.count();
777 SkASSERT((unsigned) count < 0x1000);
778 for (int index = 0; index < count; index++) {
779 const SkFlatMatrix* matrix = fMatrices[index];
780 SkASSERT(matrix);
reed@google.com82065d62011-02-07 15:30:46 +0000781 matrix->validate();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000782 }
783}
784
785void SkPictureRecord::validatePaints() const {
786 int count = fPaints.count();
787 SkASSERT((unsigned) count < 0x1000);
788 for (int index = 0; index < count; index++) {
789 const SkFlatPaint* paint = fPaints[index];
790 SkASSERT(paint);
791// paint->validate();
792 }
793}
794
795void SkPictureRecord::validatePaths() const {
796 int count = fPaths.count();
797 SkASSERT((unsigned) count < 0x1000);
798 for (int index = 0; index < count; index++) {
799 const SkFlatPath* path = fPaths[index];
800 SkASSERT(path);
801 path->validate();
802 }
803}
804
805void SkPictureRecord::validateRegions() const {
806 int count = fRegions.count();
807 SkASSERT((unsigned) count < 0x1000);
808 for (int index = 0; index < count; index++) {
809 const SkFlatRegion* region = fRegions[index];
810 SkASSERT(region);
811 region->validate();
812 }
813}
814#endif
815