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

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: rebased 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),
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 }
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