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" |
| 11 #include "SkRRect.h" | 11 #include "SkRRect.h" |
| 12 #include "SkBBoxHierarchy.h" | 12 #include "SkBBoxHierarchy.h" |
| 13 #include "SkDevice.h" | |
| 13 #include "SkPictureStateTree.h" | 14 #include "SkPictureStateTree.h" |
| 14 | 15 |
| 15 #define MIN_WRITER_SIZE 16384 | 16 #define MIN_WRITER_SIZE 16384 |
| 16 #define HEAP_BLOCK_SIZE 4096 | 17 #define HEAP_BLOCK_SIZE 4096 |
| 17 | 18 |
| 18 enum { | 19 enum { |
| 19 // just need a value that save or getSaveCount would never return | 20 // just need a value that save or getSaveCount would never return |
| 20 kNoInitialSave = -1, | 21 kNoInitialSave = -1, |
| 21 }; | 22 }; |
| 22 | 23 |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 size += kUInt32Size; | 749 size += kUInt32Size; |
| 749 } | 750 } |
| 750 uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size); | 751 uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size); |
| 751 addRRect(rrect); | 752 addRRect(rrect); |
| 752 addInt(ClipParams_pack(op, doAA)); | 753 addInt(ClipParams_pack(op, doAA)); |
| 753 recordRestoreOffsetPlaceholder(op); | 754 recordRestoreOffsetPlaceholder(op); |
| 754 | 755 |
| 755 validate(initialOffset, size); | 756 validate(initialOffset, size); |
| 756 | 757 |
| 757 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { | 758 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { |
| 758 return this->INHERITED::clipRect(rrect.getBounds(), op, doAA); | 759 return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, doAA, false); |
| 759 } else { | 760 } else { |
| 760 return this->INHERITED::clipRRect(rrect, op, doAA); | 761 return this->INHERITED::clipRRect(rrect, op, doAA); |
| 761 } | 762 } |
| 762 } | 763 } |
| 763 | 764 |
| 764 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 765 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
| 765 | 766 |
| 766 SkRect r; | 767 SkRect r; |
| 767 if (!path.isInverseFillType() && path.isRect(&r)) { | 768 if (!path.isInverseFillType() && path.isRect(&r)) { |
| 768 return this->clipRect(r, op, doAA); | 769 return this->clipRect(r, op, doAA); |
| 769 } | 770 } |
| 770 | 771 |
| 771 // op + path index + clip params | 772 // op + path index + clip params |
| 772 uint32_t size = 3 * kUInt32Size; | 773 uint32_t size = 3 * kUInt32Size; |
| 773 // recordRestoreOffsetPlaceholder doesn't always write an offset | 774 // recordRestoreOffsetPlaceholder doesn't always write an offset |
| 774 if (!fRestoreOffsetStack.isEmpty()) { | 775 if (!fRestoreOffsetStack.isEmpty()) { |
| 775 // + restore offset | 776 // + restore offset |
| 776 size += kUInt32Size; | 777 size += kUInt32Size; |
| 777 } | 778 } |
| 778 uint32_t initialOffset = this->addDraw(CLIP_PATH, &size); | 779 uint32_t initialOffset = this->addDraw(CLIP_PATH, &size); |
| 779 addPath(path); | 780 addPath(path); |
| 780 addInt(ClipParams_pack(op, doAA)); | 781 addInt(ClipParams_pack(op, doAA)); |
| 781 recordRestoreOffsetPlaceholder(op); | 782 recordRestoreOffsetPlaceholder(op); |
| 782 | 783 |
| 783 validate(initialOffset, size); | 784 validate(initialOffset, size); |
| 784 | 785 |
| 785 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { | 786 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { |
| 786 return this->INHERITED::clipRect(path.getBounds(), op, doAA); | 787 return this->updateClipConservativelyUsingBounds(path.getBounds(), op, d oAA, |
| 788 path.isInverseFillType( )); | |
| 787 } else { | 789 } else { |
| 788 return this->INHERITED::clipPath(path, op, doAA); | 790 return this->INHERITED::clipPath(path, op, doAA); |
| 789 } | 791 } |
| 790 } | 792 } |
| 791 | 793 |
| 794 bool SkPictureRecord::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, | |
| 795 bool doAA, bool invers eFilled) { | |
| 796 // This is for updating the clip when kUsePathBoundsForClip_RecordingFlag | |
| 797 // is set. The current clip of the recording canvas is used for quick | |
| 798 // culling of clipped-out primitives, which must not yield any false | |
| 799 // positives, while still rejecting as many as possible. | |
| 800 // Contract: | |
| 801 // The current clip must contain the true clip. The true | |
| 802 // clip is the clip that would have been computed with | |
| 803 // kUsePathBoundsForClip_RecordingFlag disabled. | |
| 804 // Objective: | |
| 805 // Keep the current clip as small as possible without | |
| 806 // breaking the contract, using only clip bounding rectangles | |
| 807 // (for performance). | |
| 808 if (inverseFilled) { | |
| 809 switch (op) { | |
| 810 case SkRegion::kIntersect_Op: | |
| 811 case SkRegion::kDifference_Op: | |
| 812 // These ops can only shrink the current clip. So leaving | |
| 813 // the clip unchanges conservatively respects the contract. | |
| 814 return this->getClipDeviceBounds(NULL); | |
| 815 case SkRegion::kUnion_Op: | |
| 816 case SkRegion::kReplace_Op: | |
| 817 case SkRegion::kReverseDifference_Op: | |
| 818 case SkRegion::kXOR_Op: | |
| 819 { | |
| 820 // These ops can grow the current clip up to the extents of | |
| 821 // the input clip, which is inverse filled, so we just set | |
| 822 // the current clip to the device bounds. | |
| 823 SkRect deviceBounds; | |
| 824 SkIRect deviceIBounds; | |
| 825 this->getDevice()->getGlobalBounds(&deviceIBounds); | |
| 826 deviceBounds = SkRect::MakeFromIRect(deviceIBounds); | |
| 827 this->INHERITED::save(SkCanvas::kMatrix_SaveFlag); | |
| 828 // set the clip in device space | |
| 829 this->INHERITED::setMatrix(SkMatrix::I()); | |
| 830 bool result = this->INHERITED::clipRect(deviceBounds, SkRegi on::kReplace_Op, doAA); | |
|
reed1
2013/05/07 20:49:12
nit: line-width
| |
| 831 this->INHERITED::restore(); //pop the matrix, but keep the c lip | |
| 832 return result; | |
| 833 } | |
| 834 default: | |
| 835 SkASSERT(0); // unhandled op? | |
| 836 } | |
| 837 } else { | |
| 838 // Not inverse filled | |
| 839 switch (op) { | |
| 840 case SkRegion::kIntersect_Op: | |
| 841 case SkRegion::kUnion_Op: | |
| 842 case SkRegion::kReplace_Op: | |
| 843 return this->INHERITED::clipRect(bounds, op, doAA); | |
| 844 case SkRegion::kDifference_Op: | |
| 845 // Difference can only shrink the current clip. | |
| 846 // Leaving clip unchanged conservatively fullfills the contract. | |
| 847 return this->getClipDeviceBounds(NULL); | |
| 848 case SkRegion::kReverseDifference_Op: | |
| 849 // To reverse, we swap in the bounds with a replace op. | |
| 850 // As with difference, leave it unchanged. | |
| 851 return this->INHERITED::clipRect(bounds, SkRegion::kReplace_Op, doAA); | |
| 852 case SkRegion::kXOR_Op: | |
| 853 // Be conservative, based on (A XOR B) always included in (A uni on B), | |
| 854 // which is always included in (bounds(A) union bounds(B)) | |
| 855 return this->INHERITED::clipRect(bounds, SkRegion::kUnion_Op, do AA); | |
| 856 default: | |
| 857 SkASSERT(0); // unhandled op? | |
| 858 } | |
| 859 } | |
| 860 return true; | |
| 861 } | |
| 862 | |
| 792 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { | 863 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { |
| 793 // op + region index + clip params | 864 // op + region index + clip params |
| 794 uint32_t size = 3 * kUInt32Size; | 865 uint32_t size = 3 * kUInt32Size; |
| 795 // recordRestoreOffsetPlaceholder doesn't always write an offset | 866 // recordRestoreOffsetPlaceholder doesn't always write an offset |
| 796 if (!fRestoreOffsetStack.isEmpty()) { | 867 if (!fRestoreOffsetStack.isEmpty()) { |
| 797 // + restore offset | 868 // + restore offset |
| 798 size += kUInt32Size; | 869 size += kUInt32Size; |
| 799 } | 870 } |
| 800 uint32_t initialOffset = this->addDraw(CLIP_REGION, &size); | 871 uint32_t initialOffset = this->addDraw(CLIP_REGION, &size); |
| 801 addRegion(region); | 872 addRegion(region); |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1450 void SkPictureRecord::validateRegions() const { | 1521 void SkPictureRecord::validateRegions() const { |
| 1451 int count = fRegions.count(); | 1522 int count = fRegions.count(); |
| 1452 SkASSERT((unsigned) count < 0x1000); | 1523 SkASSERT((unsigned) count < 0x1000); |
| 1453 for (int index = 0; index < count; index++) { | 1524 for (int index = 0; index < count; index++) { |
| 1454 const SkFlatData* region = fRegions[index]; | 1525 const SkFlatData* region = fRegions[index]; |
| 1455 SkASSERT(region); | 1526 SkASSERT(region); |
| 1456 // region->validate(); | 1527 // region->validate(); |
| 1457 } | 1528 } |
| 1458 } | 1529 } |
| 1459 #endif | 1530 #endif |
| OLD | NEW |