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 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 size += kUInt32Size; | 749 size += kUInt32Size; |
750 } | 750 } |
751 uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size); | 751 uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size); |
752 addRRect(rrect); | 752 addRRect(rrect); |
753 addInt(ClipParams_pack(op, doAA)); | 753 addInt(ClipParams_pack(op, doAA)); |
754 recordRestoreOffsetPlaceholder(op); | 754 recordRestoreOffsetPlaceholder(op); |
755 | 755 |
756 validate(initialOffset, size); | 756 validate(initialOffset, size); |
757 | 757 |
758 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { | 758 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { |
759 return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op,
doAA, false); | 759 return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op,
false); |
760 } else { | 760 } else { |
761 return this->INHERITED::clipRRect(rrect, op, doAA); | 761 return this->INHERITED::clipRRect(rrect, op, doAA); |
762 } | 762 } |
763 } | 763 } |
764 | 764 |
765 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 765 bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
766 | 766 |
767 SkRect r; | 767 SkRect r; |
768 if (!path.isInverseFillType() && path.isRect(&r)) { | 768 if (!path.isInverseFillType() && path.isRect(&r)) { |
769 return this->clipRect(r, op, doAA); | 769 return this->clipRect(r, op, doAA); |
770 } | 770 } |
771 | 771 |
772 // op + path index + clip params | 772 // op + path index + clip params |
773 uint32_t size = 3 * kUInt32Size; | 773 uint32_t size = 3 * kUInt32Size; |
774 // recordRestoreOffsetPlaceholder doesn't always write an offset | 774 // recordRestoreOffsetPlaceholder doesn't always write an offset |
775 if (!fRestoreOffsetStack.isEmpty()) { | 775 if (!fRestoreOffsetStack.isEmpty()) { |
776 // + restore offset | 776 // + restore offset |
777 size += kUInt32Size; | 777 size += kUInt32Size; |
778 } | 778 } |
779 uint32_t initialOffset = this->addDraw(CLIP_PATH, &size); | 779 uint32_t initialOffset = this->addDraw(CLIP_PATH, &size); |
780 addPath(path); | 780 addPath(path); |
781 addInt(ClipParams_pack(op, doAA)); | 781 addInt(ClipParams_pack(op, doAA)); |
782 recordRestoreOffsetPlaceholder(op); | 782 recordRestoreOffsetPlaceholder(op); |
783 | 783 |
784 validate(initialOffset, size); | 784 validate(initialOffset, size); |
785 | 785 |
786 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { | 786 if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) { |
787 return this->updateClipConservativelyUsingBounds(path.getBounds(), op, d
oAA, | 787 return this->updateClipConservativelyUsingBounds(path.getBounds(), op, |
788 path.isInverseFillType(
)); | 788 path.isInverseFillType(
)); |
789 } else { | 789 } else { |
790 return this->INHERITED::clipPath(path, op, doAA); | 790 return this->INHERITED::clipPath(path, op, doAA); |
791 } | 791 } |
792 } | 792 } |
793 | 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, | |
831 SkRegion::kReplace_Op, doAA); | |
832 this->INHERITED::restore(); //pop the matrix, but keep the c
lip | |
833 return result; | |
834 } | |
835 default: | |
836 SkASSERT(0); // unhandled op? | |
837 } | |
838 } else { | |
839 // Not inverse filled | |
840 switch (op) { | |
841 case SkRegion::kIntersect_Op: | |
842 case SkRegion::kUnion_Op: | |
843 case SkRegion::kReplace_Op: | |
844 return this->INHERITED::clipRect(bounds, op, doAA); | |
845 case SkRegion::kDifference_Op: | |
846 // Difference can only shrink the current clip. | |
847 // Leaving clip unchanged conservatively fullfills the contract. | |
848 return this->getClipDeviceBounds(NULL); | |
849 case SkRegion::kReverseDifference_Op: | |
850 // To reverse, we swap in the bounds with a replace op. | |
851 // As with difference, leave it unchanged. | |
852 return this->INHERITED::clipRect(bounds, SkRegion::kReplace_Op,
doAA); | |
853 case SkRegion::kXOR_Op: | |
854 // Be conservative, based on (A XOR B) always included in (A uni
on B), | |
855 // which is always included in (bounds(A) union bounds(B)) | |
856 return this->INHERITED::clipRect(bounds, SkRegion::kUnion_Op, do
AA); | |
857 default: | |
858 SkASSERT(0); // unhandled op? | |
859 } | |
860 } | |
861 return true; | |
862 } | |
863 | |
864 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { | 794 bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { |
865 // op + region index + clip params | 795 // op + region index + clip params |
866 uint32_t size = 3 * kUInt32Size; | 796 uint32_t size = 3 * kUInt32Size; |
867 // recordRestoreOffsetPlaceholder doesn't always write an offset | 797 // recordRestoreOffsetPlaceholder doesn't always write an offset |
868 if (!fRestoreOffsetStack.isEmpty()) { | 798 if (!fRestoreOffsetStack.isEmpty()) { |
869 // + restore offset | 799 // + restore offset |
870 size += kUInt32Size; | 800 size += kUInt32Size; |
871 } | 801 } |
872 uint32_t initialOffset = this->addDraw(CLIP_REGION, &size); | 802 uint32_t initialOffset = this->addDraw(CLIP_REGION, &size); |
873 addRegion(region); | 803 addRegion(region); |
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 void SkPictureRecord::validateRegions() const { | 1442 void SkPictureRecord::validateRegions() const { |
1513 int count = fRegions.count(); | 1443 int count = fRegions.count(); |
1514 SkASSERT((unsigned) count < 0x1000); | 1444 SkASSERT((unsigned) count < 0x1000); |
1515 for (int index = 0; index < count; index++) { | 1445 for (int index = 0; index < count; index++) { |
1516 const SkFlatData* region = fRegions[index]; | 1446 const SkFlatData* region = fRegions[index]; |
1517 SkASSERT(region); | 1447 SkASSERT(region); |
1518 // region->validate(); | 1448 // region->validate(); |
1519 } | 1449 } |
1520 } | 1450 } |
1521 #endif | 1451 #endif |
OLD | NEW |