OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkPictureRecord.h" | 8 #include "SkPictureRecord.h" |
9 #include "SkTSearch.h" | 9 #include "SkTSearch.h" |
10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 SkSafeUnref(fBitmapHeap); | 56 SkSafeUnref(fBitmapHeap); |
57 SkSafeUnref(fPathHeap); | 57 SkSafeUnref(fPathHeap); |
58 SkSafeUnref(fBoundingHierarchy); | 58 SkSafeUnref(fBoundingHierarchy); |
59 SkSafeUnref(fStateTree); | 59 SkSafeUnref(fStateTree); |
60 fFlattenableHeap.setBitmapStorage(NULL); | 60 fFlattenableHeap.setBitmapStorage(NULL); |
61 fPictureRefs.unrefAll(); | 61 fPictureRefs.unrefAll(); |
62 } | 62 } |
63 | 63 |
64 /////////////////////////////////////////////////////////////////////////////// | 64 /////////////////////////////////////////////////////////////////////////////// |
65 | 65 |
66 enum DrawTypeFlags { | |
67 kHasPaint_DrawTypeFlag = 1 << 0, | |
68 kModifiesState_DrawTypeFlag = 1 << 1, // modifes clip or matrix state | |
69 kCanRecordBounds_DrawTypeFlag = 1 << 2, | |
70 }; | |
71 | |
72 static const uint8_t gDrawTypeFlags[LAST_DRAWTYPE_ENUM + 1] = { | |
73 0, // UNUSED | |
74 kModifiesState_DrawTypeFlag, // CLIP_PATH | |
75 kModifiesState_DrawTypeFlag, // CLIP_REGION | |
76 kModifiesState_DrawTypeFlag, // CLIP_RECT | |
77 kModifiesState_DrawTypeFlag, // CLIP_RRECT | |
78 kModifiesState_DrawTypeFlag, // CONCAT | |
79 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_BITMAP | |
80 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_BITMAP_MATR IX | |
81 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_BITMAP_NINE | |
82 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_BITMAP_RECT _TO_RECT | |
83 0, // DRAW_CLEAR | |
84 0, // DRAW_DATA | |
85 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_OVAL | |
86 kHasPaint_DrawTypeFlag, // DRAW_PAINT | |
87 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_PATH | |
88 kModifiesState_DrawTypeFlag, // DRAW_PICTURE | |
89 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_POINTS | |
90 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_POS_TEXT | |
91 kHasPaint_DrawTypeFlag, // DRAW_POS_TEXT_TO P_BOTTOM | |
92 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_POS_TEXT_H | |
93 kHasPaint_DrawTypeFlag, // DRAW_POS_TEXT_H_ TOP_BOTTOM | |
94 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_RECT | |
95 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_RRECT | |
96 kHasPaint_DrawTypeFlag, // DRAW_SPRITE | |
97 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_TEXT | |
98 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_TEXT_ON_PAT H | |
99 kHasPaint_DrawTypeFlag, // DRAW_TEXT_TOP_BO TTOM | |
100 kHasPaint_DrawTypeFlag | kCanRecordBounds_DrawTypeFlag, // DRAW_VERTICES | |
101 kModifiesState_DrawTypeFlag, // RESTORE | |
102 kModifiesState_DrawTypeFlag, // ROTATE | |
103 kModifiesState_DrawTypeFlag, // SAVE | |
104 kHasPaint_DrawTypeFlag | kModifiesState_DrawTypeFlag, // SAVE_LAYER | |
105 kModifiesState_DrawTypeFlag, // SCALE | |
106 kModifiesState_DrawTypeFlag, // SET_MATRIX | |
107 kModifiesState_DrawTypeFlag, // SKEW | |
108 kModifiesState_DrawTypeFlag, // TRANSLATE | |
109 0, // NOOP | |
110 }; | |
111 | |
112 bool SkPictureRecord::canRecordBounds(DrawType op) { | |
113 #if SK_RECORD_BOUNDS_IN_PICTURE | |
114 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM); | |
115 return SkToBool(gDrawTypeFlags[op] & kCanRecordBounds_DrawTypeFlag); | |
116 #else | |
117 return false; | |
118 #endif | |
119 } | |
120 | |
121 static inline bool modifies_state(DrawType op) { | |
122 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM); | |
123 return SkToBool(gDrawTypeFlags[op] & kModifiesState_DrawTypeFlag); | |
124 } | |
125 | |
66 // Return the offset of the paint inside a given op's byte stream. A zero | 126 // Return the offset of the paint inside a given op's byte stream. A zero |
67 // return value means there is no paint (and you really shouldn't be calling | 127 // return value means there is no paint (and you really shouldn't be calling |
68 // this method) | 128 // this method) |
69 static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) { | 129 static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) { |
70 // These offsets are where the paint would be if the op size doesn't overflo w | 130 // These offsets are where the paint would be if the op size doesn't overflo w |
71 static const uint8_t gPaintOffsets[LAST_DRAWTYPE_ENUM + 1] = { | |
72 0, // UNUSED - no paint | |
73 0, // CLIP_PATH - no paint | |
74 0, // CLIP_REGION - no paint | |
75 0, // CLIP_RECT - no paint | |
76 0, // CLIP_RRECT - no paint | |
77 0, // CONCAT - no paint | |
78 1, // DRAW_BITMAP - right after op code | |
79 1, // DRAW_BITMAP_MATRIX - right after op code | |
80 1, // DRAW_BITMAP_NINE - right after op code | |
81 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code | |
82 0, // DRAW_CLEAR - no paint | |
83 0, // DRAW_DATA - no paint | |
84 1, // DRAW_OVAL - right after op code | |
85 1, // DRAW_PAINT - right after op code | |
86 1, // DRAW_PATH - right after op code | |
87 0, // DRAW_PICTURE - no paint | |
88 1, // DRAW_POINTS - right after op code | |
89 1, // DRAW_POS_TEXT - right after op code | |
90 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code | |
91 1, // DRAW_POS_TEXT_H - right after op code | |
92 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code | |
93 1, // DRAW_RECT - right after op code | |
94 1, // DRAW_RRECT - right after op code | |
95 1, // DRAW_SPRITE - right after op code | |
96 1, // DRAW_TEXT - right after op code | |
97 1, // DRAW_TEXT_ON_PATH - right after op code | |
98 1, // DRAW_TEXT_TOP_BOTTOM - right after op code | |
99 1, // DRAW_VERTICES - right after op code | |
100 0, // RESTORE - no paint | |
101 0, // ROTATE - no paint | |
102 0, // SAVE - no paint | |
103 0, // SAVE_LAYER - see below - this paint's location varies | |
104 0, // SCALE - no paint | |
105 0, // SET_MATRIX - no paint | |
106 0, // SKEW - no paint | |
107 0, // TRANSLATE - no paint | |
108 0, // NOOP - no paint | |
109 }; | |
110 | |
111 SkASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1); | |
112 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM); | 131 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM); |
113 | 132 |
114 int overflow = 0; | 133 int offset = sizeof(uint32_t); // storage for op and 24-bit size |
115 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) { | 134 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) { |
116 // This op's size overflows so an extra uint32_t will be written | 135 // This op's size overflows so an extra uint32_t will be written |
117 // after the op code | 136 // after the op code |
118 overflow = sizeof(uint32_t); | 137 offset += sizeof(uint32_t); |
138 } | |
139 if (SkPictureRecord::canRecordBounds(op)) { | |
140 offset += sizeof(SkIRect); | |
119 } | 141 } |
120 | 142 |
121 if (SAVE_LAYER == op) { | 143 if (SAVE_LAYER == op) { |
122 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size; | 144 static const uint32_t kSaveLayerNoBoundsPaintOffset = kUInt32Size; |
123 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect); | 145 static const uint32_t kSaveLayerWithBoundsPaintOffset = kUInt32Size + si zeof(SkRect); |
124 | 146 |
125 if (kSaveLayerNoBoundsSize == opSize) { | 147 if (kSaveLayerNoBoundsSize == opSize) { |
126 return kSaveLayerNoBoundsPaintOffset + overflow; | 148 offset += kSaveLayerNoBoundsPaintOffset; |
127 } else { | 149 } else { |
128 SkASSERT(kSaveLayerWithBoundsSize == opSize); | 150 SkASSERT(kSaveLayerWithBoundsSize == opSize); |
129 return kSaveLayerWithBoundsPaintOffset + overflow; | 151 offset += kSaveLayerWithBoundsPaintOffset; |
130 } | 152 } |
131 } | 153 } |
132 | 154 |
133 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this meth od | 155 SkASSERT(kHasPaint_DrawTypeFlag & gDrawTypeFlags[op]); // Shouldn't be call ing this method |
134 return gPaintOffsets[op] * sizeof(uint32_t) + overflow; | 156 return offset; |
135 } | 157 } |
136 | 158 |
137 SkDevice* SkPictureRecord::setDevice(SkDevice* device) { | 159 SkDevice* SkPictureRecord::setDevice(SkDevice* device) { |
138 SkASSERT(!"eeek, don't try to change the device on a recording canvas"); | 160 SkASSERT(!"eeek, don't try to change the device on a recording canvas"); |
139 return this->INHERITED::setDevice(device); | 161 return this->INHERITED::setDevice(device); |
140 } | 162 } |
141 | 163 |
142 int SkPictureRecord::save(SaveFlags flags) { | 164 int SkPictureRecord::save(SaveFlags flags) { |
143 // record the offset to us, making it non-positive to distinguish a save | 165 // record the offset to us, making it non-positive to distinguish a save |
144 // from a clip entry. | 166 // from a clip entry. |
145 fRestoreOffsetStack.push(-(int32_t)fWriter.size()); | 167 fRestoreOffsetStack.push(-(int32_t)fWriter.size()); |
146 | 168 |
147 // op + flags | 169 // op + flags |
148 uint32_t size = 2 * kUInt32Size; | 170 uint32_t size = 2 * kUInt32Size; |
149 uint32_t initialOffset = this->addDraw(SAVE, &size); | 171 uint32_t initialOffset = this->addDraw(SAVE, &size); |
172 SkASSERT(kInvalidOffset != initialOffset); | |
150 addInt(flags); | 173 addInt(flags); |
151 | 174 |
152 validate(initialOffset, size); | 175 validate(initialOffset, size); |
153 return this->INHERITED::save(flags); | 176 return this->INHERITED::save(flags); |
154 } | 177 } |
155 | 178 |
156 int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint, | 179 int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint, |
157 SaveFlags flags) { | 180 SaveFlags flags) { |
158 // record the offset to us, making it non-positive to distinguish a save | 181 // record the offset to us, making it non-positive to distinguish a save |
159 // from a clip entry. | 182 // from a clip entry. |
160 fRestoreOffsetStack.push(-(int32_t)fWriter.size()); | 183 fRestoreOffsetStack.push(-(int32_t)fWriter.size()); |
161 | 184 |
162 // op + bool for 'bounds' | 185 // op + bool for 'bounds' |
163 uint32_t size = 2 * kUInt32Size; | 186 uint32_t size = 2 * kUInt32Size; |
164 if (NULL != bounds) { | 187 if (NULL != bounds) { |
165 size += sizeof(*bounds); // + rect | 188 size += sizeof(*bounds); // + rect |
166 } | 189 } |
167 // + paint index + flags | 190 // + paint index + flags |
168 size += 2 * kUInt32Size; | 191 size += 2 * kUInt32Size; |
169 | 192 |
170 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size) ; | 193 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size) ; |
171 | 194 |
172 uint32_t initialOffset = this->addDraw(SAVE_LAYER, &size); | 195 uint32_t initialOffset = this->addDraw(SAVE_LAYER, &size); |
196 SkASSERT(kInvalidOffset != initialOffset); | |
173 addRectPtr(bounds); | 197 addRectPtr(bounds); |
174 SkASSERT(initialOffset+getPaintOffset(SAVE_LAYER, size) == fWriter.size()); | 198 SkASSERT(initialOffset + getPaintOffset(SAVE_LAYER, size) == fWriter.size()) ; |
175 addPaintPtr(paint); | 199 addPaintPtr(paint); |
176 addInt(flags); | 200 addInt(flags); |
177 | 201 |
178 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) { | 202 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) { |
179 fFirstSavedLayerIndex = fRestoreOffsetStack.count(); | 203 fFirstSavedLayerIndex = fRestoreOffsetStack.count(); |
180 } | 204 } |
181 | 205 |
182 validate(initialOffset, size); | 206 validate(initialOffset, size); |
183 /* Don't actually call saveLayer, because that will try to allocate an | 207 /* Don't actually call saveLayer, because that will try to allocate an |
184 offscreen device (potentially very big) which we don't actually need | 208 offscreen device (potentially very big) which we don't actually need |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
579 } | 603 } |
580 } | 604 } |
581 | 605 |
582 if ((fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag) || | 606 if ((fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag) || |
583 SK_ARRAY_COUNT(gPictureRecordOpts) == opt) { | 607 SK_ARRAY_COUNT(gPictureRecordOpts) == opt) { |
584 // No optimization fired so add the RESTORE | 608 // No optimization fired so add the RESTORE |
585 fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size ()); | 609 fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size ()); |
586 size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code | 610 size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code |
587 initialOffset = this->addDraw(RESTORE, &size); | 611 initialOffset = this->addDraw(RESTORE, &size); |
588 } | 612 } |
613 SkASSERT(kInvalidOffset != initialOffset); | |
589 | 614 |
590 fRestoreOffsetStack.pop(); | 615 fRestoreOffsetStack.pop(); |
591 | 616 |
592 validate(initialOffset, size); | 617 validate(initialOffset, size); |
593 return this->INHERITED::restore(); | 618 return this->INHERITED::restore(); |
594 } | 619 } |
595 | 620 |
621 uint32_t SkPictureRecord::addDraw(DrawType drawType, uint32_t* size, | |
622 const SkPaint* paint, const SkRect* localBound s) { | |
623 SkIRect devClipBounds; // Bounds of the current clip in device space | |
624 if (!this->getClipDeviceBounds(&devClipBounds) && !modifies_state(drawType)) { | |
625 // Optimize-out calls that are clipped-out. State modifying commands | |
626 // can not be optimized-out because they may have an impact on future ca lls | |
627 // if the clip is ever expanded. For example, with a union clip op. | |
628 return kInvalidOffset; | |
629 } | |
630 #if SK_RECORD_BOUNDS_IN_PICTURE | |
631 bool writeBounds = canRecordBounds(drawType); | |
632 SkIRect clippedDevBounds; // Bounds of the clipped draw in device space | |
Tom Hudson
2013/05/14 17:00:49
Nit: clippedDevBounds and devClipBounds are a bit
| |
633 if (writeBounds) { | |
634 SkASSERT(!modifies_state(drawType)); // Ensure devClipBounds is initial ized | |
Tom Hudson
2013/05/14 17:00:49
Not obvious how the comment follows from the asser
| |
635 if (NULL == localBounds || (NULL != paint && !paint->canComputeFastBound s())) { | |
636 clippedDevBounds = devClipBounds; | |
637 } else { | |
638 SkRect paintBounds; | |
639 SkRect rectifiedBounds = *localBounds; | |
640 rectifiedBounds.sort(); | |
641 if (NULL != paint) { | |
642 if (drawType == DRAW_POINTS) { | |
643 paintBounds = paint->computeFastStrokeBounds(rectifiedBounds , &paintBounds); | |
644 } else { | |
645 paintBounds = paint->computeFastBounds(rectifiedBounds, &pai ntBounds); | |
646 } | |
647 } else { | |
648 paintBounds = *localBounds; | |
649 } | |
650 if (paintBounds.isEmpty()) { | |
651 // Area affected by draw op is empty even after accounting | |
652 // for stroke width. | |
653 return kInvalidOffset; | |
654 } | |
655 SkRect devBounds; | |
656 this->getTotalMatrix().mapRect(&devBounds, paintBounds); | |
657 devBounds.roundOut(&clippedDevBounds); | |
658 if (!clippedDevBounds.intersect(devClipBounds)) { | |
659 // Draw lies outside of clip. The clip can only get further | |
660 // restricted at playback time, so it is safe to reject during | |
661 // record stage. | |
662 return kInvalidOffset; | |
663 } | |
664 } | |
665 *size += sizeof(SkIRect); | |
666 } | |
667 #else | |
668 sk_ignore_unused_variable(paint); | |
669 sk_ignore_unused_variable(localBounds); | |
670 #endif | |
671 | |
672 uint32_t offset = fWriter.size(); | |
673 | |
674 this->predrawNotify(); | |
675 | |
676 #ifdef SK_DEBUG_TRACE | |
677 SkDebugf("add %s\n", DrawTypeToString(drawType)); | |
678 #endif | |
679 SkASSERT(0 != *size); | |
680 SkASSERT(((uint8_t) drawType) == drawType); | |
681 if (0 != (*size & ~MASK_24) || *size == MASK_24) { | |
682 fWriter.writeInt(PACK_8_24(drawType, MASK_24)); | |
683 *size += 1; | |
684 fWriter.writeInt(*size); | |
685 } else { | |
686 fWriter.writeInt(PACK_8_24(drawType, *size)); | |
687 } | |
688 | |
689 #if SK_RECORD_BOUNDS_IN_PICTURE | |
690 if (writeBounds) { | |
691 fWriter.write(&clippedDevBounds, sizeof(clippedDevBounds)); | |
692 fLastDrawBounds = clippedDevBounds; | |
693 } else { | |
694 fLastDrawBounds = devClipBounds; | |
695 } | |
696 #endif | |
697 | |
698 return offset; | |
699 } | |
700 | |
596 bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) { | 701 bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) { |
597 // op + dx + dy | 702 // op + dx + dy |
598 uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); | 703 uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); |
599 uint32_t initialOffset = this->addDraw(TRANSLATE, &size); | 704 uint32_t initialOffset = this->addDraw(TRANSLATE, &size); |
705 SkASSERT(kInvalidOffset != initialOffset); | |
600 addScalar(dx); | 706 addScalar(dx); |
601 addScalar(dy); | 707 addScalar(dy); |
602 validate(initialOffset, size); | 708 validate(initialOffset, size); |
603 return this->INHERITED::translate(dx, dy); | 709 return this->INHERITED::translate(dx, dy); |
604 } | 710 } |
605 | 711 |
606 bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) { | 712 bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) { |
607 // op + sx + sy | 713 // op + sx + sy |
608 uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); | 714 uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); |
609 uint32_t initialOffset = this->addDraw(SCALE, &size); | 715 uint32_t initialOffset = this->addDraw(SCALE, &size); |
716 SkASSERT(kInvalidOffset != initialOffset); | |
610 addScalar(sx); | 717 addScalar(sx); |
611 addScalar(sy); | 718 addScalar(sy); |
612 validate(initialOffset, size); | 719 validate(initialOffset, size); |
613 return this->INHERITED::scale(sx, sy); | 720 return this->INHERITED::scale(sx, sy); |
614 } | 721 } |
615 | 722 |
616 bool SkPictureRecord::rotate(SkScalar degrees) { | 723 bool SkPictureRecord::rotate(SkScalar degrees) { |
617 // op + degrees | 724 // op + degrees |
618 uint32_t size = 1 * kUInt32Size + sizeof(SkScalar); | 725 uint32_t size = 1 * kUInt32Size + sizeof(SkScalar); |
619 uint32_t initialOffset = this->addDraw(ROTATE, &size); | 726 uint32_t initialOffset = this->addDraw(ROTATE, &size); |
727 SkASSERT(kInvalidOffset != initialOffset); | |
620 addScalar(degrees); | 728 addScalar(degrees); |
621 validate(initialOffset, size); | 729 validate(initialOffset, size); |
622 return this->INHERITED::rotate(degrees); | 730 return this->INHERITED::rotate(degrees); |
623 } | 731 } |
624 | 732 |
625 bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) { | 733 bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) { |
626 // op + sx + sy | 734 // op + sx + sy |
627 uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); | 735 uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar); |
628 uint32_t initialOffset = this->addDraw(SKEW, &size); | 736 uint32_t initialOffset = this->addDraw(SKEW, &size); |
737 SkASSERT(kInvalidOffset != initialOffset); | |
629 addScalar(sx); | 738 addScalar(sx); |
630 addScalar(sy); | 739 addScalar(sy); |
631 validate(initialOffset, size); | 740 validate(initialOffset, size); |
632 return this->INHERITED::skew(sx, sy); | 741 return this->INHERITED::skew(sx, sy); |
633 } | 742 } |
634 | 743 |
635 bool SkPictureRecord::concat(const SkMatrix& matrix) { | 744 bool SkPictureRecord::concat(const SkMatrix& matrix) { |
636 validate(fWriter.size(), 0); | 745 validate(fWriter.size(), 0); |
637 // op + matrix index | 746 // op + matrix index |
638 uint32_t size = 2 * kUInt32Size; | 747 uint32_t size = 2 * kUInt32Size; |
639 uint32_t initialOffset = this->addDraw(CONCAT, &size); | 748 uint32_t initialOffset = this->addDraw(CONCAT, &size); |
749 SkASSERT(kInvalidOffset != initialOffset); | |
640 addMatrix(matrix); | 750 addMatrix(matrix); |
641 validate(initialOffset, size); | 751 validate(initialOffset, size); |
642 return this->INHERITED::concat(matrix); | 752 return this->INHERITED::concat(matrix); |
643 } | 753 } |
644 | 754 |
645 void SkPictureRecord::setMatrix(const SkMatrix& matrix) { | 755 void SkPictureRecord::setMatrix(const SkMatrix& matrix) { |
646 validate(fWriter.size(), 0); | 756 validate(fWriter.size(), 0); |
647 // op + matrix index | 757 // op + matrix index |
648 uint32_t size = 2 * kUInt32Size; | 758 uint32_t size = 2 * kUInt32Size; |
649 uint32_t initialOffset = this->addDraw(SET_MATRIX, &size); | 759 uint32_t initialOffset = this->addDraw(SET_MATRIX, &size); |
760 SkASSERT(kInvalidOffset != initialOffset); | |
650 addMatrix(matrix); | 761 addMatrix(matrix); |
651 validate(initialOffset, size); | 762 validate(initialOffset, size); |
652 this->INHERITED::setMatrix(matrix); | 763 this->INHERITED::setMatrix(matrix); |
653 } | 764 } |
654 | 765 |
655 static bool regionOpExpands(SkRegion::Op op) { | 766 static bool regionOpExpands(SkRegion::Op op) { |
656 switch (op) { | 767 switch (op) { |
657 case SkRegion::kUnion_Op: | 768 case SkRegion::kUnion_Op: |
658 case SkRegion::kXOR_Op: | 769 case SkRegion::kXOR_Op: |
659 case SkRegion::kReverseDifference_Op: | 770 case SkRegion::kReverseDifference_Op: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
721 | 832 |
722 bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | 833 bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { |
723 // id + rect + clip params | 834 // id + rect + clip params |
724 uint32_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size; | 835 uint32_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size; |
725 // recordRestoreOffsetPlaceholder doesn't always write an offset | 836 // recordRestoreOffsetPlaceholder doesn't always write an offset |
726 if (!fRestoreOffsetStack.isEmpty()) { | 837 if (!fRestoreOffsetStack.isEmpty()) { |
727 // + restore offset | 838 // + restore offset |
728 size += kUInt32Size; | 839 size += kUInt32Size; |
729 } | 840 } |
730 uint32_t initialOffset = this->addDraw(CLIP_RECT, &size); | 841 uint32_t initialOffset = this->addDraw(CLIP_RECT, &size); |
842 SkASSERT(kInvalidOffset != initialOffset); | |
731 addRect(rect); | 843 addRect(rect); |
732 addInt(ClipParams_pack(op, doAA)); | 844 addInt(ClipParams_pack(op, doAA)); |
733 recordRestoreOffsetPlaceholder(op); | 845 recordRestoreOffsetPlaceholder(op); |
734 | 846 |
735 validate(initialOffset, size); | 847 validate(initialOffset, size); |
736 return this->INHERITED::clipRect(rect, op, doAA); | 848 return this->INHERITED::clipRect(rect, op, doAA); |
737 } | 849 } |
738 | 850 |
739 bool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA ) { | 851 bool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA ) { |
740 if (rrect.isRect()) { | 852 if (rrect.isRect()) { |
741 return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA); | 853 return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA); |
742 } | 854 } |
743 | 855 |
744 // op + rrect + clip params | 856 // op + rrect + clip params |
745 uint32_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size; | 857 uint32_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size; |
746 // recordRestoreOffsetPlaceholder doesn't always write an offset | 858 // recordRestoreOffsetPlaceholder doesn't always write an offset |
747 if (!fRestoreOffsetStack.isEmpty()) { | 859 if (!fRestoreOffsetStack.isEmpty()) { |
748 // + restore offset | 860 // + restore offset |
749 size += kUInt32Size; | 861 size += kUInt32Size; |
750 } | 862 } |
751 uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size); | 863 uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size); |
864 SkASSERT(kInvalidOffset != initialOffset); | |
752 addRRect(rrect); | 865 addRRect(rrect); |
753 addInt(ClipParams_pack(op, doAA)); | 866 addInt(ClipParams_pack(op, doAA)); |
754 recordRestoreOffsetPlaceholder(op); | 867 recordRestoreOffsetPlaceholder(op); |
755 | 868 |
756 validate(initialOffset, size); | 869 validate(initialOffset, size); |
757 | 870 |
758 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { | 871 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { |
759 return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, doAA, false); | 872 return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, doAA, false); |
760 } else { | 873 } else { |
761 return this->INHERITED::clipRRect(rrect, op, doAA); | 874 return this->INHERITED::clipRRect(rrect, op, doAA); |
762 } | 875 } |
763 } | 876 } |
764 | 877 |
765 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 878 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
766 | 879 |
767 SkRect r; | 880 SkRect r; |
768 if (!path.isInverseFillType() && path.isRect(&r)) { | 881 if (!path.isInverseFillType() && path.isRect(&r)) { |
769 return this->clipRect(r, op, doAA); | 882 return this->clipRect(r, op, doAA); |
770 } | 883 } |
771 | 884 |
772 // op + path index + clip params | 885 // op + path index + clip params |
773 uint32_t size = 3 * kUInt32Size; | 886 uint32_t size = 3 * kUInt32Size; |
774 // recordRestoreOffsetPlaceholder doesn't always write an offset | 887 // recordRestoreOffsetPlaceholder doesn't always write an offset |
775 if (!fRestoreOffsetStack.isEmpty()) { | 888 if (!fRestoreOffsetStack.isEmpty()) { |
776 // + restore offset | 889 // + restore offset |
777 size += kUInt32Size; | 890 size += kUInt32Size; |
778 } | 891 } |
779 uint32_t initialOffset = this->addDraw(CLIP_PATH, &size); | 892 uint32_t initialOffset = this->addDraw(CLIP_PATH, &size); |
893 SkASSERT(kInvalidOffset != initialOffset); | |
780 addPath(path); | 894 addPath(path); |
781 addInt(ClipParams_pack(op, doAA)); | 895 addInt(ClipParams_pack(op, doAA)); |
782 recordRestoreOffsetPlaceholder(op); | 896 recordRestoreOffsetPlaceholder(op); |
783 | 897 |
784 validate(initialOffset, size); | 898 validate(initialOffset, size); |
785 | 899 |
786 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { | 900 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { |
787 return this->updateClipConservativelyUsingBounds(path.getBounds(), op, d oAA, | 901 return this->updateClipConservativelyUsingBounds(path.getBounds(), op, d oAA, |
788 path.isInverseFillType( )); | 902 path.isInverseFillType( )); |
789 } else { | 903 } else { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
863 | 977 |
864 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { | 978 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { |
865 // op + region index + clip params | 979 // op + region index + clip params |
866 uint32_t size = 3 * kUInt32Size; | 980 uint32_t size = 3 * kUInt32Size; |
867 // recordRestoreOffsetPlaceholder doesn't always write an offset | 981 // recordRestoreOffsetPlaceholder doesn't always write an offset |
868 if (!fRestoreOffsetStack.isEmpty()) { | 982 if (!fRestoreOffsetStack.isEmpty()) { |
869 // + restore offset | 983 // + restore offset |
870 size += kUInt32Size; | 984 size += kUInt32Size; |
871 } | 985 } |
872 uint32_t initialOffset = this->addDraw(CLIP_REGION, &size); | 986 uint32_t initialOffset = this->addDraw(CLIP_REGION, &size); |
987 SkASSERT(kInvalidOffset != initialOffset); | |
873 addRegion(region); | 988 addRegion(region); |
874 addInt(ClipParams_pack(op, false)); | 989 addInt(ClipParams_pack(op, false)); |
875 recordRestoreOffsetPlaceholder(op); | 990 recordRestoreOffsetPlaceholder(op); |
876 | 991 |
877 validate(initialOffset, size); | 992 validate(initialOffset, size); |
878 return this->INHERITED::clipRegion(region, op); | 993 return this->INHERITED::clipRegion(region, op); |
879 } | 994 } |
880 | 995 |
881 void SkPictureRecord::clear(SkColor color) { | 996 void SkPictureRecord::clear(SkColor color) { |
882 // op + color | 997 // op + color |
883 uint32_t size = 2 * kUInt32Size; | 998 uint32_t size = 2 * kUInt32Size; |
884 uint32_t initialOffset = this->addDraw(DRAW_CLEAR, &size); | 999 uint32_t initialOffset = this->addDraw(DRAW_CLEAR, &size); |
1000 if (kInvalidOffset == initialOffset) { | |
Tom Hudson
2013/05/14 17:00:49
Why not asserts here as above?
| |
1001 return; | |
1002 } | |
885 addInt(color); | 1003 addInt(color); |
886 validate(initialOffset, size); | 1004 validate(initialOffset, size); |
887 } | 1005 } |
888 | 1006 |
889 void SkPictureRecord::drawPaint(const SkPaint& paint) { | 1007 void SkPictureRecord::drawPaint(const SkPaint& paint) { |
890 // op + paint index | 1008 // op + paint index |
891 uint32_t size = 2 * kUInt32Size; | 1009 uint32_t size = 2 * kUInt32Size; |
892 uint32_t initialOffset = this->addDraw(DRAW_PAINT, &size); | 1010 uint32_t initialOffset = this->addDraw(DRAW_PAINT, &size); |
893 SkASSERT(initialOffset+getPaintOffset(DRAW_PAINT, size) == fWriter.size()); | 1011 if (kInvalidOffset == initialOffset) { |
1012 return; | |
1013 } | |
1014 SkASSERT(initialOffset + getPaintOffset(DRAW_PAINT, size) == fWriter.size()) ; | |
894 addPaint(paint); | 1015 addPaint(paint); |
895 validate(initialOffset, size); | 1016 validate(initialOffset, size); |
896 } | 1017 } |
897 | 1018 |
898 void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts [], | 1019 void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts [], |
899 const SkPaint& paint) { | 1020 const SkPaint& paint) { |
900 // op + paint index + mode + count + point data | 1021 // op + paint index + mode + count + point data |
901 uint32_t size = 4 * kUInt32Size + count * sizeof(SkPoint); | 1022 uint32_t size = 4 * kUInt32Size + count * sizeof(SkPoint); |
1023 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1024 SkRect bbox; | |
1025 bbox.set(pts, count); | |
1026 uint32_t initialOffset = this->addDraw(DRAW_POINTS, &size, &paint, &bbox); | |
1027 #else | |
902 uint32_t initialOffset = this->addDraw(DRAW_POINTS, &size); | 1028 uint32_t initialOffset = this->addDraw(DRAW_POINTS, &size); |
903 SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.size()); | 1029 #endif |
1030 if (kInvalidOffset == initialOffset) { | |
1031 return; | |
1032 } | |
1033 SkASSERT(initialOffset + getPaintOffset(DRAW_POINTS, size) == fWriter.size() ); | |
904 addPaint(paint); | 1034 addPaint(paint); |
905 addInt(mode); | 1035 addInt(mode); |
906 addInt(count); | 1036 addInt(count); |
907 fWriter.writeMul4(pts, count * sizeof(SkPoint)); | 1037 fWriter.writeMul4(pts, count * sizeof(SkPoint)); |
908 validate(initialOffset, size); | 1038 validate(initialOffset, size); |
909 } | 1039 } |
910 | 1040 |
911 void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) { | 1041 void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) { |
912 // op + paint index + rect | 1042 // op + paint index + rect |
913 uint32_t size = 2 * kUInt32Size + sizeof(oval); | 1043 uint32_t size = 2 * kUInt32Size + sizeof(oval); |
1044 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1045 uint32_t initialOffset = this->addDraw(DRAW_OVAL, &size, &paint, &oval); | |
1046 #else | |
914 uint32_t initialOffset = this->addDraw(DRAW_OVAL, &size); | 1047 uint32_t initialOffset = this->addDraw(DRAW_OVAL, &size); |
915 SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.size()); | 1048 #endif |
1049 if (kInvalidOffset == initialOffset) { | |
1050 return; | |
1051 } | |
1052 SkASSERT(initialOffset + getPaintOffset(DRAW_OVAL, size) == fWriter.size()); | |
916 addPaint(paint); | 1053 addPaint(paint); |
917 addRect(oval); | 1054 addRect(oval); |
918 validate(initialOffset, size); | 1055 validate(initialOffset, size); |
919 } | 1056 } |
920 | 1057 |
921 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) { | 1058 void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) { |
922 // op + paint index + rect | 1059 // op + paint index + rect |
923 uint32_t size = 2 * kUInt32Size + sizeof(rect); | 1060 uint32_t size = 2 * kUInt32Size + sizeof(rect); |
1061 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1062 uint32_t initialOffset = this->addDraw(DRAW_RECT, &size, &paint, &rect); | |
1063 #else | |
924 uint32_t initialOffset = this->addDraw(DRAW_RECT, &size); | 1064 uint32_t initialOffset = this->addDraw(DRAW_RECT, &size); |
925 SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.size()); | 1065 #endif |
1066 if (kInvalidOffset == initialOffset) { | |
1067 return; | |
1068 } | |
1069 SkASSERT(initialOffset + getPaintOffset(DRAW_RECT, size) == fWriter.size()); | |
926 addPaint(paint); | 1070 addPaint(paint); |
927 addRect(rect); | 1071 addRect(rect); |
928 validate(initialOffset, size); | 1072 validate(initialOffset, size); |
929 } | 1073 } |
930 | 1074 |
931 void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) { | 1075 void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) { |
932 if (rrect.isRect()) { | 1076 if (rrect.isRect()) { |
933 this->SkPictureRecord::drawRect(rrect.getBounds(), paint); | 1077 this->SkPictureRecord::drawRect(rrect.getBounds(), paint); |
934 } else if (rrect.isOval()) { | 1078 } else if (rrect.isOval()) { |
935 this->SkPictureRecord::drawOval(rrect.getBounds(), paint); | 1079 this->SkPictureRecord::drawOval(rrect.getBounds(), paint); |
936 } else { | 1080 } else { |
937 // op + paint index + rrect | 1081 // op + paint index + rrect |
938 uint32_t initialOffset, size; | 1082 uint32_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory; |
939 size = 2 * kUInt32Size + SkRRect::kSizeInMemory; | 1083 #if SK_RECORD_BOUNDS_IN_PICTURE |
940 initialOffset = this->addDraw(DRAW_RRECT, &size); | 1084 uint32_t initialOffset = this->addDraw(DRAW_RRECT, &size, &paint, &rrect .getBounds()); |
941 SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.size( )); | 1085 #else |
1086 uint32_t initialOffset = this->addDraw(DRAW_RRECT, &size); | |
1087 #endif | |
1088 if (kInvalidOffset == initialOffset) { | |
1089 return; | |
1090 } | |
1091 SkASSERT(initialOffset + getPaintOffset(DRAW_RRECT, size) == fWriter.siz e()); | |
942 addPaint(paint); | 1092 addPaint(paint); |
943 addRRect(rrect); | 1093 addRRect(rrect); |
944 validate(initialOffset, size); | 1094 validate(initialOffset, size); |
945 } | 1095 } |
946 } | 1096 } |
947 | 1097 |
948 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) { | 1098 void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) { |
949 // op + paint index + path index | 1099 // op + paint index + path index |
950 uint32_t size = 3 * kUInt32Size; | 1100 uint32_t size = 3 * kUInt32Size; |
1101 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1102 const SkRect* bounds = path.isInverseFillType() ? NULL : &path.getBounds(); | |
1103 uint32_t initialOffset = this->addDraw(DRAW_PATH, &size, &paint, bounds); | |
1104 #else | |
951 uint32_t initialOffset = this->addDraw(DRAW_PATH, &size); | 1105 uint32_t initialOffset = this->addDraw(DRAW_PATH, &size); |
952 SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.size()); | 1106 #endif |
1107 if (kInvalidOffset == initialOffset) { | |
1108 return; | |
1109 } | |
1110 SkASSERT(initialOffset + getPaintOffset(DRAW_PATH, size) == fWriter.size()); | |
953 addPaint(paint); | 1111 addPaint(paint); |
954 addPath(path); | 1112 addPath(path); |
955 validate(initialOffset, size); | 1113 validate(initialOffset, size); |
956 } | 1114 } |
957 | 1115 |
958 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, | 1116 void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, |
959 const SkPaint* paint = NULL) { | 1117 const SkPaint* paint = NULL) { |
960 // op + paint index + bitmap index + left + top | 1118 // op + paint index + bitmap index + left + top |
961 uint32_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); | 1119 uint32_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar); |
1120 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1121 SkRect bounds = SkRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()) ; | |
1122 uint32_t initialOffset = this->addDraw(DRAW_BITMAP, &size, paint, &bounds); | |
1123 #else | |
962 uint32_t initialOffset = this->addDraw(DRAW_BITMAP, &size); | 1124 uint32_t initialOffset = this->addDraw(DRAW_BITMAP, &size); |
963 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.size()); | 1125 #endif |
1126 if (kInvalidOffset == initialOffset) { | |
1127 return; | |
1128 } | |
1129 SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP, size) == fWriter.size() ); | |
964 addPaintPtr(paint); | 1130 addPaintPtr(paint); |
965 addBitmap(bitmap); | 1131 addBitmap(bitmap); |
966 addScalar(left); | 1132 addScalar(left); |
967 addScalar(top); | 1133 addScalar(top); |
968 validate(initialOffset, size); | 1134 validate(initialOffset, size); |
969 } | 1135 } |
970 | 1136 |
971 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, | 1137 void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, |
972 const SkRect& dst, const SkPaint* paint) { | 1138 const SkRect& dst, const SkPaint* paint) { |
973 // id + paint index + bitmap index + bool for 'src' | 1139 // id + paint index + bitmap index + bool for 'src' |
974 uint32_t size = 4 * kUInt32Size; | 1140 uint32_t size = 4 * kUInt32Size; |
975 if (NULL != src) { | 1141 if (NULL != src) { |
976 size += sizeof(*src); // + rect | 1142 size += sizeof(*src); // + rect |
977 } | 1143 } |
978 size += sizeof(dst); // + rect | 1144 size += sizeof(dst); // + rect |
979 | 1145 |
1146 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1147 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size, pain t, &dst); | |
1148 #else | |
980 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size); | 1149 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size); |
981 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size) == fWr iter.size()); | 1150 #endif |
1151 if (kInvalidOffset == initialOffset) { | |
1152 return; | |
1153 } | |
1154 SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size) == f Writer.size()); | |
982 addPaintPtr(paint); | 1155 addPaintPtr(paint); |
983 addBitmap(bitmap); | 1156 addBitmap(bitmap); |
984 addRectPtr(src); // may be null | 1157 addRectPtr(src); // may be null |
985 addRect(dst); | 1158 addRect(dst); |
986 validate(initialOffset, size); | 1159 validate(initialOffset, size); |
987 } | 1160 } |
988 | 1161 |
989 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m atrix, | 1162 void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m atrix, |
990 const SkPaint* paint) { | 1163 const SkPaint* paint) { |
991 // id + paint index + bitmap index + matrix index | 1164 // id + paint index + bitmap index + matrix index |
992 uint32_t size = 4 * kUInt32Size; | 1165 uint32_t size = 4 * kUInt32Size; |
1166 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1167 SkRect bounds = SkRect::MakeWH(bitmap.width(), bitmap.height()); | |
1168 matrix.mapRect(&bounds); | |
1169 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size, paint, &bo unds); | |
1170 #else | |
993 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size); | 1171 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size); |
994 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.s ize()); | 1172 #endif |
1173 if (kInvalidOffset == initialOffset) { | |
1174 return; | |
1175 } | |
1176 SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter .size()); | |
995 addPaintPtr(paint); | 1177 addPaintPtr(paint); |
996 addBitmap(bitmap); | 1178 addBitmap(bitmap); |
997 addMatrix(matrix); | 1179 addMatrix(matrix); |
998 validate(initialOffset, size); | 1180 validate(initialOffset, size); |
999 } | 1181 } |
1000 | 1182 |
1001 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& cent er, | 1183 void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& cent er, |
1002 const SkRect& dst, const SkPaint* paint) { | 1184 const SkRect& dst, const SkPaint* paint) { |
1003 // op + paint index + bitmap id + center + dst rect | 1185 // op + paint index + bitmap id + center + dst rect |
1004 uint32_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst); | 1186 uint32_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst); |
1187 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1188 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size, paint, &dst) ; | |
1189 #else | |
1005 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size); | 1190 uint32_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size); |
1006 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.siz e()); | 1191 #endif |
1192 if (kInvalidOffset == initialOffset) { | |
1193 return; | |
1194 } | |
1195 SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.s ize()); | |
1007 addPaintPtr(paint); | 1196 addPaintPtr(paint); |
1008 addBitmap(bitmap); | 1197 addBitmap(bitmap); |
1009 addIRect(center); | 1198 addIRect(center); |
1010 addRect(dst); | 1199 addRect(dst); |
1011 validate(initialOffset, size); | 1200 validate(initialOffset, size); |
1012 } | 1201 } |
1013 | 1202 |
1014 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top, | 1203 void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top, |
1015 const SkPaint* paint = NULL) { | 1204 const SkPaint* paint) { |
1016 // op + paint index + bitmap index + left + top | 1205 // op + paint index + bitmap index + left + top |
1017 uint32_t size = 5 * kUInt32Size; | 1206 uint32_t size = 5 * kUInt32Size; |
1207 // Note: Bounds encoding not supported on drawSprite. Because drawSprite | |
1208 // ignores the current transform matrix, the bounds will not follow the | |
1209 // playback canvas's initial tranform matrix at playback time, and | |
1210 // recorded bounds are assumed to be in the playback canvas' initial | |
1211 // local frame of reference. | |
1018 uint32_t initialOffset = this->addDraw(DRAW_SPRITE, &size); | 1212 uint32_t initialOffset = this->addDraw(DRAW_SPRITE, &size); |
1019 SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.size()); | 1213 if (kInvalidOffset == initialOffset) { |
1214 return; | |
1215 } | |
1216 SkASSERT(initialOffset + getPaintOffset(DRAW_SPRITE, size) == fWriter.size() ); | |
1020 addPaintPtr(paint); | 1217 addPaintPtr(paint); |
1021 addBitmap(bitmap); | 1218 addBitmap(bitmap); |
1022 addInt(left); | 1219 addInt(left); |
1023 addInt(top); | 1220 addInt(top); |
1024 validate(initialOffset, size); | 1221 validate(initialOffset, size); |
1025 } | 1222 } |
1026 | 1223 |
1224 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1027 // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been | 1225 // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been |
1028 // tweaked by paint.computeFastBounds(). | 1226 // tweaked by paint.computeFastBounds(). |
1029 // | 1227 // |
1030 static void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2] ) { | 1228 static void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2] ) { |
1031 SkPaint::FontMetrics metrics; | 1229 SkPaint::FontMetrics metrics; |
1032 paint.getFontMetrics(&metrics); | 1230 paint.getFontMetrics(&metrics); |
1033 SkRect bounds; | 1231 SkRect bounds; |
1034 // construct a rect so we can see any adjustments from the paint. | 1232 // construct a rect so we can see any adjustments from the paint. |
1035 // we use 0,1 for left,right, just so the rect isn't empty | 1233 // we use 0,1 for left,right, just so the rect isn't empty |
1036 bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom); | 1234 bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom); |
1037 (void)paint.computeFastBounds(bounds, &bounds); | 1235 (void)paint.computeFastBounds(bounds, &bounds); |
1038 topbot[0] = bounds.fTop; | 1236 topbot[0] = bounds.fTop; |
1039 topbot[1] = bounds.fBottom; | 1237 topbot[1] = bounds.fBottom; |
1040 } | 1238 } |
1041 | 1239 |
1042 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlat Data& flat, | 1240 void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlat Data& flat, |
1043 SkScalar minY, SkScalar maxY) { | 1241 SkScalar minY, SkScalar maxY) { |
1044 if (!flat.isTopBotWritten()) { | 1242 if (!flat.isTopBotWritten()) { |
1045 computeFontMetricsTopBottom(paint, flat.writableTopBot()); | 1243 computeFontMetricsTopBottom(paint, flat.writableTopBot()); |
1046 SkASSERT(flat.isTopBotWritten()); | 1244 SkASSERT(flat.isTopBotWritten()); |
1047 } | 1245 } |
1048 addScalar(flat.topBot()[0] + minY); | 1246 addScalar(flat.topBot()[0] + minY); |
1049 addScalar(flat.topBot()[1] + maxY); | 1247 addScalar(flat.topBot()[1] + maxY); |
1050 } | 1248 } |
1249 #endif | |
1250 | |
1251 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1252 static void pad_text_bbox_horizontally(const SkPaint::FontMetrics& metrics, SkRe ct* bbox) { | |
1253 // Pad horizontal bounds on each side by max vertical extents. | |
1254 // This is sort of arbitrary, but seems to produce reasonable results. | |
1255 // If there were a way of getting max glyph X-extents to pad by, that | |
1256 // may be better here, but FontMetrics fXMin and fXMax seem incorrect | |
1257 // on most platforms (too small in Linux, never even set in Windows). | |
1258 SkScalar pad = (metrics.fBottom - metrics.fTop); | |
1259 SkASSERT(pad > 0); | |
1260 bbox->fLeft -= pad; | |
1261 bbox->fRight += pad; | |
1262 } | |
1263 #endif | |
1051 | 1264 |
1052 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x, | 1265 void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x, |
1053 SkScalar y, const SkPaint& paint) { | 1266 SkScalar y, const SkPaint& paint) { |
1054 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); | 1267 // Note: The DRAW_TEXT_TOP_BOTTOM optimization is redundant if we are |
1268 // already recording full bounds. | |
1055 | 1269 |
1056 // op + paint index + length + 'length' worth of chars + x + y | 1270 // op + paint index + length + 'length' worth of chars + x + y |
1057 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar ); | 1271 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar ); |
1272 | |
1273 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1274 SkRect bbox; | |
1275 paint.measureText(text, byteLength, &bbox); | |
1276 SkPaint::FontMetrics metrics; | |
1277 paint.getFontMetrics(&metrics); | |
1278 | |
1279 // Vertical and aligned text need to be offset | |
1280 if (paint.isVerticalText()) { | |
1281 SkScalar h = bbox.fBottom - bbox.fTop; | |
1282 if (paint.getTextAlign() == SkPaint::kCenter_Align) { | |
1283 bbox.fTop -= h / 2; | |
1284 bbox.fBottom -= h / 2; | |
1285 } | |
1286 // Pad top and bottom with max extents from FontMetrics | |
1287 bbox.fBottom += metrics.fBottom; | |
1288 bbox.fTop += metrics.fTop; | |
1289 } else { | |
1290 SkScalar w = bbox.fRight - bbox.fLeft; | |
1291 if (paint.getTextAlign() == SkPaint::kCenter_Align) { | |
1292 bbox.fLeft -= w / 2; | |
1293 bbox.fRight -= w / 2; | |
1294 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { | |
1295 bbox.fLeft -= w; | |
1296 bbox.fRight -= w; | |
1297 } | |
1298 // Set vertical bounds to max extents from font metrics | |
1299 bbox.fTop = metrics.fTop; | |
1300 bbox.fBottom = metrics.fBottom; | |
1301 } | |
1302 pad_text_bbox_horizontally(metrics, &bbox); | |
1303 bbox.fLeft += x; | |
1304 bbox.fRight += x; | |
1305 bbox.fTop += y; | |
1306 bbox.fBottom += y; | |
1307 uint32_t initialOffset = this->addDraw(DRAW_TEXT, &size, &paint, &bbox); | |
1308 #else | |
1309 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); | |
1310 | |
1058 if (fast) { | 1311 if (fast) { |
1059 size += 2 * sizeof(SkScalar); // + top & bottom | 1312 size += 2 * sizeof(SkScalar); // + top & bottom |
1060 } | 1313 } |
1061 | |
1062 DrawType op = fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT; | 1314 DrawType op = fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT; |
1063 uint32_t initialOffset = this->addDraw(op, &size); | 1315 uint32_t initialOffset = this->addDraw(op, &size); |
1064 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.size()); | 1316 #endif |
1317 if (kInvalidOffset == initialOffset) { | |
1318 return; | |
1319 } | |
1320 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1321 SkASSERT(initialOffset + getPaintOffset(DRAW_TEXT, size) == fWriter.size()); | |
1322 #else | |
1323 SkASSERT(initialOffset + getPaintOffset(op, size) == fWriter.size()); | |
1324 #endif | |
1065 const SkFlatData* flatPaintData = addPaint(paint); | 1325 const SkFlatData* flatPaintData = addPaint(paint); |
1066 SkASSERT(flatPaintData); | |
1067 addText(text, byteLength); | 1326 addText(text, byteLength); |
1068 addScalar(x); | 1327 addScalar(x); |
1069 addScalar(y); | 1328 addScalar(y); |
1329 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1330 // We still need to call addPaint even if we don't use flatPaintData | |
1331 sk_ignore_unused_variable(flatPaintData); | |
1332 #else | |
1333 SkASSERT(flatPaintData); | |
1070 if (fast) { | 1334 if (fast) { |
1071 addFontMetricsTopBottom(paint, *flatPaintData, y, y); | 1335 addFontMetricsTopBottom(paint, *flatPaintData, y, y); |
1072 } | 1336 } |
1337 #endif | |
1073 validate(initialOffset, size); | 1338 validate(initialOffset, size); |
1074 } | 1339 } |
1075 | 1340 |
1076 void SkPictureRecord::drawPosText(const void* text, size_t byteLength, | 1341 void SkPictureRecord::drawPosText(const void* text, size_t byteLength, |
1077 const SkPoint pos[], const SkPaint& paint) { | 1342 const SkPoint pos[], const SkPaint& paint) { |
1078 size_t points = paint.countText(text, byteLength); | 1343 size_t points = paint.countText(text, byteLength); |
1079 if (0 == points) | 1344 if (0 == points) |
1080 return; | 1345 return; |
1081 | 1346 |
1082 bool canUseDrawH = true; | 1347 bool canUseDrawH = true; |
1083 SkScalar minY = pos[0].fY; | 1348 SkScalar minY = pos[0].fY; |
1084 SkScalar maxY = pos[0].fY; | 1349 SkScalar maxY = pos[0].fY; |
1085 // check if the caller really should have used drawPosTextH() | 1350 // check if the caller really should have used drawPosTextH() |
1086 { | 1351 { |
1087 const SkScalar firstY = pos[0].fY; | 1352 const SkScalar firstY = pos[0].fY; |
1088 for (size_t index = 1; index < points; index++) { | 1353 for (size_t index = 1; index < points; index++) { |
1089 if (pos[index].fY != firstY) { | 1354 if (pos[index].fY != firstY) { |
1090 canUseDrawH = false; | 1355 canUseDrawH = false; |
1091 if (pos[index].fY < minY) { | 1356 if (pos[index].fY < minY) { |
1092 minY = pos[index].fY; | 1357 minY = pos[index].fY; |
1093 } else if (pos[index].fY > maxY) { | 1358 } else if (pos[index].fY > maxY) { |
1094 maxY = pos[index].fY; | 1359 maxY = pos[index].fY; |
1095 } | 1360 } |
1096 } | 1361 } |
1097 } | 1362 } |
1098 } | 1363 } |
1099 | 1364 |
1365 // Note: The DRAW_TEXT_[H_]TOP_BOTTOM optimization is redundant if we are | |
1366 // already recording full bounds. | |
1367 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1100 bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds(); | 1368 bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds(); |
1101 bool fast = canUseDrawH && fastBounds; | 1369 bool fast = canUseDrawH && fastBounds; |
1370 #endif | |
1102 | 1371 |
1103 // op + paint index + length + 'length' worth of data + num points | 1372 // op + paint index + length + 'length' worth of data + num points |
1104 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size; | 1373 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size; |
1105 if (canUseDrawH) { | 1374 if (canUseDrawH) { |
1375 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1106 if (fast) { | 1376 if (fast) { |
1107 size += 2 * sizeof(SkScalar); // + top & bottom | 1377 size += 2 * sizeof(SkScalar); // + top & bottom |
1108 } | 1378 } |
1379 #endif | |
1109 // + y-pos + actual x-point data | 1380 // + y-pos + actual x-point data |
1110 size += sizeof(SkScalar) + points * sizeof(SkScalar); | 1381 size += sizeof(SkScalar) + points * sizeof(SkScalar); |
1111 } else { | 1382 } else { |
1112 // + x&y point data | 1383 // + x&y point data |
1113 size += points * sizeof(SkPoint); | 1384 size += points * sizeof(SkPoint); |
1385 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1114 if (fastBounds) { | 1386 if (fastBounds) { |
1115 size += 2 * sizeof(SkScalar); // + top & bottom | 1387 size += 2 * sizeof(SkScalar); // + top & bottom |
1116 } | 1388 } |
1389 #endif | |
1117 } | 1390 } |
1118 | 1391 |
1119 DrawType op; | 1392 DrawType op; |
1393 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1120 if (fast) { | 1394 if (fast) { |
1121 op = DRAW_POS_TEXT_H_TOP_BOTTOM; | 1395 op = DRAW_POS_TEXT_H_TOP_BOTTOM; |
1122 } else if (canUseDrawH) { | 1396 } else |
1397 #endif | |
1398 if (canUseDrawH) { | |
1123 op = DRAW_POS_TEXT_H; | 1399 op = DRAW_POS_TEXT_H; |
1400 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1124 } else if (fastBounds) { | 1401 } else if (fastBounds) { |
1125 op = DRAW_POS_TEXT_TOP_BOTTOM; | 1402 op = DRAW_POS_TEXT_TOP_BOTTOM; |
1403 #endif | |
1126 } else { | 1404 } else { |
1127 op = DRAW_POS_TEXT; | 1405 op = DRAW_POS_TEXT; |
1128 } | 1406 } |
1407 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1408 SkRect bbox; | |
1409 bbox.set(pos, paint.countText(text, byteLength)); | |
1410 SkPaint::FontMetrics metrics; | |
1411 paint.getFontMetrics(&metrics); | |
1412 bbox.fTop += metrics.fTop; | |
1413 bbox.fBottom += metrics.fBottom; | |
1414 | |
1415 // pad on left and right by half of max vertical glyph extents | |
1416 pad_text_bbox_horizontally(metrics, &bbox); | |
1417 uint32_t initialOffset = this->addDraw(op, &size, &paint, &bbox); | |
1418 #else | |
1129 uint32_t initialOffset = this->addDraw(op, &size); | 1419 uint32_t initialOffset = this->addDraw(op, &size); |
1130 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.size()); | 1420 #endif |
1421 if (kInvalidOffset == initialOffset) { | |
1422 return; | |
1423 } | |
1424 SkASSERT(initialOffset + getPaintOffset(op, size) == fWriter.size()); | |
1131 const SkFlatData* flatPaintData = addPaint(paint); | 1425 const SkFlatData* flatPaintData = addPaint(paint); |
1132 SkASSERT(flatPaintData); | 1426 SkASSERT(flatPaintData); |
1133 addText(text, byteLength); | 1427 addText(text, byteLength); |
1134 addInt(points); | 1428 addInt(points); |
1135 | 1429 |
1136 #ifdef SK_DEBUG_SIZE | 1430 #ifdef SK_DEBUG_SIZE |
1137 size_t start = fWriter.size(); | 1431 size_t start = fWriter.size(); |
1138 #endif | 1432 #endif |
1139 if (canUseDrawH) { | 1433 if (canUseDrawH) { |
1434 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1435 // We still need to call addPaint even if we don't use flatPaintData | |
1436 sk_ignore_unused_variable(flatPaintData); | |
1437 #else | |
1140 if (fast) { | 1438 if (fast) { |
1141 addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY) ; | 1439 addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY) ; |
1142 } | 1440 } |
1441 #endif | |
1143 addScalar(pos[0].fY); | 1442 addScalar(pos[0].fY); |
1144 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar)); | 1443 SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar)); |
1145 for (size_t index = 0; index < points; index++) | 1444 for (size_t index = 0; index < points; index++) |
1146 *xptr++ = pos[index].fX; | 1445 *xptr++ = pos[index].fX; |
1147 } else { | 1446 } else { |
1148 fWriter.writeMul4(pos, points * sizeof(SkPoint)); | 1447 fWriter.writeMul4(pos, points * sizeof(SkPoint)); |
1448 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1449 // We still need to call addPaint even if we don't use flatPaintData | |
1450 sk_ignore_unused_variable(flatPaintData); | |
1451 #else | |
1149 if (fastBounds) { | 1452 if (fastBounds) { |
1150 addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY); | 1453 addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY); |
1151 } | 1454 } |
1455 #endif | |
1152 } | 1456 } |
1153 #ifdef SK_DEBUG_SIZE | 1457 #ifdef SK_DEBUG_SIZE |
1154 fPointBytes += fWriter.size() - start; | 1458 fPointBytes += fWriter.size() - start; |
1155 fPointWrites += points; | 1459 fPointWrites += points; |
1156 #endif | 1460 #endif |
1157 validate(initialOffset, size); | 1461 validate(initialOffset, size); |
1158 } | 1462 } |
1159 | 1463 |
1160 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, | 1464 void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, |
1161 const SkScalar xpos[], SkScalar constY, | 1465 const SkScalar xpos[], SkScalar constY, |
1162 const SkPaint& paint) { | 1466 const SkPaint& paint) { |
1163 size_t points = paint.countText(text, byteLength); | 1467 size_t numChars = paint.countText(text, byteLength); |
1164 if (0 == points) | 1468 if (0 == numChars) |
1165 return; | 1469 return; |
1166 | 1470 |
1167 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); | |
1168 | |
1169 // op + paint index + length + 'length' worth of data + num points | 1471 // op + paint index + length + 'length' worth of data + num points |
1170 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size; | 1472 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size; |
1473 | |
1474 // Note: The DRAW_POS_TEXT_H_TOP_BOTTOM optimization is redundant if we are | |
1475 // already recording full bounds. | |
1476 #if !(SK_RECORD_BOUNDS_IN_PICTURE) | |
1477 bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); | |
1171 if (fast) { | 1478 if (fast) { |
1172 size += 2 * sizeof(SkScalar); // + top & bottom | 1479 size += 2 * sizeof(SkScalar); // + top & bottom |
1173 } | 1480 } |
1481 #endif | |
1482 | |
1174 // + y + the actual points | 1483 // + y + the actual points |
1175 size += 1 * kUInt32Size + points * sizeof(SkScalar); | 1484 size += 1 * kUInt32Size + numChars * sizeof(SkScalar); |
1176 | 1485 |
1486 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1487 SkRect bbox; | |
1488 bbox.fLeft = xpos[0]; | |
1489 bbox.fRight = xpos[numChars - 1]; | |
1490 // if we had a guarantee that these will be monotonically increasing, this c ould be sped up | |
Tom Hudson
2013/05/14 17:00:49
Would this break on RTL? Do we have a guarantee th
| |
1491 for (size_t i = 0; i < numChars; ++i) { | |
1492 if (xpos[i] < bbox.fLeft) { | |
1493 bbox.fLeft = xpos[i]; | |
1494 } | |
1495 if (xpos[i] > bbox.fRight) { | |
1496 bbox.fRight = xpos[i]; | |
1497 } | |
1498 } | |
1499 SkPaint::FontMetrics metrics; | |
1500 paint.getFontMetrics(&metrics); | |
1501 pad_text_bbox_horizontally(metrics, &bbox); | |
1502 bbox.fTop = metrics.fTop + constY; | |
1503 bbox.fBottom = metrics.fBottom + constY; | |
1504 uint32_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size, &paint, &bbox ); | |
1505 #else | |
1177 uint32_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : D RAW_POS_TEXT_H, | 1506 uint32_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : D RAW_POS_TEXT_H, |
1178 &size); | 1507 &size); |
1508 #endif | |
1509 if (kInvalidOffset == initialOffset) { | |
1510 return; | |
1511 } | |
1512 SkASSERT(initialOffset + getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter. size()); | |
1179 const SkFlatData* flatPaintData = addPaint(paint); | 1513 const SkFlatData* flatPaintData = addPaint(paint); |
1180 SkASSERT(flatPaintData); | 1514 SkASSERT(flatPaintData); |
1181 addText(text, byteLength); | 1515 addText(text, byteLength); |
1182 addInt(points); | 1516 addInt(numChars); |
1183 | 1517 |
1184 #ifdef SK_DEBUG_SIZE | 1518 #ifdef SK_DEBUG_SIZE |
1185 size_t start = fWriter.size(); | 1519 size_t start = fWriter.size(); |
1186 #endif | 1520 #endif |
1521 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1522 // We still need to call addPaint even if we don't use flatPaintData | |
1523 sk_ignore_unused_variable(flatPaintData); | |
1524 #else | |
1187 if (fast) { | 1525 if (fast) { |
1188 addFontMetricsTopBottom(paint, *flatPaintData, constY, constY); | 1526 addFontMetricsTopBottom(paint, *flatPaintData, constY, constY); |
1189 } | 1527 } |
1528 #endif | |
1190 addScalar(constY); | 1529 addScalar(constY); |
1191 fWriter.writeMul4(xpos, points * sizeof(SkScalar)); | 1530 fWriter.writeMul4(xpos, numChars * sizeof(SkScalar)); |
1192 #ifdef SK_DEBUG_SIZE | 1531 #ifdef SK_DEBUG_SIZE |
1193 fPointBytes += fWriter.size() - start; | 1532 fPointBytes += fWriter.size() - start; |
1194 fPointWrites += points; | 1533 fPointWrites += points; |
1195 #endif | 1534 #endif |
1196 validate(initialOffset, size); | 1535 validate(initialOffset, size); |
1197 } | 1536 } |
1198 | 1537 |
1199 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength, | 1538 void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength, |
1200 const SkPath& path, const SkMatrix* matrix, | 1539 const SkPath& path, const SkMatrix* matrix, |
1201 const SkPaint& paint) { | 1540 const SkPaint& paint) { |
1202 // op + paint index + length + 'length' worth of data + path index + matrix index | 1541 // op + paint index + length + 'length' worth of data + path index + matrix index |
1203 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * kUInt32Size; | 1542 uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * kUInt32Size; |
1543 #if SK_RECORD_BOUNDS_IN_PICTURE | |
1544 SkRect bbox = path.getBounds(); | |
1545 SkPaint::FontMetrics metrics; | |
1546 paint.getFontMetrics(&metrics); | |
1547 // pad out all sides by the max glyph height above baseline | |
1548 SkScalar pad = metrics.fTop; | |
1549 bbox.fLeft += pad; | |
1550 bbox.fRight -= pad; | |
1551 bbox.fTop += pad; | |
1552 bbox.fBottom -= pad; | |
1553 uint32_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size, &paint, &bb ox); | |
1554 #else | |
1204 uint32_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size); | 1555 uint32_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size); |
1205 SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.si ze()); | 1556 #endif |
1557 if (kInvalidOffset == initialOffset) { | |
1558 return; | |
1559 } | |
1560 SkASSERT(initialOffset + getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter. size()); | |
1206 addPaint(paint); | 1561 addPaint(paint); |
1207 addText(text, byteLength); | 1562 addText(text, byteLength); |
1208 addPath(path); | 1563 addPath(path); |
1209 addMatrixPtr(matrix); | 1564 addMatrixPtr(matrix); |
1210 validate(initialOffset, size); | 1565 validate(initialOffset, size); |
1211 } | 1566 } |
1212 | 1567 |
1213 void SkPictureRecord::drawPicture(SkPicture& picture) { | 1568 void SkPictureRecord::drawPicture(SkPicture& picture) { |
1214 // op + picture index | 1569 // op + picture index |
1215 uint32_t size = 2 * kUInt32Size; | 1570 uint32_t size = 2 * kUInt32Size; |
1216 uint32_t initialOffset = this->addDraw(DRAW_PICTURE, &size); | 1571 uint32_t initialOffset = this->addDraw(DRAW_PICTURE, &size); |
1572 SkASSERT(kInvalidOffset != initialOffset); | |
1217 addPicture(picture); | 1573 addPicture(picture); |
1218 validate(initialOffset, size); | 1574 validate(initialOffset, size); |
1219 } | 1575 } |
1220 | 1576 |
1221 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount, | 1577 void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount, |
1222 const SkPoint vertices[], const SkPoint texs[], | 1578 const SkPoint vertices[], const SkPoint texs[], |
1223 const SkColor colors[], SkXfermode*, | 1579 const SkColor colors[], SkXfermode*, |
1224 const uint16_t indices[], int indexCount, | 1580 const uint16_t indices[], int indexCount, |
1225 const SkPaint& paint) { | 1581 const SkPaint& paint) { |
1226 uint32_t flags = 0; | 1582 uint32_t flags = 0; |
(...skipping 12 matching lines...) Expand all Loading... | |
1239 if (flags & DRAW_VERTICES_HAS_TEXS) { | 1595 if (flags & DRAW_VERTICES_HAS_TEXS) { |
1240 size += vertexCount * sizeof(SkPoint); // + uvs | 1596 size += vertexCount * sizeof(SkPoint); // + uvs |
1241 } | 1597 } |
1242 if (flags & DRAW_VERTICES_HAS_COLORS) { | 1598 if (flags & DRAW_VERTICES_HAS_COLORS) { |
1243 size += vertexCount * sizeof(SkColor); // + vert colors | 1599 size += vertexCount * sizeof(SkColor); // + vert colors |
1244 } | 1600 } |
1245 if (flags & DRAW_VERTICES_HAS_INDICES) { | 1601 if (flags & DRAW_VERTICES_HAS_INDICES) { |
1246 // + num indices + indices | 1602 // + num indices + indices |
1247 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t)); | 1603 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t)); |
1248 } | 1604 } |
1249 | 1605 #if SK_RECORD_BOUNDS_IN_PICTURE |
1606 SkRect bbox; | |
1607 bbox.set(vertices, vertexCount); | |
1608 uint32_t initialOffset = this->addDraw(DRAW_VERTICES, &size, &paint, &bbox); | |
1609 #else | |
1250 uint32_t initialOffset = this->addDraw(DRAW_VERTICES, &size); | 1610 uint32_t initialOffset = this->addDraw(DRAW_VERTICES, &size); |
1251 SkASSERT(initialOffset+getPaintOffset(DRAW_VERTICES, size) == fWriter.size() ); | 1611 #endif |
1612 if (kInvalidOffset == initialOffset) { | |
1613 return; | |
1614 } | |
1615 SkASSERT(initialOffset + getPaintOffset(DRAW_VERTICES, size) == fWriter.size ()); | |
1252 addPaint(paint); | 1616 addPaint(paint); |
1253 addInt(flags); | 1617 addInt(flags); |
1254 addInt(vmode); | 1618 addInt(vmode); |
1255 addInt(vertexCount); | 1619 addInt(vertexCount); |
1256 addPoints(vertices, vertexCount); | 1620 addPoints(vertices, vertexCount); |
1257 if (flags & DRAW_VERTICES_HAS_TEXS) { | 1621 if (flags & DRAW_VERTICES_HAS_TEXS) { |
1258 addPoints(texs, vertexCount); | 1622 addPoints(texs, vertexCount); |
1259 } | 1623 } |
1260 if (flags & DRAW_VERTICES_HAS_COLORS) { | 1624 if (flags & DRAW_VERTICES_HAS_COLORS) { |
1261 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor)); | 1625 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor)); |
1262 } | 1626 } |
1263 if (flags & DRAW_VERTICES_HAS_INDICES) { | 1627 if (flags & DRAW_VERTICES_HAS_INDICES) { |
1264 addInt(indexCount); | 1628 addInt(indexCount); |
1265 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); | 1629 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); |
1266 } | 1630 } |
1267 validate(initialOffset, size); | 1631 validate(initialOffset, size); |
1268 } | 1632 } |
1269 | 1633 |
1270 void SkPictureRecord::drawData(const void* data, size_t length) { | 1634 void SkPictureRecord::drawData(const void* data, size_t length) { |
1271 // op + length + 'length' worth of data | 1635 // op + length + 'length' worth of data |
1272 uint32_t size = 2 * kUInt32Size + SkAlign4(length); | 1636 uint32_t size = 2 * kUInt32Size + SkAlign4(length); |
1273 uint32_t initialOffset = this->addDraw(DRAW_DATA, &size); | 1637 uint32_t initialOffset = this->addDraw(DRAW_DATA, &size); |
1638 SkASSERT(kInvalidOffset != initialOffset); | |
1274 addInt(length); | 1639 addInt(length); |
1275 fWriter.writePad(data, length); | 1640 fWriter.writePad(data, length); |
1276 validate(initialOffset, size); | 1641 validate(initialOffset, size); |
1277 } | 1642 } |
1278 | 1643 |
1279 /////////////////////////////////////////////////////////////////////////////// | 1644 /////////////////////////////////////////////////////////////////////////////// |
1280 | 1645 |
1281 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) { | 1646 void SkPictureRecord::addBitmap(const SkBitmap& bitmap) { |
1282 const int index = fBitmapHeap->insert(bitmap); | 1647 const int index = fBitmapHeap->insert(bitmap); |
1283 // In debug builds, a bad return value from insert() will crash, allowing fo r debugging. In | 1648 // In debug builds, a bad return value from insert() will crash, allowing fo r debugging. In |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1512 void SkPictureRecord::validateRegions() const { | 1877 void SkPictureRecord::validateRegions() const { |
1513 int count = fRegions.count(); | 1878 int count = fRegions.count(); |
1514 SkASSERT((unsigned) count < 0x1000); | 1879 SkASSERT((unsigned) count < 0x1000); |
1515 for (int index = 0; index < count; index++) { | 1880 for (int index = 0; index < count; index++) { |
1516 const SkFlatData* region = fRegions[index]; | 1881 const SkFlatData* region = fRegions[index]; |
1517 SkASSERT(region); | 1882 SkASSERT(region); |
1518 // region->validate(); | 1883 // region->validate(); |
1519 } | 1884 } |
1520 } | 1885 } |
1521 #endif | 1886 #endif |
OLD | NEW |