OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 The Android Open Source Project | 3 * Copyright 2011 The Android Open Source Project |
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 | 8 |
9 | 9 |
10 #include "SkScan.h" | 10 #include "SkScan.h" |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 if (R & 0xFF) { | 967 if (R & 0xFF) { |
968 blitter->blitV(R >> 8, top, height, ~R & 0xFF); | 968 blitter->blitV(R >> 8, top, height, ~R & 0xFF); |
969 } | 969 } |
970 } | 970 } |
971 | 971 |
972 if (B & 0xFF) { | 972 if (B & 0xFF) { |
973 inner_scanline(L, bot, R, ~B & 0xFF, blitter); | 973 inner_scanline(L, bot, R, ~B & 0xFF, blitter); |
974 } | 974 } |
975 } | 975 } |
976 | 976 |
| 977 static inline void align_thin_stroke(FDot8& edge1, FDot8& edge2) { |
| 978 SkASSERT(edge1 <= edge2); |
| 979 |
| 980 if (FDot8Floor(edge1) == FDot8Floor(edge2)) { |
| 981 edge2 -= (edge1 & 0xFF); |
| 982 edge1 &= ~0xFF; |
| 983 } |
| 984 } |
| 985 |
977 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, | 986 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, |
978 const SkRegion* clip, SkBlitter* blitter) { | 987 const SkRegion* clip, SkBlitter* blitter) { |
979 SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); | 988 SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); |
980 | 989 |
981 SkScalar rx = SkScalarHalf(strokeSize.fX); | 990 SkScalar rx = SkScalarHalf(strokeSize.fX); |
982 SkScalar ry = SkScalarHalf(strokeSize.fY); | 991 SkScalar ry = SkScalarHalf(strokeSize.fY); |
983 | 992 |
984 // outset by the radius | 993 // outset by the radius |
985 FDot8 L = SkScalarToFDot8(r.fLeft - rx); | 994 FDot8 outerL = SkScalarToFDot8(r.fLeft - rx); |
986 FDot8 T = SkScalarToFDot8(r.fTop - ry); | 995 FDot8 outerT = SkScalarToFDot8(r.fTop - ry); |
987 FDot8 R = SkScalarToFDot8(r.fRight + rx); | 996 FDot8 outerR = SkScalarToFDot8(r.fRight + rx); |
988 FDot8 B = SkScalarToFDot8(r.fBottom + ry); | 997 FDot8 outerB = SkScalarToFDot8(r.fBottom + ry); |
989 | 998 |
990 SkIRect outer; | 999 SkIRect outer; |
991 // set outer to the outer rect of the outer section | 1000 // set outer to the outer rect of the outer section |
992 outer.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); | 1001 outer.set(FDot8Floor(outerL), FDot8Floor(outerT), FDot8Ceil(outerR), FDot8Ce
il(outerB)); |
993 | 1002 |
994 SkBlitterClipper clipper; | 1003 SkBlitterClipper clipper; |
995 if (clip) { | 1004 if (clip) { |
996 if (clip->quickReject(outer)) { | 1005 if (clip->quickReject(outer)) { |
997 return; | 1006 return; |
998 } | 1007 } |
999 if (!clip->contains(outer)) { | 1008 if (!clip->contains(outer)) { |
1000 blitter = clipper.apply(blitter, clip, &outer); | 1009 blitter = clipper.apply(blitter, clip, &outer); |
1001 } | 1010 } |
1002 // now we can ignore clip for the rest of the function | 1011 // now we can ignore clip for the rest of the function |
1003 } | 1012 } |
1004 | 1013 |
1005 // stroke the outer hull | |
1006 antifilldot8(L, T, R, B, blitter, false); | |
1007 | |
1008 // set outer to the outer rect of the middle section | |
1009 outer.set(FDot8Ceil(L), FDot8Ceil(T), FDot8Floor(R), FDot8Floor(B)); | |
1010 | |
1011 // in case we lost a bit with diameter/2 | 1014 // in case we lost a bit with diameter/2 |
1012 rx = strokeSize.fX - rx; | 1015 rx = strokeSize.fX - rx; |
1013 ry = strokeSize.fY - ry; | 1016 ry = strokeSize.fY - ry; |
| 1017 |
1014 // inset by the radius | 1018 // inset by the radius |
1015 L = SkScalarToFDot8(r.fLeft + rx); | 1019 FDot8 innerL = SkScalarToFDot8(r.fLeft + rx); |
1016 T = SkScalarToFDot8(r.fTop + ry); | 1020 FDot8 innerT = SkScalarToFDot8(r.fTop + ry); |
1017 R = SkScalarToFDot8(r.fRight - rx); | 1021 FDot8 innerR = SkScalarToFDot8(r.fRight - rx); |
1018 B = SkScalarToFDot8(r.fBottom - ry); | 1022 FDot8 innerB = SkScalarToFDot8(r.fBottom - ry); |
1019 | 1023 |
1020 if (L >= R || T >= B) { | 1024 // For sub-unit strokes, tweak the hulls such that one of the edges coincide
s with the pixel |
| 1025 // edge. This ensures that the general rect stroking logic below |
| 1026 // a) doesn't blit the same scanline twice |
| 1027 // b) computes the correct coverage when both edges fall within the same p
ixel |
| 1028 if (strokeSize.fX < 1 || strokeSize.fY < 1) { |
| 1029 align_thin_stroke(outerL, innerL); |
| 1030 align_thin_stroke(outerT, innerT); |
| 1031 align_thin_stroke(innerR, outerR); |
| 1032 align_thin_stroke(innerB, outerB); |
| 1033 } |
| 1034 |
| 1035 // stroke the outer hull |
| 1036 antifilldot8(outerL, outerT, outerR, outerB, blitter, false); |
| 1037 |
| 1038 // set outer to the outer rect of the middle section |
| 1039 outer.set(FDot8Ceil(outerL), FDot8Ceil(outerT), FDot8Floor(outerR), FDot8Flo
or(outerB)); |
| 1040 |
| 1041 if (innerL >= innerR || innerT >= innerB) { |
1021 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, outer.fBottom, | 1042 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, outer.fBottom, |
1022 blitter); | 1043 blitter); |
1023 } else { | 1044 } else { |
1024 SkIRect inner; | 1045 SkIRect inner; |
1025 // set inner to the inner rect of the middle section | 1046 // set inner to the inner rect of the middle section |
1026 inner.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); | 1047 inner.set(FDot8Floor(innerL), FDot8Floor(innerT), FDot8Ceil(innerR), FDo
t8Ceil(innerB)); |
1027 | 1048 |
1028 // draw the frame in 4 pieces | 1049 // draw the frame in 4 pieces |
1029 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, inner.fTop, | 1050 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, inner.fTop, |
1030 blitter); | 1051 blitter); |
1031 fillcheckrect(outer.fLeft, inner.fTop, inner.fLeft, inner.fBottom, | 1052 fillcheckrect(outer.fLeft, inner.fTop, inner.fLeft, inner.fBottom, |
1032 blitter); | 1053 blitter); |
1033 fillcheckrect(inner.fRight, inner.fTop, outer.fRight, inner.fBottom, | 1054 fillcheckrect(inner.fRight, inner.fTop, outer.fRight, inner.fBottom, |
1034 blitter); | 1055 blitter); |
1035 fillcheckrect(outer.fLeft, inner.fBottom, outer.fRight, outer.fBottom, | 1056 fillcheckrect(outer.fLeft, inner.fBottom, outer.fRight, outer.fBottom, |
1036 blitter); | 1057 blitter); |
1037 | 1058 |
1038 // now stroke the inner rect, which is similar to antifilldot8() except
that | 1059 // now stroke the inner rect, which is similar to antifilldot8() except
that |
1039 // it treats the fractional coordinates with the inverse bias (since its | 1060 // it treats the fractional coordinates with the inverse bias (since its |
1040 // inner). | 1061 // inner). |
1041 innerstrokedot8(L, T, R, B, blitter); | 1062 innerstrokedot8(innerL, innerT, innerR, innerB, blitter); |
1042 } | 1063 } |
1043 } | 1064 } |
1044 | 1065 |
1045 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, | 1066 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, |
1046 const SkRasterClip& clip, SkBlitter* blitter) { | 1067 const SkRasterClip& clip, SkBlitter* blitter) { |
1047 if (clip.isBW()) { | 1068 if (clip.isBW()) { |
1048 AntiFrameRect(r, strokeSize, &clip.bwRgn(), blitter); | 1069 AntiFrameRect(r, strokeSize, &clip.bwRgn(), blitter); |
1049 } else { | 1070 } else { |
1050 SkAAClipBlitterWrapper wrap(clip, blitter); | 1071 SkAAClipBlitterWrapper wrap(clip, blitter); |
1051 AntiFrameRect(r, strokeSize, &wrap.getRgn(), wrap.getBlitter()); | 1072 AntiFrameRect(r, strokeSize, &wrap.getRgn(), wrap.getBlitter()); |
1052 } | 1073 } |
1053 } | 1074 } |
OLD | NEW |