| 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 "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/BoxBorderPainter.h" | 6 #include "core/paint/BoxBorderPainter.h" |
| 7 | 7 |
| 8 #include "core/paint/BoxPainter.h" | 8 #include "core/paint/BoxPainter.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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 const BorderEdgeFlags bottomLeftFlags = edgeFlagForSide(BSBottom) | edge
FlagForSide(BSLeft); | 73 const BorderEdgeFlags bottomLeftFlags = edgeFlagForSide(BSBottom) | edge
FlagForSide(BSLeft); |
| 74 | 74 |
| 75 BorderEdgeFlags flags = edgeFlagForSide(side) | edgeFlagForSide(adjacent
Side); | 75 BorderEdgeFlags flags = edgeFlagForSide(side) | edgeFlagForSide(adjacent
Side); |
| 76 return flags == topRightFlags || flags == bottomLeftFlags; | 76 return flags == topRightFlags || flags == bottomLeftFlags; |
| 77 } | 77 } |
| 78 return false; | 78 return false; |
| 79 } | 79 } |
| 80 | 80 |
| 81 inline bool colorsMatchAtCorner(BoxSide side, BoxSide adjacentSide, const Border
Edge edges[]) | 81 inline bool colorsMatchAtCorner(BoxSide side, BoxSide adjacentSide, const Border
Edge edges[]) |
| 82 { | 82 { |
| 83 if (edges[side].shouldRender() != edges[adjacentSide].shouldRender()) | 83 if (!edges[adjacentSide].shouldRender()) |
| 84 return false; | 84 return false; |
| 85 | 85 |
| 86 if (!edges[side].sharesColorWith(edges[adjacentSide])) | 86 if (!edges[side].sharesColorWith(edges[adjacentSide])) |
| 87 return false; | 87 return false; |
| 88 | 88 |
| 89 return !borderStyleHasUnmatchedColorsAtCorner(edges[side].borderStyle(), sid
e, adjacentSide); | 89 return !borderStyleHasUnmatchedColorsAtCorner(edges[side].borderStyle(), sid
e, adjacentSide); |
| 90 } | 90 } |
| 91 | 91 |
| 92 inline bool colorNeedsAntiAliasAtCorner(BoxSide side, BoxSide adjacentSide, cons
t BorderEdge edges[]) | |
| 93 { | |
| 94 if (!edges[side].color.hasAlpha()) | |
| 95 return false; | |
| 96 | |
| 97 if (edges[side].shouldRender() != edges[adjacentSide].shouldRender()) | |
| 98 return false; | |
| 99 | |
| 100 if (!edges[side].sharesColorWith(edges[adjacentSide])) | |
| 101 return true; | |
| 102 | |
| 103 return borderStyleHasUnmatchedColorsAtCorner(edges[side].borderStyle(), side
, adjacentSide); | |
| 104 } | |
| 105 | |
| 106 inline bool borderWillArcInnerEdge(const FloatSize& firstRadius, const FloatSize
& secondRadius) | 92 inline bool borderWillArcInnerEdge(const FloatSize& firstRadius, const FloatSize
& secondRadius) |
| 107 { | 93 { |
| 108 return !firstRadius.isZero() || !secondRadius.isZero(); | 94 return !firstRadius.isZero() || !secondRadius.isZero(); |
| 109 } | 95 } |
| 110 | 96 |
| 111 inline bool willOverdraw(BoxSide side, EBorderStyle style, BorderEdgeFlags compl
etedEdges) | 97 inline bool willOverdraw(BoxSide side, EBorderStyle style, BorderEdgeFlags compl
etedEdges) |
| 112 { | 98 { |
| 113 // If we're done with this side, it will obviously not overdraw any portion
of the current edge. | 99 // If we're done with this side, it will obviously not overdraw any portion
of the current edge. |
| 114 if (includesEdge(completedEdges, side)) | 100 if (includesEdge(completedEdges, side)) |
| 115 return false; | 101 return false; |
| 116 | 102 |
| 117 // The side is still to be drawn. It overdraws the current edge iff it has a
solid fill style. | 103 // The side is still to be drawn. It overdraws the current edge iff it has a
solid fill style. |
| 118 return borderStyleFillsBorderArea(style); | 104 return borderStyleFillsBorderArea(style); |
| 119 } | 105 } |
| 120 | 106 |
| 121 inline bool borderStylesRequireMitre(BoxSide side, BoxSide adjacentSide, EBorder
Style style, EBorderStyle adjacentStyle) | 107 inline bool borderStylesRequireMitre(BoxSide side, BoxSide adjacentSide, EBorder
Style style, EBorderStyle adjacentStyle) |
| 122 { | 108 { |
| 123 if (style == DOUBLE || adjacentStyle == DOUBLE || adjacentStyle == GROOVE ||
adjacentStyle == RIDGE) | 109 if (style == DOUBLE || adjacentStyle == DOUBLE || adjacentStyle == GROOVE ||
adjacentStyle == RIDGE) |
| 124 return true; | 110 return true; |
| 125 | 111 |
| 126 if (borderStyleIsDottedOrDashed(style) != borderStyleIsDottedOrDashed(adjace
ntStyle)) | 112 if (borderStyleIsDottedOrDashed(style) != borderStyleIsDottedOrDashed(adjace
ntStyle)) |
| 127 return true; | 113 return true; |
| 128 | 114 |
| 129 if (style != adjacentStyle) | 115 if (style != adjacentStyle) |
| 130 return true; | 116 return true; |
| 131 | 117 |
| 132 return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide); | 118 return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide); |
| 133 } | 119 } |
| 134 | 120 |
| 135 inline bool joinRequiresMitre(BoxSide side, BoxSide adjacentSide, const BorderEd
ge edges[], | |
| 136 bool allowOverdraw, BorderEdgeFlags completedEdges) | |
| 137 { | |
| 138 if (!edges[adjacentSide].isPresent) | |
| 139 return false; | |
| 140 | |
| 141 if (allowOverdraw && willOverdraw(adjacentSide, edges[adjacentSide].borderSt
yle(), completedEdges)) | |
| 142 return false; | |
| 143 | |
| 144 if (!edges[side].sharesColorWith(edges[adjacentSide])) | |
| 145 return true; | |
| 146 | |
| 147 if (borderStylesRequireMitre(side, adjacentSide, edges[side].borderStyle(),
edges[adjacentSide].borderStyle())) | |
| 148 return true; | |
| 149 | |
| 150 return false; | |
| 151 } | |
| 152 | |
| 153 FloatRect calculateSideRect(const FloatRoundedRect& outerBorder, const BorderEdg
e& edge, int side) | 121 FloatRect calculateSideRect(const FloatRoundedRect& outerBorder, const BorderEdg
e& edge, int side) |
| 154 { | 122 { |
| 155 FloatRect sideRect = outerBorder.rect(); | 123 FloatRect sideRect = outerBorder.rect(); |
| 156 int width = edge.width; | 124 int width = edge.width; |
| 157 | 125 |
| 158 if (side == BSTop) | 126 if (side == BSTop) |
| 159 sideRect.setHeight(width); | 127 sideRect.setHeight(width); |
| 160 else if (side == BSBottom) | 128 else if (side == BSBottom) |
| 161 sideRect.shiftYEdgeTo(sideRect.maxY() - width); | 129 sideRect.shiftYEdgeTo(sideRect.maxY() - width); |
| 162 else if (side == BSLeft) | 130 else if (side == BSLeft) |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 | 764 |
| 797 paintOneBorderSide(context, sideRect, BSRight, BSTop, BSBottom, path, bo
rderInfo.antiAlias, | 765 paintOneBorderSide(context, sideRect, BSRight, BSTop, BSBottom, path, bo
rderInfo.antiAlias, |
| 798 color, completedEdges); | 766 color, completedEdges); |
| 799 break; | 767 break; |
| 800 } | 768 } |
| 801 default: | 769 default: |
| 802 ASSERT_NOT_REACHED(); | 770 ASSERT_NOT_REACHED(); |
| 803 } | 771 } |
| 804 } | 772 } |
| 805 | 773 |
| 774 BoxBorderPainter::MitreType BoxBorderPainter::computeMitre(BoxSide side, BoxSide
adjacentSide, |
| 775 BorderEdgeFlags completedEdges, bool antialias) const |
| 776 { |
| 777 const BorderEdge& adjacentEdge = m_edges[adjacentSide]; |
| 778 |
| 779 // No miters for missing edges. |
| 780 if (!adjacentEdge.isPresent) |
| 781 return NoMitre; |
| 782 |
| 783 // Legacy behavior - preserve for now. |
| 784 bool allowOverdraw = !antialias; |
| 785 |
| 786 // The adjacent edge will overdraw this corner, resulting in a correct mitre
. |
| 787 if (allowOverdraw && willOverdraw(adjacentSide, adjacentEdge.borderStyle(),
completedEdges)) |
| 788 return NoMitre; |
| 789 |
| 790 // Color transitions require mitres. Use mitres compatible with the AA drawi
ng mode to avoid |
| 791 // introducing extra clips. |
| 792 if (!colorsMatchAtCorner(side, adjacentSide, m_edges)) |
| 793 return antialias ? SoftMitre : HardMitre; |
| 794 |
| 795 // Non-anti-aliased mitres ensure correct same-color seaming when required b
y style. |
| 796 if (borderStylesRequireMitre(side, adjacentSide, m_edges[side].borderStyle()
, adjacentEdge.borderStyle())) |
| 797 return HardMitre; |
| 798 |
| 799 // Overdraw the adjacent edge when the colors match and we have no style res
trictions. |
| 800 return NoMitre; |
| 801 } |
| 802 |
| 803 bool BoxBorderPainter::mitresRequireClipping(MitreType mitre1, MitreType mitre2,
EBorderStyle style, |
| 804 bool antialias) |
| 805 { |
| 806 // Clipping is required if any of the present mitres doesn't match the curre
nt AA mode. |
| 807 bool shouldClip = antialias |
| 808 ? mitre1 == HardMitre || mitre2 == HardMitre |
| 809 : mitre1 == SoftMitre || mitre2 == SoftMitre; |
| 810 |
| 811 // Some styles require clipping for any type of mitre. |
| 812 shouldClip = shouldClip |
| 813 || ((mitre1 != NoMitre || mitre2 != NoMitre) && styleRequiresClipPolygon
(style)); |
| 814 |
| 815 return shouldClip; |
| 816 } |
| 817 |
| 806 void BoxBorderPainter::paintOneBorderSide(GraphicsContext* graphicsContext, | 818 void BoxBorderPainter::paintOneBorderSide(GraphicsContext* graphicsContext, |
| 807 const FloatRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adja
centSide2, | 819 const FloatRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adja
centSide2, |
| 808 const Path* path, bool antialias, Color color, BorderEdgeFlags completedEdge
s) const | 820 const Path* path, bool antialias, Color color, BorderEdgeFlags completedEdge
s) const |
| 809 { | 821 { |
| 810 const BorderEdge& edgeToRender = m_edges[side]; | 822 const BorderEdge& edgeToRender = m_edges[side]; |
| 811 ASSERT(edgeToRender.width); | 823 ASSERT(edgeToRender.width); |
| 812 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1]; | 824 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1]; |
| 813 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2]; | 825 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2]; |
| 814 | 826 |
| 815 if (path) { | 827 if (path) { |
| 816 bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSide1,
m_edges); | 828 MitreType mitre1 = colorsMatchAtCorner(side, adjacentSide1, m_edges) ? H
ardMitre : SoftMitre; |
| 817 bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSide2,
m_edges); | 829 MitreType mitre2 = colorsMatchAtCorner(side, adjacentSide2, m_edges) ? H
ardMitre : SoftMitre; |
| 818 | 830 |
| 819 GraphicsContextStateSaver stateSaver(*graphicsContext); | 831 GraphicsContextStateSaver stateSaver(*graphicsContext); |
| 820 if (m_inner.isRenderable()) | 832 if (m_inner.isRenderable()) |
| 821 clipBorderSidePolygon(graphicsContext, side, adjacentSide1StylesMatc
h, adjacentSide2StylesMatch); | 833 clipBorderSidePolygon(graphicsContext, side, mitre1, mitre2); |
| 822 else | 834 else |
| 823 clipBorderSideForComplexInnerPath(graphicsContext, side); | 835 clipBorderSideForComplexInnerPath(graphicsContext, side); |
| 824 float thickness = std::max(std::max(edgeToRender.width, adjacentEdge1.wi
dth), adjacentEdge2.width); | 836 float thickness = std::max(std::max(edgeToRender.width, adjacentEdge1.wi
dth), adjacentEdge2.width); |
| 825 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path,
edgeToRender.width, | 837 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path,
edgeToRender.width, |
| 826 thickness, side, color, edgeToRender.borderStyle()); | 838 thickness, side, color, edgeToRender.borderStyle()); |
| 827 } else { | 839 } else { |
| 828 bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSide1, m_edges
, !antialias, completedEdges); | 840 MitreType mitre1 = computeMitre(side, adjacentSide1, completedEdges, ant
ialias); |
| 829 bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSide2, m_edges
, !antialias, completedEdges); | 841 MitreType mitre2 = computeMitre(side, adjacentSide2, completedEdges, ant
ialias); |
| 830 | 842 bool shouldClip = mitresRequireClipping(mitre1, mitre2, edgeToRender.bor
derStyle(), antialias); |
| 831 bool clipForStyle = styleRequiresClipPolygon(edgeToRender.borderStyle()) | |
| 832 && (mitreAdjacentSide1 || mitreAdjacentSide2); | |
| 833 bool clipAdjacentSide1 = colorNeedsAntiAliasAtCorner(side, adjacentSide1
, m_edges) && mitreAdjacentSide1; | |
| 834 bool clipAdjacentSide2 = colorNeedsAntiAliasAtCorner(side, adjacentSide2
, m_edges) && mitreAdjacentSide2; | |
| 835 bool shouldClip = clipForStyle || clipAdjacentSide1 || clipAdjacentSide2
; | |
| 836 | 843 |
| 837 GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip); | 844 GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip); |
| 838 if (shouldClip) { | 845 if (shouldClip) { |
| 839 bool aliasAdjacentSide1 = clipAdjacentSide1 || (clipForStyle && mitr
eAdjacentSide1); | 846 clipBorderSidePolygon(graphicsContext, side, mitre1, mitre2); |
| 840 bool aliasAdjacentSide2 = clipAdjacentSide2 || (clipForStyle && mitr
eAdjacentSide2); | 847 |
| 841 clipBorderSidePolygon(graphicsContext, side, !aliasAdjacentSide1, !a
liasAdjacentSide2); | 848 // Mitres are applied via clipping, no need to draw them. |
| 842 // Since we clipped, no need to draw with a mitre. | 849 mitre1 = mitre2 = NoMitre; |
| 843 mitreAdjacentSide1 = false; | |
| 844 mitreAdjacentSide2 = false; | |
| 845 } | 850 } |
| 846 | 851 |
| 847 ObjectPainter::drawLineForBoxSide(graphicsContext, sideRect.x(), sideRec
t.y(), | 852 ObjectPainter::drawLineForBoxSide(graphicsContext, sideRect.x(), sideRec
t.y(), |
| 848 sideRect.maxX(), sideRect.maxY(), side, color, edgeToRender.borderSt
yle(), | 853 sideRect.maxX(), sideRect.maxY(), side, color, edgeToRender.borderSt
yle(), |
| 849 mitreAdjacentSide1 ? adjacentEdge1.width : 0, mitreAdjacentSide2 ? a
djacentEdge2.width : 0, antialias); | 854 mitre1 != NoMitre ? adjacentEdge1.width : 0, mitre2 != NoMitre ? adj
acentEdge2.width : 0, |
| 855 antialias); |
| 850 } | 856 } |
| 851 } | 857 } |
| 852 | 858 |
| 853 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext* graphicsContext, | 859 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext* graphicsContext, |
| 854 const LayoutRect& borderRect, const Path& borderPath, float thickness, float
drawThickness, | 860 const LayoutRect& borderRect, const Path& borderPath, float thickness, float
drawThickness, |
| 855 BoxSide side, Color color, EBorderStyle borderStyle) const | 861 BoxSide side, Color color, EBorderStyle borderStyle) const |
| 856 { | 862 { |
| 857 if (thickness <= 0) | 863 if (thickness <= 0) |
| 858 return; | 864 return; |
| 859 | 865 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 void BoxBorderPainter::clipBorderSideForComplexInnerPath(GraphicsContext* graphi
csContext, | 999 void BoxBorderPainter::clipBorderSideForComplexInnerPath(GraphicsContext* graphi
csContext, |
| 994 BoxSide side) const | 1000 BoxSide side) const |
| 995 { | 1001 { |
| 996 graphicsContext->clip(calculateSideRectIncludingInner(m_outer, m_edges, side
)); | 1002 graphicsContext->clip(calculateSideRectIncludingInner(m_outer, m_edges, side
)); |
| 997 FloatRoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(m_inner, s
ide); | 1003 FloatRoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(m_inner, s
ide); |
| 998 if (!adjustedInnerRect.isEmpty()) | 1004 if (!adjustedInnerRect.isEmpty()) |
| 999 graphicsContext->clipOutRoundedRect(adjustedInnerRect); | 1005 graphicsContext->clipOutRoundedRect(adjustedInnerRect); |
| 1000 } | 1006 } |
| 1001 | 1007 |
| 1002 void BoxBorderPainter::clipBorderSidePolygon(GraphicsContext* graphicsContext, B
oxSide side, | 1008 void BoxBorderPainter::clipBorderSidePolygon(GraphicsContext* graphicsContext, B
oxSide side, |
| 1003 bool firstEdgeMatches, bool secondEdgeMatches) const | 1009 MitreType firstMitre, MitreType secondMitre) const |
| 1004 { | 1010 { |
| 1011 ASSERT(firstMitre != NoMitre || secondMitre != NoMitre); |
| 1012 |
| 1005 FloatPoint quad[4]; | 1013 FloatPoint quad[4]; |
| 1006 | 1014 |
| 1007 const LayoutRect outerRect(m_outer.rect()); | 1015 const LayoutRect outerRect(m_outer.rect()); |
| 1008 const LayoutRect innerRect(m_inner.rect()); | 1016 const LayoutRect innerRect(m_inner.rect()); |
| 1009 | 1017 |
| 1010 // For each side, create a quad that encompasses all parts of that side that
may draw, | 1018 // For each side, create a quad that encompasses all parts of that side that
may draw, |
| 1011 // including areas inside the innerBorder. | 1019 // including areas inside the innerBorder. |
| 1012 // | 1020 // |
| 1013 // 0----------------3 | 1021 // 0----------------3 |
| 1014 // 0 \ / 0 | 1022 // 0 \ / 0 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 quad[2].x() - m_inner.radii().bottomRight().width(), | 1140 quad[2].x() - m_inner.radii().bottomRight().width(), |
| 1133 quad[2].y()), | 1141 quad[2].y()), |
| 1134 FloatPoint( | 1142 FloatPoint( |
| 1135 quad[2].x(), | 1143 quad[2].x(), |
| 1136 quad[2].y() - m_inner.radii().bottomRight().height()), | 1144 quad[2].y() - m_inner.radii().bottomRight().height()), |
| 1137 quad[2]); | 1145 quad[2]); |
| 1138 } | 1146 } |
| 1139 break; | 1147 break; |
| 1140 } | 1148 } |
| 1141 | 1149 |
| 1142 // If the border matches both of its adjacent sides, don't anti-alias the cl
ip, and | 1150 if (firstMitre == secondMitre) { |
| 1143 // if neither side matches, anti-alias the clip. | 1151 graphicsContext->clipPolygon(4, quad, firstMitre == SoftMitre); |
| 1144 if (firstEdgeMatches == secondEdgeMatches) { | |
| 1145 graphicsContext->clipPolygon(4, quad, !firstEdgeMatches); | |
| 1146 return; | 1152 return; |
| 1147 } | 1153 } |
| 1148 | 1154 |
| 1149 // If antialiasing settings for the first edge and second edge is different, | 1155 // If antialiasing settings for the first edge and second edge is different, |
| 1150 // they have to be addressed separately. We do this by breaking the quad int
o | 1156 // they have to be addressed separately. We do this by breaking the quad int
o |
| 1151 // two parallelograms, made by moving quad[1] and quad[2]. | 1157 // two parallelograms, made by moving quad[1] and quad[2]. |
| 1152 float ax = quad[1].x() - quad[0].x(); | 1158 float ax = quad[1].x() - quad[0].x(); |
| 1153 float ay = quad[1].y() - quad[0].y(); | 1159 float ay = quad[1].y() - quad[0].y(); |
| 1154 float bx = quad[2].x() - quad[1].x(); | 1160 float bx = quad[2].x() - quad[1].x(); |
| 1155 float by = quad[2].y() - quad[1].y(); | 1161 float by = quad[2].y() - quad[1].y(); |
| 1156 float cx = quad[3].x() - quad[2].x(); | 1162 float cx = quad[3].x() - quad[2].x(); |
| 1157 float cy = quad[3].y() - quad[2].y(); | 1163 float cy = quad[3].y() - quad[2].y(); |
| 1158 | 1164 |
| 1159 const static float kEpsilon = 1e-2f; | 1165 const static float kEpsilon = 1e-2f; |
| 1160 float r1, r2; | 1166 float r1, r2; |
| 1161 if (fabsf(bx) < kEpsilon && fabsf(by) < kEpsilon) { | 1167 if (fabsf(bx) < kEpsilon && fabsf(by) < kEpsilon) { |
| 1162 // The quad was actually a triangle. | 1168 // The quad was actually a triangle. |
| 1163 r1 = r2 = 1.0f; | 1169 r1 = r2 = 1.0f; |
| 1164 } else { | 1170 } else { |
| 1165 // Extend parallelogram a bit to hide calculation error | 1171 // Extend parallelogram a bit to hide calculation error |
| 1166 const static float kExtendFill = 1e-2f; | 1172 const static float kExtendFill = 1e-2f; |
| 1167 | 1173 |
| 1168 r1 = (-ax * by + ay * bx) / (cx * by - cy * bx) + kExtendFill; | 1174 r1 = (-ax * by + ay * bx) / (cx * by - cy * bx) + kExtendFill; |
| 1169 r2 = (-cx * by + cy * bx) / (ax * by - ay * bx) + kExtendFill; | 1175 r2 = (-cx * by + cy * bx) / (ax * by - ay * bx) + kExtendFill; |
| 1170 } | 1176 } |
| 1171 | 1177 |
| 1172 FloatPoint firstQuad[4]; | 1178 if (firstMitre != NoMitre) { |
| 1173 firstQuad[0] = quad[0]; | 1179 FloatPoint firstQuad[4]; |
| 1174 firstQuad[1] = quad[1]; | 1180 firstQuad[0] = quad[0]; |
| 1175 firstQuad[2] = FloatPoint(quad[3].x() + r2 * ax, quad[3].y() + r2 * ay); | 1181 firstQuad[1] = quad[1]; |
| 1176 firstQuad[3] = quad[3]; | 1182 firstQuad[2] = FloatPoint(quad[3].x() + r2 * ax, quad[3].y() + r2 * ay); |
| 1177 graphicsContext->clipPolygon(4, firstQuad, !firstEdgeMatches); | 1183 firstQuad[3] = quad[3]; |
| 1184 graphicsContext->clipPolygon(4, firstQuad, firstMitre == SoftMitre); |
| 1185 } |
| 1178 | 1186 |
| 1179 FloatPoint secondQuad[4]; | 1187 if (secondMitre != NoMitre) { |
| 1180 secondQuad[0] = quad[0]; | 1188 FloatPoint secondQuad[4]; |
| 1181 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); | 1189 secondQuad[0] = quad[0]; |
| 1182 secondQuad[2] = quad[2]; | 1190 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy)
; |
| 1183 secondQuad[3] = quad[3]; | 1191 secondQuad[2] = quad[2]; |
| 1184 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches); | 1192 secondQuad[3] = quad[3]; |
| 1193 graphicsContext->clipPolygon(4, secondQuad, secondMitre == SoftMitre); |
| 1194 } |
| 1185 } | 1195 } |
| 1186 | 1196 |
| 1187 } // namespace blink | 1197 } // namespace blink |
| OLD | NEW |