blob: d78c13abbda83d04a00b413dbd961778b1a8e0a4 [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:
142 SkASSERT(!"unknown region op");
143 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@android.com8a1c16f2008-12-17 15:59:43 +0000166bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op) {
167 addDraw(CLIP_RECT);
168 addRect(rect);
169 addInt(op);
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();
174 return this->INHERITED::clipRect(rect, op);
175}
176
177bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op) {
178 addDraw(CLIP_PATH);
179 addPath(path);
180 addInt(op);
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@android.comd252db02009-04-01 18:31:44 +0000187 return this->INHERITED::clipRect(path.getBounds(), op);
reed@android.comae814c82009-02-13 14:56:09 +0000188 } else {
189 return this->INHERITED::clipPath(path, op);
190 }
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);
196 addInt(op);
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,
261 const SkPaint* paint) {
262 addDraw(DRAW_BITMAP_MATRIX);
263 addPaintPtr(paint);
264 addBitmap(bitmap);
265 addMatrix(matrix);
266 validate();
267}
268
269void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
270 const SkPaint* paint = NULL) {
271 addDraw(DRAW_SPRITE);
272 addPaintPtr(paint);
273 addBitmap(bitmap);
274 addInt(left);
275 addInt(top);
276 validate();
277}
278
279void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
280 SkScalar baselineY) {
281 SkPaint::FontMetrics metrics;
282 paint.getFontMetrics(&metrics);
283 SkRect bounds;
284 // construct a rect so we can see any adjustments from the paint.
285 // we use 0,1 for left,right, just so the rect isn't empty
286 bounds.set(0, metrics.fTop + baselineY,
287 SK_Scalar1, metrics.fBottom + baselineY);
288 (void)paint.computeFastBounds(bounds, &bounds);
289 // now record the top and bottom
290 addScalar(bounds.fTop);
291 addScalar(bounds.fBottom);
292}
293
reed@google.com82065d62011-02-07 15:30:46 +0000294void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295 SkScalar y, const SkPaint& paint) {
296 bool fast = paint.canComputeFastBounds();
reed@google.com82065d62011-02-07 15:30:46 +0000297
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
299 addPaint(paint);
300 addText(text, byteLength);
301 addScalar(x);
302 addScalar(y);
303 if (fast) {
304 addFontMetricsTopBottom(paint, y);
305 }
306 validate();
307}
308
reed@google.com82065d62011-02-07 15:30:46 +0000309void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310 const SkPoint pos[], const SkPaint& paint) {
311 size_t points = paint.countText(text, byteLength);
312 if (0 == points)
313 return;
314
315 bool canUseDrawH = true;
316 // check if the caller really should have used drawPosTextH()
317 {
318 const SkScalar firstY = pos[0].fY;
319 for (size_t index = 1; index < points; index++) {
320 if (pos[index].fY != firstY) {
321 canUseDrawH = false;
322 break;
323 }
324 }
325 }
reed@google.com82065d62011-02-07 15:30:46 +0000326
reed@android.com8a1c16f2008-12-17 15:59:43 +0000327 bool fast = canUseDrawH && paint.canComputeFastBounds();
328
329 if (fast) {
330 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
331 } else {
332 addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
333 }
334 addPaint(paint);
335 addText(text, byteLength);
336 addInt(points);
337
338#ifdef SK_DEBUG_SIZE
339 size_t start = fWriter.size();
340#endif
341 if (canUseDrawH) {
342 if (fast) {
343 addFontMetricsTopBottom(paint, pos[0].fY);
344 }
345 addScalar(pos[0].fY);
346 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
reed@google.com82065d62011-02-07 15:30:46 +0000347 for (size_t index = 0; index < points; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000348 *xptr++ = pos[index].fX;
349 }
350 else {
351 fWriter.writeMul4(pos, points * sizeof(SkPoint));
352 }
353#ifdef SK_DEBUG_SIZE
354 fPointBytes += fWriter.size() - start;
355 fPointWrites += points;
356#endif
357 validate();
358}
359
360void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
361 const SkScalar xpos[], SkScalar constY,
362 const SkPaint& paint) {
363 size_t points = paint.countText(text, byteLength);
364 if (0 == points)
365 return;
reed@google.com82065d62011-02-07 15:30:46 +0000366
reed@android.com8a1c16f2008-12-17 15:59:43 +0000367 bool fast = paint.canComputeFastBounds();
368
369 addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H);
370 addPaint(paint);
371 addText(text, byteLength);
372 addInt(points);
reed@google.com82065d62011-02-07 15:30:46 +0000373
reed@android.com8a1c16f2008-12-17 15:59:43 +0000374#ifdef SK_DEBUG_SIZE
375 size_t start = fWriter.size();
376#endif
377 if (fast) {
378 addFontMetricsTopBottom(paint, constY);
379 }
380 addScalar(constY);
381 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
382#ifdef SK_DEBUG_SIZE
383 fPointBytes += fWriter.size() - start;
384 fPointWrites += points;
385#endif
386 validate();
387}
388
reed@google.com82065d62011-02-07 15:30:46 +0000389void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
390 const SkPath& path, const SkMatrix* matrix,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000391 const SkPaint& paint) {
392 addDraw(DRAW_TEXT_ON_PATH);
393 addPaint(paint);
394 addText(text, byteLength);
395 addPath(path);
396 addMatrixPtr(matrix);
397 validate();
398}
399
400void SkPictureRecord::drawPicture(SkPicture& picture) {
401 addDraw(DRAW_PICTURE);
402 addPicture(picture);
403 validate();
404}
405
406void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
407 const SkPoint vertices[], const SkPoint texs[],
408 const SkColor colors[], SkXfermode*,
409 const uint16_t indices[], int indexCount,
410 const SkPaint& paint) {
411 uint32_t flags = 0;
412 if (texs) {
413 flags |= DRAW_VERTICES_HAS_TEXS;
414 }
415 if (colors) {
416 flags |= DRAW_VERTICES_HAS_COLORS;
417 }
418 if (indexCount > 0) {
419 flags |= DRAW_VERTICES_HAS_INDICES;
420 }
421
422 addDraw(DRAW_VERTICES);
423 addPaint(paint);
424 addInt(flags);
425 addInt(vmode);
426 addInt(vertexCount);
427 addPoints(vertices, vertexCount);
428 if (flags & DRAW_VERTICES_HAS_TEXS) {
429 addPoints(texs, vertexCount);
430 }
431 if (flags & DRAW_VERTICES_HAS_COLORS) {
432 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
433 }
434 if (flags & DRAW_VERTICES_HAS_INDICES) {
435 addInt(indexCount);
436 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
437 }
438}
439
reed@android.comcb608442009-12-04 21:32:27 +0000440void SkPictureRecord::drawData(const void* data, size_t length) {
441 addDraw(DRAW_DATA);
442 addInt(length);
443 fWriter.writePad(data, length);
444}
445
reed@android.com8a1c16f2008-12-17 15:59:43 +0000446///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000447
reed@android.com8a1c16f2008-12-17 15:59:43 +0000448void SkPictureRecord::reset() {
reed@google.com82065d62011-02-07 15:30:46 +0000449 SkSafeUnref(fPathHeap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000450 fPathHeap = NULL;
451
452 fBitmaps.reset();
453 fMatrices.reset();
454 fPaints.reset();
455 fPictureRefs.unrefAll();
456 fRegions.reset();
457 fWriter.reset();
458 fHeap.reset();
reed@google.com82065d62011-02-07 15:30:46 +0000459
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460 fRestoreOffsetStack.setCount(1);
461 fRestoreOffsetStack.top() = 0;
reed@google.com82065d62011-02-07 15:30:46 +0000462
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000463 fRCSet.reset();
464 fTFSet.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465}
466
467void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
468 addInt(find(fBitmaps, bitmap));
469}
470
471void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
472 addMatrixPtr(&matrix);
473}
474
475void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
476 addInt(find(fMatrices, matrix));
477}
478
479void SkPictureRecord::addPaint(const SkPaint& paint) {
480 addPaintPtr(&paint);
481}
482
483void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
484 addInt(find(fPaints, paint));
485}
486
487void SkPictureRecord::addPath(const SkPath& path) {
488 if (NULL == fPathHeap) {
489 fPathHeap = SkNEW(SkPathHeap);
490 }
491 addInt(fPathHeap->append(path));
492}
493
494void SkPictureRecord::addPicture(SkPicture& picture) {
495 int index = fPictureRefs.find(&picture);
496 if (index < 0) { // not found
497 index = fPictureRefs.count();
498 *fPictureRefs.append() = &picture;
499 picture.ref();
500 }
501 // follow the convention of recording a 1-based index
502 addInt(index + 1);
503}
504
505void SkPictureRecord::addPoint(const SkPoint& point) {
506#ifdef SK_DEBUG_SIZE
507 size_t start = fWriter.size();
508#endif
509 fWriter.writePoint(point);
510#ifdef SK_DEBUG_SIZE
511 fPointBytes += fWriter.size() - start;
512 fPointWrites++;
513#endif
514}
reed@google.com82065d62011-02-07 15:30:46 +0000515
reed@android.com8a1c16f2008-12-17 15:59:43 +0000516void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
517 fWriter.writeMul4(pts, count * sizeof(SkPoint));
518#ifdef SK_DEBUG_SIZE
519 fPointBytes += count * sizeof(SkPoint);
520 fPointWrites++;
521#endif
522}
523
524void SkPictureRecord::addRect(const SkRect& rect) {
525#ifdef SK_DEBUG_SIZE
526 size_t start = fWriter.size();
527#endif
528 fWriter.writeRect(rect);
529#ifdef SK_DEBUG_SIZE
530 fRectBytes += fWriter.size() - start;
531 fRectWrites++;
532#endif
533}
534
535void SkPictureRecord::addRectPtr(const SkRect* rect) {
536 if (fWriter.writeBool(rect != NULL)) {
537 fWriter.writeRect(*rect);
538 }
539}
540
541void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
542 if (fWriter.writeBool(rect != NULL)) {
543 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
544 }
545}
546
547void SkPictureRecord::addRegion(const SkRegion& region) {
548 addInt(find(fRegions, region));
549}
550
551void SkPictureRecord::addText(const void* text, size_t byteLength) {
552#ifdef SK_DEBUG_SIZE
553 size_t start = fWriter.size();
554#endif
555 addInt(byteLength);
556 fWriter.writePad(text, byteLength);
557#ifdef SK_DEBUG_SIZE
558 fTextBytes += fWriter.size() - start;
559 fTextWrites++;
560#endif
561}
562
563///////////////////////////////////////////////////////////////////////////////
564
565int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
566 SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000567 &fRCSet);
reed@google.com82065d62011-02-07 15:30:46 +0000568 int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000569 bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
570 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000571 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000572 return bitmaps[index]->index();
573 }
574 index = ~index;
575 *bitmaps.insert(index) = flat;
576 return fBitmapIndex++;
577}
578
579int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
580 if (matrix == NULL)
581 return 0;
582 SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000583 int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000584 matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000585 if (index >= 0) {
586 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587 return matrices[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000588 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589 index = ~index;
590 *matrices.insert(index) = flat;
591 return fMatrixIndex++;
592}
593
594int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
595 if (paint == NULL) {
596 return 0;
597 }
reed@google.com82065d62011-02-07 15:30:46 +0000598
reed@android.com8a1c16f2008-12-17 15:59:43 +0000599 SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
mike@reedtribe.orge9e08cc2011-04-29 01:44:52 +0000600 &fRCSet, &fTFSet);
reed@google.com82065d62011-02-07 15:30:46 +0000601 int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000602 paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
603 if (index >= 0) {
reed@android.comaefd2bc2009-03-30 21:02:14 +0000604 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000605 return paints[index]->index();
606 }
607
608 index = ~index;
609 *paints.insert(index) = flat;
610 return fPaintIndex++;
611}
612
613int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
614 SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
reed@google.com82065d62011-02-07 15:30:46 +0000615 int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616 regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
reed@android.comaefd2bc2009-03-30 21:02:14 +0000617 if (index >= 0) {
618 (void)fHeap.unalloc(flat);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000619 return regions[index]->index();
reed@android.comaefd2bc2009-03-30 21:02:14 +0000620 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000621 index = ~index;
622 *regions.insert(index) = flat;
623 return fRegionIndex++;
624}
625
626#ifdef SK_DEBUG_DUMP
627void SkPictureRecord::dumpMatrices() {
628 int count = fMatrices.count();
629 SkMatrix defaultMatrix;
630 defaultMatrix.reset();
631 for (int index = 0; index < count; index++) {
632 const SkFlatMatrix* flatMatrix = fMatrices[index];
633 flatMatrix->dump();
634 }
635}
636
637void SkPictureRecord::dumpPaints() {
638 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000639 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000640 fPaints[index]->dump();
641}
642#endif
643
644#ifdef SK_DEBUG_SIZE
645size_t SkPictureRecord::size() const {
646 size_t result = 0;
647 size_t sizeData;
648 bitmaps(&sizeData);
649 result += sizeData;
650 matrices(&sizeData);
651 result += sizeData;
652 paints(&sizeData);
653 result += sizeData;
654 paths(&sizeData);
655 result += sizeData;
656 pictures(&sizeData);
657 result += sizeData;
658 regions(&sizeData);
659 result += sizeData;
660 result += streamlen();
661 return result;
662}
663
664int SkPictureRecord::bitmaps(size_t* size) const {
665 size_t result = 0;
666 int count = fBitmaps.count();
reed@google.com82065d62011-02-07 15:30:46 +0000667 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000668 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
669 *size = result;
670 return count;
671}
672
673int SkPictureRecord::matrices(size_t* size) const {
674 int count = fMatrices.count();
675 *size = sizeof(fMatrices[0]) * count;
676 return count;
677}
678
679int SkPictureRecord::paints(size_t* size) const {
680 size_t result = 0;
681 int count = fPaints.count();
reed@google.com82065d62011-02-07 15:30:46 +0000682 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000683 result += sizeof(fPaints[index]) + fPaints[index]->size();
684 *size = result;
685 return count;
686}
687
688int SkPictureRecord::paths(size_t* size) const {
689 size_t result = 0;
690 int count = fPaths.count();
reed@google.com82065d62011-02-07 15:30:46 +0000691 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000692 result += sizeof(fPaths[index]) + fPaths[index]->size();
693 *size = result;
694 return count;
695}
696
697int SkPictureRecord::regions(size_t* size) const {
698 size_t result = 0;
699 int count = fRegions.count();
reed@google.com82065d62011-02-07 15:30:46 +0000700 for (int index = 0; index < count; index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000701 result += sizeof(fRegions[index]) + fRegions[index]->size();
702 *size = result;
703 return count;
704}
705
706size_t SkPictureRecord::streamlen() const {
707 return fWriter.size();
708}
709#endif
710
711#ifdef SK_DEBUG_VALIDATE
712void SkPictureRecord::validate() const {
713 validateBitmaps();
714 validateMatrices();
715 validatePaints();
716 validatePaths();
717 validatePictures();
718 validateRegions();
719}
720
721void SkPictureRecord::validateBitmaps() const {
722 int count = fBitmaps.count();
723 SkASSERT((unsigned) count < 0x1000);
724 for (int index = 0; index < count; index++) {
725 const SkFlatBitmap* bitPtr = fBitmaps[index];
726 SkASSERT(bitPtr);
727 bitPtr->validate();
728 }
729}
730
731void SkPictureRecord::validateMatrices() const {
732 int count = fMatrices.count();
733 SkASSERT((unsigned) count < 0x1000);
734 for (int index = 0; index < count; index++) {
735 const SkFlatMatrix* matrix = fMatrices[index];
736 SkASSERT(matrix);
reed@google.com82065d62011-02-07 15:30:46 +0000737 matrix->validate();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000738 }
739}
740
741void SkPictureRecord::validatePaints() const {
742 int count = fPaints.count();
743 SkASSERT((unsigned) count < 0x1000);
744 for (int index = 0; index < count; index++) {
745 const SkFlatPaint* paint = fPaints[index];
746 SkASSERT(paint);
747// paint->validate();
748 }
749}
750
751void SkPictureRecord::validatePaths() const {
752 int count = fPaths.count();
753 SkASSERT((unsigned) count < 0x1000);
754 for (int index = 0; index < count; index++) {
755 const SkFlatPath* path = fPaths[index];
756 SkASSERT(path);
757 path->validate();
758 }
759}
760
761void SkPictureRecord::validateRegions() const {
762 int count = fRegions.count();
763 SkASSERT((unsigned) count < 0x1000);
764 for (int index = 0; index < count; index++) {
765 const SkFlatRegion* region = fRegions[index];
766 SkASSERT(region);
767 region->validate();
768 }
769}
770#endif
771