Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: src/core/SkScan_Antihair.cpp

Issue 819253003: Fix thin rect stroking. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: formatting Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 }
OLDNEW
« no previous file with comments | « expectations/gm/ignored-tests.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698