OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/paint/BoxBorderPainter.h" | 5 #include "core/paint/BoxBorderPainter.h" |
6 | 6 |
7 #include "core/paint/BoxPainter.h" | 7 #include "core/paint/BoxPainter.h" |
8 #include "core/paint/ObjectPainter.h" | 8 #include "core/paint/ObjectPainter.h" |
9 #include "core/paint/PaintInfo.h" | 9 #include "core/paint/PaintInfo.h" |
10 #include "core/style/BorderEdge.h" | 10 #include "core/style/BorderEdge.h" |
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
969 | 969 |
970 if (borderStyle == BorderStyleDouble && thickness < 3) | 970 if (borderStyle == BorderStyleDouble && thickness < 3) |
971 borderStyle = BorderStyleSolid; | 971 borderStyle = BorderStyleSolid; |
972 | 972 |
973 switch (borderStyle) { | 973 switch (borderStyle) { |
974 case BorderStyleNone: | 974 case BorderStyleNone: |
975 case BorderStyleHidden: | 975 case BorderStyleHidden: |
976 return; | 976 return; |
977 case BorderStyleDotted: | 977 case BorderStyleDotted: |
978 case BorderStyleDashed: { | 978 case BorderStyleDashed: { |
979 drawDashedDottedBoxSideFromPath(graphicsContext, borderPath, thickness, | 979 drawDashedDottedBoxSideFromPath(graphicsContext, borderRect, borderPath, |
980 drawThickness, color, borderStyle); | 980 thickness, drawThickness, color, |
981 borderStyle); | |
981 return; | 982 return; |
982 } | 983 } |
983 case BorderStyleDouble: { | 984 case BorderStyleDouble: { |
984 drawDoubleBoxSideFromPath(graphicsContext, borderRect, borderPath, | 985 drawDoubleBoxSideFromPath(graphicsContext, borderRect, borderPath, |
985 thickness, drawThickness, side, color); | 986 thickness, drawThickness, side, color); |
986 return; | 987 return; |
987 } | 988 } |
988 case BorderStyleRidge: | 989 case BorderStyleRidge: |
989 case BorderStyleGroove: { | 990 case BorderStyleGroove: { |
990 drawRidgeGrooveBoxSideFromPath(graphicsContext, borderRect, borderPath, | 991 drawRidgeGrooveBoxSideFromPath(graphicsContext, borderRect, borderPath, |
(...skipping 13 matching lines...) Expand all Loading... | |
1004 break; | 1005 break; |
1005 } | 1006 } |
1006 | 1007 |
1007 graphicsContext.setStrokeStyle(NoStroke); | 1008 graphicsContext.setStrokeStyle(NoStroke); |
1008 graphicsContext.setFillColor(color); | 1009 graphicsContext.setFillColor(color); |
1009 graphicsContext.drawRect(pixelSnappedIntRect(borderRect)); | 1010 graphicsContext.drawRect(pixelSnappedIntRect(borderRect)); |
1010 } | 1011 } |
1011 | 1012 |
1012 void BoxBorderPainter::drawDashedDottedBoxSideFromPath( | 1013 void BoxBorderPainter::drawDashedDottedBoxSideFromPath( |
1013 GraphicsContext& graphicsContext, | 1014 GraphicsContext& graphicsContext, |
1015 const LayoutRect& borderRect, | |
1014 const Path& borderPath, | 1016 const Path& borderPath, |
1015 float thickness, | 1017 float thickness, |
1016 float drawThickness, | 1018 float drawThickness, |
1017 Color color, | 1019 Color color, |
1018 EBorderStyle borderStyle) const { | 1020 EBorderStyle borderStyle) const { |
1019 graphicsContext.setStrokeColor(color); | 1021 graphicsContext.setStrokeColor(color); |
1020 | 1022 |
1023 if (borderStyle == BorderStyleDotted && thickness > 3) { | |
f(malita)
2017/03/03 15:34:08
Why is dotted predicated on thickness > 3?
These
Stephen Chennney
2017/03/03 22:19:22
Done.
| |
1024 drawWideDottedBoxSideFromPath(graphicsContext, borderRect, borderPath, | |
1025 thickness); | |
1026 return; | |
1027 } | |
1028 | |
1021 // The stroke is doubled here because the provided path is the | 1029 // The stroke is doubled here because the provided path is the |
1022 // outside edge of the border so half the stroke is clipped off. | 1030 // outside edge of the border so half the stroke is clipped off. |
1023 // The extra multiplier is so that the clipping mask can antialias | 1031 // The extra multiplier is so that the clipping mask can antialias |
1024 // the edges to prevent jaggies. | 1032 // the edges to prevent jaggies. |
1025 graphicsContext.setStrokeThickness(drawThickness * 2 * 1.1f); | 1033 graphicsContext.setStrokeThickness(drawThickness * 2 * 1.1f); |
1026 graphicsContext.setStrokeStyle( | 1034 graphicsContext.setStrokeStyle( |
1027 borderStyle == BorderStyleDashed ? DashedStroke : DottedStroke); | 1035 borderStyle == BorderStyleDashed ? DashedStroke : DottedStroke); |
1028 | 1036 |
1029 // If the number of dashes that fit in the path is odd and non-integral | 1037 // If the number of dashes that fit in the path is odd and non-integral |
1030 // then we will have an awkwardly-sized dash at the end of the path. To | 1038 // then we will have an awkwardly-sized dash at the end of the path. To |
1031 // try to avoid that here, we simply make the whitespace dashes ever so | 1039 // try to avoid that here, we simply make the whitespace dashes ever so |
1032 // slightly bigger. | 1040 // slightly bigger. |
1033 // TODO(schenney): This code for setting up the dash effect is trying to | 1041 // TODO(schenney): This code for setting up the dash effect is trying to |
1034 // do the same thing as StrokeData::setupPaintDashPathEffect and should be | 1042 // do the same thing as StrokeData::setupPaintDashPathEffect and should be |
1035 // refactored to re-use that code. It would require | 1043 // refactored to re-use that code. It would require |
1036 // GraphicsContext::strokePath to take a length parameter. | 1044 // GraphicsContext::strokePath to take a length parameter. |
1037 | |
1038 float dashLength = | 1045 float dashLength = |
1039 thickness * ((borderStyle == BorderStyleDashed) ? 3.0f : 1.0f); | 1046 thickness * ((borderStyle == BorderStyleDashed) ? 3.0f : 1.0f); |
1040 float gapLength = dashLength; | 1047 float gapLength = dashLength; |
1041 float numberOfDashes = borderPath.length() / dashLength; | 1048 float numberOfDashes = borderPath.length() / dashLength; |
1042 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. | 1049 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. |
1043 // FIXME: should do this test per side. | 1050 // FIXME: should do this test per side. |
1044 if (numberOfDashes >= 4) { | 1051 if (numberOfDashes >= 4) { |
1045 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); | 1052 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); |
1046 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes); | 1053 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes); |
1047 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { | 1054 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { |
1048 float numberOfGaps = numberOfDashes / 2; | 1055 float numberOfGaps = numberOfDashes / 2; |
1049 gapLength += (dashLength / numberOfGaps); | 1056 gapLength += (dashLength / numberOfGaps); |
1050 } | 1057 } |
1051 | 1058 |
1052 DashArray lineDash; | 1059 DashArray lineDash; |
1053 lineDash.push_back(dashLength); | 1060 lineDash.push_back(dashLength); |
1054 lineDash.push_back(gapLength); | 1061 lineDash.push_back(gapLength); |
1055 graphicsContext.setLineDash(lineDash, dashLength); | 1062 graphicsContext.setLineDash(lineDash, dashLength); |
1056 } | 1063 } |
1057 | 1064 |
1058 // FIXME: stroking the border path causes issues with tight corners: | 1065 // FIXME: stroking the border path causes issues with tight corners: |
1059 // https://bugs.webkit.org/show_bug.cgi?id=58711 | 1066 // https://bugs.webkit.org/show_bug.cgi?id=58711 |
1060 // Also, to get the best appearance we should stroke a path between the | 1067 // Also, to get the best appearance we should stroke a path between the |
1061 // two borders. | 1068 // two borders. |
1062 graphicsContext.strokePath(borderPath); | 1069 graphicsContext.strokePath(borderPath); |
1063 } | 1070 } |
1064 | 1071 |
1072 void BoxBorderPainter::drawWideDottedBoxSideFromPath( | |
1073 GraphicsContext& graphicsContext, | |
1074 const LayoutRect& borderRect, | |
1075 const Path& borderPath, | |
f(malita)
2017/03/03 15:34:08
It's kind of annoying that we don't use the provid
Stephen Chennney
2017/03/03 22:19:22
Done.
| |
1076 float thickness) const { | |
1077 // Convert the path to be down the middle of the dots. | |
1078 const LayoutRectOutsets centerOffsets( | |
1079 -roundf(m_edges[BSTop].usedWidth() * 0.5), | |
f(malita)
2017/03/03 15:34:08
Is rounding needed here? I'm always wary of snapp
Stephen Chennney
2017/03/03 22:19:22
Not needed, probably. Have changed it and we'll se
| |
1080 -roundf(m_edges[BSRight].usedWidth() * 0.5), | |
1081 -roundf(m_edges[BSBottom].usedWidth() * 0.5), | |
1082 -roundf(m_edges[BSLeft].usedWidth() * 0.5)); | |
1083 FloatRoundedRect innerClip = m_style.getRoundedInnerBorderFor( | |
f(malita)
2017/03/03 15:34:08
Naming nit: not an inner clip. Maybe centeredBord
Stephen Chennney
2017/03/03 22:19:22
Inlined.
| |
1084 borderRect, centerOffsets, m_includeLogicalLeftEdge, | |
1085 m_includeLogicalRightEdge); | |
1086 Path centerlinePath; | |
1087 centerlinePath.addRoundedRect(innerClip); | |
1088 | |
1089 graphicsContext.setStrokeThickness(thickness); | |
1090 graphicsContext.setStrokeStyle(DottedStroke); | |
1091 | |
1092 // TODO(schenney): This code for setting up the dash effect is largely | |
1093 // duplicated from StrokeData::setupPaintDashPathEffect and both this code | |
1094 // and the method above should be refactored to re-use that code. It would | |
1095 // require GraphicsContext::strokePath to take a length parameter. | |
1096 graphicsContext.setLineCap(RoundCap); | |
1097 | |
1098 // Adjust the width to get equal dot spacing as much as possible. | |
1099 float perDotLength = thickness * 2; | |
1100 static float epsilon = 1.0e-2f; | |
1101 float pathLength = centerlinePath.length(); | |
1102 | |
1103 if (pathLength < perDotLength + thickness) { | |
1104 // Exactly 2 dots with whatever space we can get | |
1105 DashArray lineDash; | |
1106 lineDash.push_back(0); | |
1107 lineDash.push_back(pathLength - thickness - epsilon); | |
1108 graphicsContext.setLineDash(lineDash, 0); | |
1109 } else { | |
1110 // Determine what number of dots gives the minimum deviation from | |
1111 // idealGap between dots. Set the gap to that width. | |
1112 float minNumDots = floorf((pathLength + thickness) / perDotLength); | |
1113 float maxNumDots = minNumDots + 1; | |
1114 float minGap = (pathLength - minNumDots * thickness) / (minNumDots - 1); | |
1115 float maxGap = (pathLength - maxNumDots * thickness) / (maxNumDots - 1); | |
1116 if (fabs(minGap - thickness) < fabs(maxGap - thickness)) { | |
1117 DashArray lineDash; | |
1118 lineDash.push_back(0); | |
1119 lineDash.push_back(minGap + thickness - epsilon); | |
1120 graphicsContext.setLineDash(lineDash, 0); | |
1121 } else { | |
1122 DashArray lineDash; | |
1123 lineDash.push_back(0); | |
1124 lineDash.push_back(maxGap + thickness - epsilon); | |
1125 graphicsContext.setLineDash(lineDash, 0); | |
1126 } | |
f(malita)
2017/03/03 15:34:08
nit: these two branches are mostly the same; maybe
Stephen Chennney
2017/03/03 22:19:22
Done.
| |
1127 } | |
1128 | |
1129 // TODO(schenney): stroking the border path causes issues with tight corners: | |
1130 // https://bugs.webkit.org/show_bug.cgi?id=58711 | |
1131 graphicsContext.strokePath(centerlinePath); | |
1132 } | |
1133 | |
1065 void BoxBorderPainter::drawDoubleBoxSideFromPath( | 1134 void BoxBorderPainter::drawDoubleBoxSideFromPath( |
1066 GraphicsContext& graphicsContext, | 1135 GraphicsContext& graphicsContext, |
1067 const LayoutRect& borderRect, | 1136 const LayoutRect& borderRect, |
1068 const Path& borderPath, | 1137 const Path& borderPath, |
1069 float thickness, | 1138 float thickness, |
1070 float drawThickness, | 1139 float drawThickness, |
1071 BoxSide side, | 1140 BoxSide side, |
1072 Color color) const { | 1141 Color color) const { |
1073 // Draw inner border line | 1142 // Draw inner border line |
1074 { | 1143 { |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1408 findIntersection(edgeQuad[2], edgeQuad[3], boundQuad1, boundQuad2, | 1477 findIntersection(edgeQuad[2], edgeQuad[3], boundQuad1, boundQuad2, |
1409 clippingQuad[2]); | 1478 clippingQuad[2]); |
1410 clippingQuad[2] -= extensionOffset; | 1479 clippingQuad[2] -= extensionOffset; |
1411 clippingQuad[3] = edgeQuad[3] - extensionOffset; | 1480 clippingQuad[3] = edgeQuad[3] - extensionOffset; |
1412 | 1481 |
1413 clipQuad(graphicsContext, clippingQuad, secondMiter == SoftMiter); | 1482 clipQuad(graphicsContext, clippingQuad, secondMiter == SoftMiter); |
1414 } | 1483 } |
1415 } | 1484 } |
1416 | 1485 |
1417 } // namespace blink | 1486 } // namespace blink |
OLD | NEW |