1
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 */
8 #include "SkPictureRecord.h"
9 #include "SkTSearch.h"
10
11 #define MIN_WRITER_SIZE 16384
12 #define HEAP_BLOCK_SIZE 4096
13
SkPictureRecord(uint32_t flags)14 SkPictureRecord::SkPictureRecord(uint32_t flags) :
15 fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
16 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);
24
25 fPathHeap = NULL; // lazy allocate
26 fFirstSavedLayerIndex = kNoSavedLayerIndex;
27 }
28
~SkPictureRecord()29 SkPictureRecord::~SkPictureRecord() {
30 reset();
31 }
32
33 ///////////////////////////////////////////////////////////////////////////////
34
save(SaveFlags flags)35 int SkPictureRecord::save(SaveFlags flags) {
36 addDraw(SAVE);
37 addInt(flags);
38
39 fRestoreOffsetStack.push(0);
40
41 validate();
42 return this->INHERITED::save(flags);
43 }
44
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)45 int 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
54 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
55 fFirstSavedLayerIndex = fRestoreOffsetStack.count();
56 }
57
58 validate();
59 /* 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 */
65 int count = this->INHERITED::save(flags);
66 this->clipRectBounds(bounds, flags, NULL);
67 return count;
68 }
69
isDrawingToLayer() const70 bool SkPictureRecord::isDrawingToLayer() const {
71 return fFirstSavedLayerIndex != kNoSavedLayerIndex;
72 }
73
restore()74 void SkPictureRecord::restore() {
75 // check for underflow
76 if (fRestoreOffsetStack.count() == 0) {
77 return;
78 }
79
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 }
88
89 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
90 fFirstSavedLayerIndex = kNoSavedLayerIndex;
91 }
92
93 fRestoreOffsetStack.pop();
94
95 addDraw(RESTORE);
96 validate();
97 return this->INHERITED::restore();
98 }
99
translate(SkScalar dx,SkScalar dy)100 bool 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
scale(SkScalar sx,SkScalar sy)108 bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
109 addDraw(SCALE);
110 addScalar(sx);
111 addScalar(sy);
112 validate();
113 return this->INHERITED::scale(sx, sy);
114 }
115
rotate(SkScalar degrees)116 bool SkPictureRecord::rotate(SkScalar degrees) {
117 addDraw(ROTATE);
118 addScalar(degrees);
119 validate();
120 return this->INHERITED::rotate(degrees);
121 }
122
skew(SkScalar sx,SkScalar sy)123 bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
124 addDraw(SKEW);
125 addScalar(sx);
126 addScalar(sy);
127 validate();
128 return this->INHERITED::skew(sx, sy);
129 }
130
concat(const SkMatrix & matrix)131 bool SkPictureRecord::concat(const SkMatrix& matrix) {
132 validate();
133 addDraw(CONCAT);
134 addMatrix(matrix);
135 validate();
136 return this->INHERITED::concat(matrix);
137 }
138
setMatrix(const SkMatrix & matrix)139 void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
140 validate();
141 addDraw(SET_MATRIX);
142 addMatrix(matrix);
143 validate();
144 this->INHERITED::setMatrix(matrix);
145 }
146
regionOpExpands(SkRegion::Op op)147 static 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:
158 SkDEBUGFAIL("unknown region op");
159 return false;
160 }
161 }
162
recordOffsetForRestore(SkRegion::Op op)163 void 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 }
176
177 size_t offset = fWriter.size();
178 addInt(fRestoreOffsetStack.top());
179 fRestoreOffsetStack.top() = offset;
180 }
181
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)182 bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
183 addDraw(CLIP_RECT);
184 addRect(rect);
185 addInt(ClipParams_pack(op, doAA));
186
187 this->recordOffsetForRestore(op);
188
189 validate();
190 return this->INHERITED::clipRect(rect, op, doAA);
191 }
192
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)193 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
194 addDraw(CLIP_PATH);
195 addPath(path);
196 addInt(ClipParams_pack(op, doAA));
197
198 this->recordOffsetForRestore(op);
199
200 validate();
201
202 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
203 return this->INHERITED::clipRect(path.getBounds(), op, doAA);
204 } else {
205 return this->INHERITED::clipPath(path, op, doAA);
206 }
207 }
208
clipRegion(const SkRegion & region,SkRegion::Op op)209 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
210 addDraw(CLIP_REGION);
211 addRegion(region);
212 addInt(ClipParams_pack(op, false));
213
214 this->recordOffsetForRestore(op);
215
216 validate();
217 return this->INHERITED::clipRegion(region, op);
218 }
219
clear(SkColor color)220 void SkPictureRecord::clear(SkColor color) {
221 addDraw(DRAW_CLEAR);
222 addInt(color);
223 validate();
224 }
225
drawPaint(const SkPaint & paint)226 void SkPictureRecord::drawPaint(const SkPaint& paint) {
227 addDraw(DRAW_PAINT);
228 addPaint(paint);
229 validate();
230 }
231
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)232 void 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
drawRect(const SkRect & rect,const SkPaint & paint)242 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
243 addDraw(DRAW_RECT);
244 addPaint(paint);
245 addRect(rect);
246 validate();
247 }
248
drawPath(const SkPath & path,const SkPaint & paint)249 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
250 addDraw(DRAW_PATH);
251 addPaint(paint);
252 addPath(path);
253 validate();
254 }
255
drawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint=NULL)256 void 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
drawBitmapRect(const SkBitmap & bitmap,const SkIRect * src,const SkRect & dst,const SkPaint * paint)266 void 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
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)276 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
277 const SkPaint* paint) {
278 addDraw(DRAW_BITMAP_MATRIX);
279 addPaintPtr(paint);
280 addBitmap(bitmap);
281 addMatrix(matrix);
282 validate();
283 }
284
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)285 void 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
drawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint=NULL)295 void 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
addFontMetricsTopBottom(const SkPaint & paint,SkScalar minY,SkScalar maxY)305 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
306 SkScalar minY, SkScalar maxY) {
307 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
312 bounds.set(0, metrics.fTop + minY,
313 SK_Scalar1, metrics.fBottom + maxY);
314 (void)paint.computeFastBounds(bounds, &bounds);
315 // now record the top and bottom
316 addScalar(bounds.fTop);
317 addScalar(bounds.fBottom);
318 }
319
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)320 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
321 SkScalar y, const SkPaint& paint) {
322 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
323
324 addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT);
325 addPaint(paint);
326 addText(text, byteLength);
327 addScalar(x);
328 addScalar(y);
329 if (fast) {
330 addFontMetricsTopBottom(paint, y, y);
331 }
332 validate();
333 }
334
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)335 void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
336 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;
342 SkScalar minY = pos[0].fY;
343 SkScalar maxY = pos[0].fY;
344 // 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;
350 if (pos[index].fY < minY) {
351 minY = pos[index].fY;
352 } else if (pos[index].fY > maxY) {
353 maxY = pos[index].fY;
354 }
355 }
356 }
357 }
358
359 bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
360 bool fast = canUseDrawH && fastBounds;
361
362 if (fast) {
363 addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
364 } else if (canUseDrawH) {
365 addDraw(DRAW_POS_TEXT_H);
366 } else if (fastBounds) {
367 addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
368 } else {
369 addDraw(DRAW_POS_TEXT);
370 }
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) {
380 addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
381 }
382 addScalar(pos[0].fY);
383 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
384 for (size_t index = 0; index < points; index++)
385 *xptr++ = pos[index].fX;
386 }
387 else {
388 fWriter.writeMul4(pos, points * sizeof(SkPoint));
389 if (fastBounds) {
390 addFontMetricsTopBottom(paint, minY, maxY);
391 }
392 }
393 #ifdef SK_DEBUG_SIZE
394 fPointBytes += fWriter.size() - start;
395 fPointWrites += points;
396 #endif
397 validate();
398 }
399
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)400 void 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;
406
407 bool fast = !paint.isVerticalText() && 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);
413
414 #ifdef SK_DEBUG_SIZE
415 size_t start = fWriter.size();
416 #endif
417 if (fast) {
418 addFontMetricsTopBottom(paint, constY, constY);
419 }
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
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)429 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
430 const SkPath& path, const SkMatrix* matrix,
431 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
drawPicture(SkPicture & picture)440 void SkPictureRecord::drawPicture(SkPicture& picture) {
441 addDraw(DRAW_PICTURE);
442 addPicture(picture);
443 validate();
444 }
445
drawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode *,const uint16_t indices[],int indexCount,const SkPaint & paint)446 void 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
drawData(const void * data,size_t length)480 void SkPictureRecord::drawData(const void* data, size_t length) {
481 addDraw(DRAW_DATA);
482 addInt(length);
483 fWriter.writePad(data, length);
484 }
485
486 ///////////////////////////////////////////////////////////////////////////////
487
reset()488 void SkPictureRecord::reset() {
489 SkSafeUnref(fPathHeap);
490 fPathHeap = NULL;
491
492 fBitmaps.reset();
493 fMatrices.reset();
494 fPaints.reset();
495 fPictureRefs.unrefAll();
496 fRegions.reset();
497 fWriter.reset();
498 fHeap.reset();
499
500 fRestoreOffsetStack.setCount(1);
501 fRestoreOffsetStack.top() = 0;
502
503 fRCSet.reset();
504 fTFSet.reset();
505 }
506
addBitmap(const SkBitmap & bitmap)507 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
508 addInt(find(fBitmaps, bitmap));
509 }
510
addMatrix(const SkMatrix & matrix)511 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
512 addMatrixPtr(&matrix);
513 }
514
addMatrixPtr(const SkMatrix * matrix)515 void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
516 addInt(find(fMatrices, matrix));
517 }
518
addPaint(const SkPaint & paint)519 void SkPictureRecord::addPaint(const SkPaint& paint) {
520 addPaintPtr(&paint);
521 }
522
addPaintPtr(const SkPaint * paint)523 void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
524 addInt(find(fPaints, paint));
525 }
526
addPath(const SkPath & path)527 void SkPictureRecord::addPath(const SkPath& path) {
528 if (NULL == fPathHeap) {
529 fPathHeap = SkNEW(SkPathHeap);
530 }
531 addInt(fPathHeap->append(path));
532 }
533
addPicture(SkPicture & picture)534 void 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
addPoint(const SkPoint & point)545 void 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 }
555
addPoints(const SkPoint pts[],int count)556 void 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
addRect(const SkRect & rect)564 void 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
addRectPtr(const SkRect * rect)575 void SkPictureRecord::addRectPtr(const SkRect* rect) {
576 if (fWriter.writeBool(rect != NULL)) {
577 fWriter.writeRect(*rect);
578 }
579 }
580
addIRect(const SkIRect & rect)581 void SkPictureRecord::addIRect(const SkIRect& rect) {
582 fWriter.write(&rect, sizeof(rect));
583 }
584
addIRectPtr(const SkIRect * rect)585 void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
586 if (fWriter.writeBool(rect != NULL)) {
587 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
588 }
589 }
590
addRegion(const SkRegion & region)591 void SkPictureRecord::addRegion(const SkRegion& region) {
592 addInt(find(fRegions, region));
593 }
594
addText(const void * text,size_t byteLength)595 void 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
find(SkTDArray<const SkFlatBitmap * > & bitmaps,const SkBitmap & bitmap)609 int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitmap& bitmap) {
610 SkFlatBitmap* flat = SkFlatBitmap::Flatten(&fHeap, bitmap, fBitmapIndex,
611 &fRCSet);
612 int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
613 bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
614 if (index >= 0) {
615 (void)fHeap.unalloc(flat);
616 return bitmaps[index]->index();
617 }
618 index = ~index;
619 *bitmaps.insert(index) = flat;
620 return fBitmapIndex++;
621 }
622
find(SkTDArray<const SkFlatMatrix * > & matrices,const SkMatrix * matrix)623 int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix) {
624 if (matrix == NULL)
625 return 0;
626 SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
627 int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
628 matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
629 if (index >= 0) {
630 (void)fHeap.unalloc(flat);
631 return matrices[index]->index();
632 }
633 index = ~index;
634 *matrices.insert(index) = flat;
635 return fMatrixIndex++;
636 }
637
find(SkTDArray<const SkFlatPaint * > & paints,const SkPaint * paint)638 int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint) {
639 if (paint == NULL) {
640 return 0;
641 }
642
643 SkFlatPaint* flat = SkFlatPaint::Flatten(&fHeap, *paint, fPaintIndex,
644 &fRCSet, &fTFSet);
645 int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
646 paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
647 if (index >= 0) {
648 (void)fHeap.unalloc(flat);
649 return paints[index]->index();
650 }
651
652 index = ~index;
653 *paints.insert(index) = flat;
654 return fPaintIndex++;
655 }
656
find(SkTDArray<const SkFlatRegion * > & regions,const SkRegion & region)657 int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) {
658 SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
659 int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
660 regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
661 if (index >= 0) {
662 (void)fHeap.unalloc(flat);
663 return regions[index]->index();
664 }
665 index = ~index;
666 *regions.insert(index) = flat;
667 return fRegionIndex++;
668 }
669
670 #ifdef SK_DEBUG_DUMP
dumpMatrices()671 void 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
dumpPaints()681 void SkPictureRecord::dumpPaints() {
682 int count = fPaints.count();
683 for (int index = 0; index < count; index++)
684 fPaints[index]->dump();
685 }
686 #endif
687
688 #ifdef SK_DEBUG_SIZE
size() const689 size_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
bitmaps(size_t * size) const708 int SkPictureRecord::bitmaps(size_t* size) const {
709 size_t result = 0;
710 int count = fBitmaps.count();
711 for (int index = 0; index < count; index++)
712 result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
713 *size = result;
714 return count;
715 }
716
matrices(size_t * size) const717 int SkPictureRecord::matrices(size_t* size) const {
718 int count = fMatrices.count();
719 *size = sizeof(fMatrices[0]) * count;
720 return count;
721 }
722
paints(size_t * size) const723 int SkPictureRecord::paints(size_t* size) const {
724 size_t result = 0;
725 int count = fPaints.count();
726 for (int index = 0; index < count; index++)
727 result += sizeof(fPaints[index]) + fPaints[index]->size();
728 *size = result;
729 return count;
730 }
731
paths(size_t * size) const732 int SkPictureRecord::paths(size_t* size) const {
733 size_t result = 0;
734 int count = fPaths.count();
735 for (int index = 0; index < count; index++)
736 result += sizeof(fPaths[index]) + fPaths[index]->size();
737 *size = result;
738 return count;
739 }
740
regions(size_t * size) const741 int SkPictureRecord::regions(size_t* size) const {
742 size_t result = 0;
743 int count = fRegions.count();
744 for (int index = 0; index < count; index++)
745 result += sizeof(fRegions[index]) + fRegions[index]->size();
746 *size = result;
747 return count;
748 }
749
streamlen() const750 size_t SkPictureRecord::streamlen() const {
751 return fWriter.size();
752 }
753 #endif
754
755 #ifdef SK_DEBUG_VALIDATE
validate() const756 void SkPictureRecord::validate() const {
757 validateBitmaps();
758 validateMatrices();
759 validatePaints();
760 validatePaths();
761 validatePictures();
762 validateRegions();
763 }
764
validateBitmaps() const765 void 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
validateMatrices() const775 void 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);
781 matrix->validate();
782 }
783 }
784
validatePaints() const785 void 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
validatePaths() const795 void 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
validateRegions() const805 void 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
816