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), |
reed1
2015/01/05 17:52:22
Why the reformat?
f(malita)
2015/01/05 18:48:36
With new var names the line got close to 80 column
| |
1002 FDot8Floor(outerT), | |
1003 FDot8Ceil(outerR), | |
1004 FDot8Ceil(outerB)); | |
993 | 1005 |
994 SkBlitterClipper clipper; | 1006 SkBlitterClipper clipper; |
995 if (clip) { | 1007 if (clip) { |
996 if (clip->quickReject(outer)) { | 1008 if (clip->quickReject(outer)) { |
997 return; | 1009 return; |
998 } | 1010 } |
999 if (!clip->contains(outer)) { | 1011 if (!clip->contains(outer)) { |
1000 blitter = clipper.apply(blitter, clip, &outer); | 1012 blitter = clipper.apply(blitter, clip, &outer); |
1001 } | 1013 } |
1002 // now we can ignore clip for the rest of the function | 1014 // now we can ignore clip for the rest of the function |
1003 } | 1015 } |
1004 | 1016 |
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 | 1017 // in case we lost a bit with diameter/2 |
1012 rx = strokeSize.fX - rx; | 1018 rx = strokeSize.fX - rx; |
1013 ry = strokeSize.fY - ry; | 1019 ry = strokeSize.fY - ry; |
1020 | |
1014 // inset by the radius | 1021 // inset by the radius |
1015 L = SkScalarToFDot8(r.fLeft + rx); | 1022 FDot8 innerL = SkScalarToFDot8(r.fLeft + rx); |
1016 T = SkScalarToFDot8(r.fTop + ry); | 1023 FDot8 innerT = SkScalarToFDot8(r.fTop + ry); |
1017 R = SkScalarToFDot8(r.fRight - rx); | 1024 FDot8 innerR = SkScalarToFDot8(r.fRight - rx); |
1018 B = SkScalarToFDot8(r.fBottom - ry); | 1025 FDot8 innerB = SkScalarToFDot8(r.fBottom - ry); |
1019 | 1026 |
1020 if (L >= R || T >= B) { | 1027 // For sub-unit strokes, tweak the hulls such that one of the edges coincide s with the pixel |
1028 // edge. This ensures that the general rect stroking logic below | |
1029 // a) doesn't blit the same scanline twice | |
1030 // b) computes the correct coverage when both edges fall within the same p ixel | |
1031 if (strokeSize.fX < 1 || strokeSize.fY < 1) { | |
1032 align_thin_stroke(outerL, innerL); | |
1033 align_thin_stroke(outerT, innerT); | |
1034 align_thin_stroke(innerR, outerR); | |
1035 align_thin_stroke(innerB, outerB); | |
1036 } | |
1037 | |
1038 // stroke the outer hull | |
1039 antifilldot8(outerL, outerT, outerR, outerB, blitter, false); | |
1040 | |
1041 // set outer to the outer rect of the middle section | |
1042 outer.set(FDot8Ceil(outerL), | |
1043 FDot8Ceil(outerT), | |
1044 FDot8Floor(outerR), | |
1045 FDot8Floor(outerB)); | |
1046 | |
1047 if (innerL >= innerR || innerT >= innerB) { | |
1021 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, outer.fBottom, | 1048 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, outer.fBottom, |
1022 blitter); | 1049 blitter); |
1023 } else { | 1050 } else { |
1024 SkIRect inner; | 1051 SkIRect inner; |
1025 // set inner to the inner rect of the middle section | 1052 // set inner to the inner rect of the middle section |
1026 inner.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); | 1053 inner.set(FDot8Floor(innerL), |
1054 FDot8Floor(innerT), | |
1055 FDot8Ceil(innerR), | |
1056 FDot8Ceil(innerB)); | |
1027 | 1057 |
1028 // draw the frame in 4 pieces | 1058 // draw the frame in 4 pieces |
1029 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, inner.fTop, | 1059 fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, inner.fTop, |
1030 blitter); | 1060 blitter); |
1031 fillcheckrect(outer.fLeft, inner.fTop, inner.fLeft, inner.fBottom, | 1061 fillcheckrect(outer.fLeft, inner.fTop, inner.fLeft, inner.fBottom, |
1032 blitter); | 1062 blitter); |
1033 fillcheckrect(inner.fRight, inner.fTop, outer.fRight, inner.fBottom, | 1063 fillcheckrect(inner.fRight, inner.fTop, outer.fRight, inner.fBottom, |
1034 blitter); | 1064 blitter); |
1035 fillcheckrect(outer.fLeft, inner.fBottom, outer.fRight, outer.fBottom, | 1065 fillcheckrect(outer.fLeft, inner.fBottom, outer.fRight, outer.fBottom, |
1036 blitter); | 1066 blitter); |
1037 | 1067 |
1038 // now stroke the inner rect, which is similar to antifilldot8() except that | 1068 // now stroke the inner rect, which is similar to antifilldot8() except that |
1039 // it treats the fractional coordinates with the inverse bias (since its | 1069 // it treats the fractional coordinates with the inverse bias (since its |
1040 // inner). | 1070 // inner). |
1041 innerstrokedot8(L, T, R, B, blitter); | 1071 innerstrokedot8(innerL, innerT, innerR, innerB, blitter); |
1042 } | 1072 } |
1043 } | 1073 } |
1044 | 1074 |
1045 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, | 1075 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, |
1046 const SkRasterClip& clip, SkBlitter* blitter) { | 1076 const SkRasterClip& clip, SkBlitter* blitter) { |
1047 if (clip.isBW()) { | 1077 if (clip.isBW()) { |
1048 AntiFrameRect(r, strokeSize, &clip.bwRgn(), blitter); | 1078 AntiFrameRect(r, strokeSize, &clip.bwRgn(), blitter); |
1049 } else { | 1079 } else { |
1050 SkAAClipBlitterWrapper wrap(clip, blitter); | 1080 SkAAClipBlitterWrapper wrap(clip, blitter); |
1051 AntiFrameRect(r, strokeSize, &wrap.getRgn(), wrap.getBlitter()); | 1081 AntiFrameRect(r, strokeSize, &wrap.getRgn(), wrap.getBlitter()); |
1052 } | 1082 } |
1053 } | 1083 } |
OLD | NEW |