Chromium Code Reviews| 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 |