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, thickness, |
980 drawThickness, color, borderStyle); | 980 drawThickness, color, borderStyle); |
981 return; | 981 return; |
982 } | 982 } |
983 case BorderStyleDouble: { | 983 case BorderStyleDouble: { |
984 drawDoubleBoxSideFromPath(graphicsContext, borderRect, borderPath, | 984 drawDoubleBoxSideFromPath(graphicsContext, borderRect, borderPath, |
985 thickness, drawThickness, side, color); | 985 thickness, drawThickness, side, color); |
986 return; | 986 return; |
987 } | 987 } |
988 case BorderStyleRidge: | 988 case BorderStyleRidge: |
989 case BorderStyleGroove: { | 989 case BorderStyleGroove: { |
(...skipping 14 matching lines...) Expand all Loading... | |
1004 break; | 1004 break; |
1005 } | 1005 } |
1006 | 1006 |
1007 graphicsContext.setStrokeStyle(NoStroke); | 1007 graphicsContext.setStrokeStyle(NoStroke); |
1008 graphicsContext.setFillColor(color); | 1008 graphicsContext.setFillColor(color); |
1009 graphicsContext.drawRect(pixelSnappedIntRect(borderRect)); | 1009 graphicsContext.drawRect(pixelSnappedIntRect(borderRect)); |
1010 } | 1010 } |
1011 | 1011 |
1012 void BoxBorderPainter::drawDashedDottedBoxSideFromPath( | 1012 void BoxBorderPainter::drawDashedDottedBoxSideFromPath( |
1013 GraphicsContext& graphicsContext, | 1013 GraphicsContext& graphicsContext, |
1014 const Path& borderPath, | 1014 const LayoutRect& borderRect, |
1015 float thickness, | 1015 float thickness, |
1016 float drawThickness, | 1016 float drawThickness, |
1017 Color color, | 1017 Color color, |
1018 EBorderStyle borderStyle) const { | 1018 EBorderStyle borderStyle) const { |
1019 // Convert the path to be down the middle of the dots or dashes. | |
1020 const LayoutRectOutsets centerOffsets( | |
1021 -m_edges[BSTop].usedWidth() * 0.5, -m_edges[BSRight].usedWidth() * 0.5, | |
1022 -m_edges[BSBottom].usedWidth() * 0.5, -m_edges[BSLeft].usedWidth() * 0.5); | |
1023 Path centerlinePath; | |
1024 centerlinePath.addRoundedRect(m_style.getRoundedInnerBorderFor( | |
1025 borderRect, centerOffsets, m_includeLogicalLeftEdge, | |
1026 m_includeLogicalRightEdge)); | |
f(malita)
2017/03/04 14:24:14
I like the consolidation, but it changes dashing a
Stephen Chennney
2017/03/05 21:50:33
How about we land this and then fix dashing? The d
| |
1027 | |
1019 graphicsContext.setStrokeColor(color); | 1028 graphicsContext.setStrokeColor(color); |
1020 | 1029 |
1030 if (borderStyle == BorderStyleDotted && thickness > 3) { | |
1031 drawWideDottedBoxSideFromPath(graphicsContext, centerlinePath, thickness); | |
1032 return; | |
1033 } | |
1034 | |
1021 // The stroke is doubled here because the provided path is the | 1035 // The stroke is doubled here because the provided path is the |
1022 // outside edge of the border so half the stroke is clipped off. | 1036 // outside edge of the border so half the stroke is clipped off. |
1023 // The extra multiplier is so that the clipping mask can antialias | 1037 // The extra multiplier is so that the clipping mask can antialias |
1024 // the edges to prevent jaggies. | 1038 // the edges to prevent jaggies. |
1025 graphicsContext.setStrokeThickness(drawThickness * 2 * 1.1f); | 1039 graphicsContext.setStrokeThickness(drawThickness * 1.1f); |
1026 graphicsContext.setStrokeStyle( | 1040 graphicsContext.setStrokeStyle( |
1027 borderStyle == BorderStyleDashed ? DashedStroke : DottedStroke); | 1041 borderStyle == BorderStyleDashed ? DashedStroke : DottedStroke); |
1028 | 1042 |
1029 // If the number of dashes that fit in the path is odd and non-integral | 1043 // 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 | 1044 // 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 | 1045 // try to avoid that here, we simply make the whitespace dashes ever so |
1032 // slightly bigger. | 1046 // slightly bigger. |
1033 // TODO(schenney): This code for setting up the dash effect is trying to | 1047 // TODO(schenney): This code for setting up the dash effect is trying to |
1034 // do the same thing as StrokeData::setupPaintDashPathEffect and should be | 1048 // do the same thing as StrokeData::setupPaintDashPathEffect and should be |
1035 // refactored to re-use that code. It would require | 1049 // refactored to re-use that code. It would require |
1036 // GraphicsContext::strokePath to take a length parameter. | 1050 // GraphicsContext::strokePath to take a length parameter. |
1037 | |
1038 float dashLength = | 1051 float dashLength = |
1039 thickness * ((borderStyle == BorderStyleDashed) ? 3.0f : 1.0f); | 1052 thickness * ((borderStyle == BorderStyleDashed) ? 3.0f : 1.0f); |
1040 float gapLength = dashLength; | 1053 float gapLength = dashLength; |
1041 float numberOfDashes = borderPath.length() / dashLength; | 1054 float numberOfDashes = centerlinePath.length() / dashLength; |
1042 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. | 1055 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. |
1043 // FIXME: should do this test per side. | 1056 // FIXME: should do this test per side. |
1044 if (numberOfDashes >= 4) { | 1057 if (numberOfDashes >= 4) { |
1045 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); | 1058 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); |
1046 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes); | 1059 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes); |
1047 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { | 1060 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { |
1048 float numberOfGaps = numberOfDashes / 2; | 1061 float numberOfGaps = numberOfDashes / 2; |
1049 gapLength += (dashLength / numberOfGaps); | 1062 gapLength += (dashLength / numberOfGaps); |
1050 } | 1063 } |
1051 | 1064 |
1052 DashArray lineDash; | 1065 DashArray lineDash; |
1053 lineDash.push_back(dashLength); | 1066 lineDash.push_back(dashLength); |
1054 lineDash.push_back(gapLength); | 1067 lineDash.push_back(gapLength); |
1055 graphicsContext.setLineDash(lineDash, dashLength); | 1068 graphicsContext.setLineDash(lineDash, dashLength); |
1056 } | 1069 } |
1057 | 1070 |
1058 // FIXME: stroking the border path causes issues with tight corners: | 1071 // FIXME: stroking the border path causes issues with tight corners: |
1059 // https://bugs.webkit.org/show_bug.cgi?id=58711 | 1072 // https://bugs.webkit.org/show_bug.cgi?id=58711 |
1060 // Also, to get the best appearance we should stroke a path between the | 1073 graphicsContext.strokePath(centerlinePath); |
1061 // two borders. | 1074 } |
1075 | |
1076 void BoxBorderPainter::drawWideDottedBoxSideFromPath( | |
1077 GraphicsContext& graphicsContext, | |
1078 const Path& borderPath, | |
1079 float thickness) const { | |
1080 graphicsContext.setStrokeThickness(thickness); | |
1081 graphicsContext.setStrokeStyle(DottedStroke); | |
1082 | |
1083 // TODO(schenney): This code for setting up the dash effect is largely | |
1084 // duplicated from StrokeData::setupPaintDashPathEffect and both this code | |
1085 // and the method above should be refactored to re-use that code. It would | |
1086 // require GraphicsContext::strokePath to take a length parameter. | |
1087 graphicsContext.setLineCap(RoundCap); | |
1088 | |
1089 // Adjust the width to get equal dot spacing as much as possible. | |
1090 float perDotLength = thickness * 2; | |
1091 static float epsilon = 1.0e-2f; | |
1092 float pathLength = borderPath.length(); | |
1093 | |
1094 if (pathLength < perDotLength + thickness) { | |
1095 // Exactly 2 dots with whatever space we can get | |
1096 DashArray lineDash; | |
1097 lineDash.push_back(0); | |
1098 lineDash.push_back(pathLength - thickness - epsilon); | |
1099 graphicsContext.setLineDash(lineDash, 0); | |
1100 } else { | |
1101 // Determine what number of dots gives the minimum deviation from | |
1102 // idealGap between dots. Set the gap to that width. | |
1103 float minNumDots = floorf((pathLength + thickness) / perDotLength); | |
1104 float maxNumDots = minNumDots + 1; | |
1105 float minGap = (pathLength - minNumDots * thickness) / (minNumDots - 1); | |
1106 float maxGap = (pathLength - maxNumDots * thickness) / (maxNumDots - 1); | |
1107 auto gap = | |
1108 fabs(minGap - thickness) < fabs(maxGap - thickness) ? minGap : maxGap; | |
1109 DashArray lineDash; | |
1110 lineDash.push_back(0); | |
1111 lineDash.push_back(gap + thickness - epsilon); | |
1112 graphicsContext.setLineDash(lineDash, 0); | |
1113 } | |
1114 | |
1115 // TODO(schenney): stroking the border path causes issues with tight corners: | |
1116 // https://bugs.webkit.org/show_bug.cgi?id=58711 | |
1062 graphicsContext.strokePath(borderPath); | 1117 graphicsContext.strokePath(borderPath); |
1063 } | 1118 } |
1064 | 1119 |
1065 void BoxBorderPainter::drawDoubleBoxSideFromPath( | 1120 void BoxBorderPainter::drawDoubleBoxSideFromPath( |
1066 GraphicsContext& graphicsContext, | 1121 GraphicsContext& graphicsContext, |
1067 const LayoutRect& borderRect, | 1122 const LayoutRect& borderRect, |
1068 const Path& borderPath, | 1123 const Path& borderPath, |
1069 float thickness, | 1124 float thickness, |
1070 float drawThickness, | 1125 float drawThickness, |
1071 BoxSide side, | 1126 BoxSide side, |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1408 findIntersection(edgeQuad[2], edgeQuad[3], boundQuad1, boundQuad2, | 1463 findIntersection(edgeQuad[2], edgeQuad[3], boundQuad1, boundQuad2, |
1409 clippingQuad[2]); | 1464 clippingQuad[2]); |
1410 clippingQuad[2] -= extensionOffset; | 1465 clippingQuad[2] -= extensionOffset; |
1411 clippingQuad[3] = edgeQuad[3] - extensionOffset; | 1466 clippingQuad[3] = edgeQuad[3] - extensionOffset; |
1412 | 1467 |
1413 clipQuad(graphicsContext, clippingQuad, secondMiter == SoftMiter); | 1468 clipQuad(graphicsContext, clippingQuad, secondMiter == SoftMiter); |
1414 } | 1469 } |
1415 } | 1470 } |
1416 | 1471 |
1417 } // namespace blink | 1472 } // namespace blink |
OLD | NEW |