| 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 |