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 |