| 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 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 | 1027 |
| 1028 graphicsContext.setStrokeColor(color); | 1028 graphicsContext.setStrokeColor(color); |
| 1029 | 1029 |
| 1030 if (!StrokeData::strokeIsDashed(thickness, borderStyle == BorderStyleDashed | 1030 if (!StrokeData::strokeIsDashed(thickness, borderStyle == BorderStyleDashed |
| 1031 ? DashedStroke | 1031 ? DashedStroke |
| 1032 : DottedStroke)) { | 1032 : DottedStroke)) { |
| 1033 drawWideDottedBoxSideFromPath(graphicsContext, centerlinePath, thickness); | 1033 drawWideDottedBoxSideFromPath(graphicsContext, centerlinePath, thickness); |
| 1034 return; | 1034 return; |
| 1035 } | 1035 } |
| 1036 | 1036 |
| 1037 // The stroke is doubled here because the provided path is the | |
| 1038 // outside edge of the border so half the stroke is clipped off. | |
| 1039 // The extra multiplier is so that the clipping mask can antialias | 1037 // The extra multiplier is so that the clipping mask can antialias |
| 1040 // the edges to prevent jaggies. | 1038 // the edges to prevent jaggies. |
| 1041 graphicsContext.setStrokeThickness(drawThickness * 1.1f); | 1039 graphicsContext.setStrokeThickness(drawThickness * 1.1f); |
| 1042 graphicsContext.setStrokeStyle( | 1040 graphicsContext.setStrokeStyle( |
| 1043 borderStyle == BorderStyleDashed ? DashedStroke : DottedStroke); | 1041 borderStyle == BorderStyleDashed ? DashedStroke : DottedStroke); |
| 1044 | 1042 |
| 1045 // If the number of dashes that fit in the path is odd and non-integral | |
| 1046 // then we will have an awkwardly-sized dash at the end of the path. To | |
| 1047 // try to avoid that here, we simply make the whitespace dashes ever so | |
| 1048 // slightly bigger. | |
| 1049 // TODO(schenney): This code for setting up the dash effect is trying to | 1043 // TODO(schenney): This code for setting up the dash effect is trying to |
| 1050 // do the same thing as StrokeData::setupPaintDashPathEffect and should be | 1044 // do the same thing as StrokeData::setupPaintDashPathEffect and should be |
| 1051 // refactored to re-use that code. It would require | 1045 // refactored to re-use that code. It would require |
| 1052 // GraphicsContext::strokePath to take a length parameter. | 1046 // GraphicsContext::strokePath to take a length parameter. |
| 1053 float dashLength = | 1047 float dashLength = drawThickness; |
| 1054 thickness * ((borderStyle == BorderStyleDashed) ? 3.0f : 1.0f); | |
| 1055 float gapLength = dashLength; | 1048 float gapLength = dashLength; |
| 1056 float numberOfDashes = centerlinePath.length() / dashLength; | 1049 if (borderStyle == BorderStyleDashed) { |
| 1050 dashLength *= StrokeData::dashLengthRatio(drawThickness); |
| 1051 gapLength *= StrokeData::dashGapRatio(drawThickness); |
| 1052 } |
| 1053 float pathLength = centerlinePath.length(); |
| 1057 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. | 1054 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. |
| 1058 // FIXME: should do this test per side. | 1055 // TODO(schenney): should do this test per side. |
| 1059 if (numberOfDashes >= 4) { | 1056 if (pathLength >= 2 * dashLength + gapLength) { |
| 1060 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); | 1057 float gap = gapLength; |
| 1061 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes); | 1058 if (borderStyle == BorderStyleDashed) |
| 1062 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { | 1059 gap = StrokeData::selectBestDashGap(pathLength, dashLength, gapLength); |
| 1063 float numberOfGaps = numberOfDashes / 2; | |
| 1064 gapLength += (dashLength / numberOfGaps); | |
| 1065 } | |
| 1066 | |
| 1067 DashArray lineDash; | 1060 DashArray lineDash; |
| 1068 lineDash.push_back(dashLength); | 1061 lineDash.push_back(dashLength); |
| 1069 lineDash.push_back(gapLength); | 1062 lineDash.push_back(gap); |
| 1070 graphicsContext.setLineDash(lineDash, dashLength); | 1063 graphicsContext.setLineDash(lineDash, dashLength); |
| 1071 } | 1064 } else if (pathLength > dashLength) { |
| 1065 // Exactly 2 dashes proportionally sized |
| 1066 float multiplier = pathLength / (2 * dashLength + gapLength); |
| 1067 DashArray lineDash; |
| 1068 lineDash.push_back(dashLength * multiplier); |
| 1069 lineDash.push_back(gapLength * multiplier); |
| 1070 graphicsContext.setLineDash(lineDash, 0); |
| 1071 } // else don't dash at all |
| 1072 | 1072 |
| 1073 // FIXME: stroking the border path causes issues with tight corners: | 1073 // TODO(schenney): stroking the border path causes issues with tight corners: |
| 1074 // https://bugs.webkit.org/show_bug.cgi?id=58711 | 1074 // https://bugs.chromium.org/p/chromium/issues/detail?id=344234 |
| 1075 graphicsContext.strokePath(centerlinePath); | 1075 graphicsContext.strokePath(centerlinePath); |
| 1076 } | 1076 } |
| 1077 | 1077 |
| 1078 void BoxBorderPainter::drawWideDottedBoxSideFromPath( | 1078 void BoxBorderPainter::drawWideDottedBoxSideFromPath( |
| 1079 GraphicsContext& graphicsContext, | 1079 GraphicsContext& graphicsContext, |
| 1080 const Path& borderPath, | 1080 const Path& borderPath, |
| 1081 float thickness) const { | 1081 float thickness) const { |
| 1082 graphicsContext.setStrokeThickness(thickness); | 1082 graphicsContext.setStrokeThickness(thickness); |
| 1083 graphicsContext.setStrokeStyle(DottedStroke); | 1083 graphicsContext.setStrokeStyle(DottedStroke); |
| 1084 | 1084 |
| 1085 // TODO(schenney): This code for setting up the dash effect is largely | 1085 // TODO(schenney): This code for setting up the dash effect is largely |
| 1086 // duplicated from StrokeData::setupPaintDashPathEffect and both this code | 1086 // duplicated from StrokeData::setupPaintDashPathEffect and both this code |
| 1087 // and the method above should be refactored to re-use that code. It would | 1087 // and the method above should be refactored to re-use that code. It would |
| 1088 // require GraphicsContext::strokePath to take a length parameter. | 1088 // require GraphicsContext::strokePath to take a length parameter. |
| 1089 graphicsContext.setLineCap(RoundCap); | 1089 graphicsContext.setLineCap(RoundCap); |
| 1090 | 1090 |
| 1091 // Adjust the width to get equal dot spacing as much as possible. | 1091 // Adjust the width to get equal dot spacing as much as possible. |
| 1092 float perDotLength = thickness * 2; | 1092 float perDotLength = thickness * 2; |
| 1093 static float epsilon = 1.0e-2f; | |
| 1094 float pathLength = borderPath.length(); | 1093 float pathLength = borderPath.length(); |
| 1095 | 1094 |
| 1096 if (pathLength < perDotLength + thickness) { | 1095 if (pathLength < perDotLength) { |
| 1097 // Exactly 2 dots with whatever space we can get | 1096 // Not enoguh space for 2 dots. Just draw 1 by giving a gap that is |
| 1097 // bigger than the length. |
| 1098 DashArray lineDash; | 1098 DashArray lineDash; |
| 1099 lineDash.push_back(0); | 1099 lineDash.push_back(0); |
| 1100 lineDash.push_back(pathLength - thickness - epsilon); | 1100 lineDash.push_back(perDotLength); |
| 1101 graphicsContext.setLineDash(lineDash, 0); | 1101 graphicsContext.setLineDash(lineDash, 0); |
| 1102 } else { | 1102 } else { |
| 1103 // Determine what number of dots gives the minimum deviation from | 1103 float gap = StrokeData::selectBestDashGap(pathLength, thickness, thickness); |
| 1104 // idealGap between dots. Set the gap to that width. | 1104 static const float epsilon = 1.0e-2f; |
| 1105 float minNumDots = floorf((pathLength + thickness) / perDotLength); | |
| 1106 float maxNumDots = minNumDots + 1; | |
| 1107 float minGap = (pathLength - minNumDots * thickness) / (minNumDots - 1); | |
| 1108 float maxGap = (pathLength - maxNumDots * thickness) / (maxNumDots - 1); | |
| 1109 auto gap = | |
| 1110 fabs(minGap - thickness) < fabs(maxGap - thickness) ? minGap : maxGap; | |
| 1111 DashArray lineDash; | 1105 DashArray lineDash; |
| 1112 lineDash.push_back(0); | 1106 lineDash.push_back(0); |
| 1113 lineDash.push_back(gap + thickness - epsilon); | 1107 lineDash.push_back(gap + thickness - epsilon); |
| 1114 graphicsContext.setLineDash(lineDash, 0); | 1108 graphicsContext.setLineDash(lineDash, 0); |
| 1115 } | 1109 } |
| 1116 | 1110 |
| 1117 // TODO(schenney): stroking the border path causes issues with tight corners: | 1111 // TODO(schenney): stroking the border path causes issues with tight corners: |
| 1118 // https://bugs.webkit.org/show_bug.cgi?id=58711 | 1112 // https://bugs.webkit.org/show_bug.cgi?id=58711 |
| 1119 graphicsContext.strokePath(borderPath); | 1113 graphicsContext.strokePath(borderPath); |
| 1120 } | 1114 } |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 findIntersection(edgeQuad[2], edgeQuad[3], boundQuad1, boundQuad2, | 1459 findIntersection(edgeQuad[2], edgeQuad[3], boundQuad1, boundQuad2, |
| 1466 clippingQuad[2]); | 1460 clippingQuad[2]); |
| 1467 clippingQuad[2] -= extensionOffset; | 1461 clippingQuad[2] -= extensionOffset; |
| 1468 clippingQuad[3] = edgeQuad[3] - extensionOffset; | 1462 clippingQuad[3] = edgeQuad[3] - extensionOffset; |
| 1469 | 1463 |
| 1470 clipQuad(graphicsContext, clippingQuad, secondMiter == SoftMiter); | 1464 clipQuad(graphicsContext, clippingQuad, secondMiter == SoftMiter); |
| 1471 } | 1465 } |
| 1472 } | 1466 } |
| 1473 | 1467 |
| 1474 } // namespace blink | 1468 } // namespace blink |
| OLD | NEW |