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

Side by Side Diff: third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp

Issue 2640143005: Support subpixel layout for borders. (Closed)
Patch Set: Rebaselined tests. Created 3 years, 10 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
OLDNEW
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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 if (style != adjacentStyle) 129 if (style != adjacentStyle)
130 return true; 130 return true;
131 131
132 return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide); 132 return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide);
133 } 133 }
134 134
135 FloatRect calculateSideRect(const FloatRoundedRect& outerBorder, 135 FloatRect calculateSideRect(const FloatRoundedRect& outerBorder,
136 const BorderEdge& edge, 136 const BorderEdge& edge,
137 int side) { 137 int side) {
138 FloatRect sideRect = outerBorder.rect(); 138 FloatRect sideRect = outerBorder.rect();
139 int width = edge.width; 139 float width = edge.width();
140 140
141 if (side == BSTop) 141 if (side == BSTop)
142 sideRect.setHeight(width); 142 sideRect.setHeight(width);
143 else if (side == BSBottom) 143 else if (side == BSBottom)
144 sideRect.shiftYEdgeTo(sideRect.maxY() - width); 144 sideRect.shiftYEdgeTo(sideRect.maxY() - width);
145 else if (side == BSLeft) 145 else if (side == BSLeft)
146 sideRect.setWidth(width); 146 sideRect.setWidth(width);
147 else 147 else
148 sideRect.shiftXEdgeTo(sideRect.maxX() - width); 148 sideRect.shiftXEdgeTo(sideRect.maxX() - width);
149 149
150 return sideRect; 150 return sideRect;
151 } 151 }
152 152
153 FloatRect calculateSideRectIncludingInner(const FloatRoundedRect& outerBorder, 153 FloatRect calculateSideRectIncludingInner(const FloatRoundedRect& outerBorder,
154 const BorderEdge edges[], 154 const BorderEdge edges[],
155 BoxSide side) { 155 BoxSide side) {
156 FloatRect sideRect = outerBorder.rect(); 156 FloatRect sideRect = outerBorder.rect();
157 int width; 157 float width;
158 158
159 switch (side) { 159 switch (side) {
160 case BSTop: 160 case BSTop:
161 width = sideRect.height() - edges[BSBottom].width; 161 width = sideRect.height() - edges[BSBottom].width();
162 sideRect.setHeight(width); 162 sideRect.setHeight(width);
163 break; 163 break;
164 case BSBottom: 164 case BSBottom:
165 width = sideRect.height() - edges[BSTop].width; 165 width = sideRect.height() - edges[BSTop].width();
166 sideRect.shiftYEdgeTo(sideRect.maxY() - width); 166 sideRect.shiftYEdgeTo(sideRect.maxY() - width);
167 break; 167 break;
168 case BSLeft: 168 case BSLeft:
169 width = sideRect.width() - edges[BSRight].width; 169 width = sideRect.width() - edges[BSRight].width();
170 sideRect.setWidth(width); 170 sideRect.setWidth(width);
171 break; 171 break;
172 case BSRight: 172 case BSRight:
173 width = sideRect.width() - edges[BSLeft].width; 173 width = sideRect.width() - edges[BSLeft].width();
174 sideRect.shiftXEdgeTo(sideRect.maxX() - width); 174 sideRect.shiftXEdgeTo(sideRect.maxX() - width);
175 break; 175 break;
176 } 176 }
177 177
178 return sideRect; 178 return sideRect;
179 } 179 }
180 180
181 FloatRoundedRect calculateAdjustedInnerBorder( 181 FloatRoundedRect calculateAdjustedInnerBorder(
182 const FloatRoundedRect& innerBorder, 182 const FloatRoundedRect& innerBorder,
183 BoxSide side) { 183 BoxSide side) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 -edges[BSRight].getDoubleBorderStripeWidth(stripe), 273 -edges[BSRight].getDoubleBorderStripeWidth(stripe),
274 -edges[BSBottom].getDoubleBorderStripeWidth(stripe), 274 -edges[BSBottom].getDoubleBorderStripeWidth(stripe),
275 -edges[BSLeft].getDoubleBorderStripeWidth(stripe)); 275 -edges[BSLeft].getDoubleBorderStripeWidth(stripe));
276 } 276 }
277 277
278 void drawSolidBorderRect(GraphicsContext& context, 278 void drawSolidBorderRect(GraphicsContext& context,
279 const FloatRect& borderRect, 279 const FloatRect& borderRect,
280 float borderWidth, 280 float borderWidth,
281 const Color& color) { 281 const Color& color) {
282 FloatRect strokeRect(borderRect); 282 FloatRect strokeRect(borderRect);
283 borderWidth = roundf(borderWidth);
283 strokeRect.inflate(-borderWidth / 2); 284 strokeRect.inflate(-borderWidth / 2);
284 285
285 bool wasAntialias = context.shouldAntialias(); 286 bool wasAntialias = context.shouldAntialias();
286 if (!wasAntialias) 287 if (!wasAntialias)
287 context.setShouldAntialias(true); 288 context.setShouldAntialias(true);
288 289
289 context.setStrokeStyle(SolidStroke); 290 context.setStrokeStyle(SolidStroke);
290 context.setStrokeColor(color); 291 context.setStrokeColor(color);
291 context.strokeRect(strokeRect, borderWidth); 292 context.strokeRect(strokeRect, borderWidth);
292 293
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 return false; 507 return false;
507 508
508 if (firstEdge().borderStyle() != BorderStyleSolid && 509 if (firstEdge().borderStyle() != BorderStyleSolid &&
509 firstEdge().borderStyle() != BorderStyleDouble) 510 firstEdge().borderStyle() != BorderStyleDouble)
510 return false; 511 return false;
511 512
512 if (m_visibleEdgeSet == AllBorderEdges) { 513 if (m_visibleEdgeSet == AllBorderEdges) {
513 if (firstEdge().borderStyle() == BorderStyleSolid) { 514 if (firstEdge().borderStyle() == BorderStyleSolid) {
514 if (m_isUniformWidth && !m_outer.isRounded()) { 515 if (m_isUniformWidth && !m_outer.isRounded()) {
515 // 4-side, solid, uniform-width, rectangular border => one drawRect() 516 // 4-side, solid, uniform-width, rectangular border => one drawRect()
516 drawSolidBorderRect(context, m_outer.rect(), firstEdge().width, 517 drawSolidBorderRect(context, m_outer.rect(), firstEdge().width(),
517 firstEdge().color); 518 firstEdge().color);
518 } else { 519 } else {
519 // 4-side, solid border => one drawDRRect() 520 // 4-side, solid border => one drawDRRect()
520 drawBleedAdjustedDRRect(context, m_bleedAvoidance, m_outer, m_inner, 521 drawBleedAdjustedDRRect(context, m_bleedAvoidance, m_outer, m_inner,
521 firstEdge().color); 522 firstEdge().color);
522 } 523 }
523 } else { 524 } else {
524 // 4-side, double border => 2x drawDRRect() 525 // 4-side, double border => 2x drawDRRect()
525 DCHECK(firstEdge().borderStyle() == BorderStyleDouble); 526 DCHECK(firstEdge().borderStyle() == BorderStyleDouble);
526 drawDoubleBorder(context, borderRect); 527 drawDoubleBorder(context, borderRect);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 630
630 m_hasAlpha |= edge.color.hasAlpha(); 631 m_hasAlpha |= edge.color.hasAlpha();
631 632
632 if (m_visibleEdgeCount == 1) { 633 if (m_visibleEdgeCount == 1) {
633 m_firstVisibleEdge = i; 634 m_firstVisibleEdge = i;
634 continue; 635 continue;
635 } 636 }
636 637
637 m_isUniformStyle &= 638 m_isUniformStyle &=
638 edge.borderStyle() == m_edges[m_firstVisibleEdge].borderStyle(); 639 edge.borderStyle() == m_edges[m_firstVisibleEdge].borderStyle();
639 m_isUniformWidth &= edge.width == m_edges[m_firstVisibleEdge].width; 640 m_isUniformWidth &= edge.width() == m_edges[m_firstVisibleEdge].width();
640 m_isUniformColor &= edge.color == m_edges[m_firstVisibleEdge].color; 641 m_isUniformColor &= edge.color == m_edges[m_firstVisibleEdge].color;
641 } 642 }
642 } 643 }
643 644
644 void BoxBorderPainter::paintBorder(const PaintInfo& info, 645 void BoxBorderPainter::paintBorder(const PaintInfo& info,
645 const LayoutRect& rect) const { 646 const LayoutRect& rect) const {
646 if (!m_visibleEdgeCount || m_outer.rect().isEmpty()) 647 if (!m_visibleEdgeCount || m_outer.rect().isEmpty())
647 return; 648 return;
648 649
649 GraphicsContext& graphicsContext = info.context; 650 GraphicsContext& graphicsContext = info.context;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 // readability. 791 // readability.
791 switch (side) { 792 switch (side) {
792 case BSTop: { 793 case BSTop: {
793 bool usePath = m_isRounded && 794 bool usePath = m_isRounded &&
794 (borderStyleHasInnerDetail(edge.borderStyle()) || 795 (borderStyleHasInnerDetail(edge.borderStyle()) ||
795 borderWillArcInnerEdge(m_inner.getRadii().topLeft(), 796 borderWillArcInnerEdge(m_inner.getRadii().topLeft(),
796 m_inner.getRadii().topRight())); 797 m_inner.getRadii().topRight()));
797 if (usePath) 798 if (usePath)
798 path = &borderInfo.roundedBorderPath; 799 path = &borderInfo.roundedBorderPath;
799 else 800 else
800 sideRect.setHeight(edge.width); 801 sideRect.setHeight(roundf(edge.width()));
801 802
802 paintOneBorderSide(context, sideRect, BSTop, BSLeft, BSRight, path, 803 paintOneBorderSide(context, sideRect, BSTop, BSLeft, BSRight, path,
803 borderInfo.antiAlias, color, completedEdges); 804 borderInfo.antiAlias, color, completedEdges);
804 break; 805 break;
805 } 806 }
806 case BSBottom: { 807 case BSBottom: {
807 bool usePath = m_isRounded && 808 bool usePath = m_isRounded &&
808 (borderStyleHasInnerDetail(edge.borderStyle()) || 809 (borderStyleHasInnerDetail(edge.borderStyle()) ||
809 borderWillArcInnerEdge(m_inner.getRadii().bottomLeft(), 810 borderWillArcInnerEdge(m_inner.getRadii().bottomLeft(),
810 m_inner.getRadii().bottomRight())); 811 m_inner.getRadii().bottomRight()));
811 if (usePath) 812 if (usePath)
812 path = &borderInfo.roundedBorderPath; 813 path = &borderInfo.roundedBorderPath;
813 else 814 else
814 sideRect.shiftYEdgeTo(sideRect.maxY() - edge.width); 815 sideRect.shiftYEdgeTo(sideRect.maxY() - roundf(edge.width()));
815 816
816 paintOneBorderSide(context, sideRect, BSBottom, BSLeft, BSRight, path, 817 paintOneBorderSide(context, sideRect, BSBottom, BSLeft, BSRight, path,
817 borderInfo.antiAlias, color, completedEdges); 818 borderInfo.antiAlias, color, completedEdges);
818 break; 819 break;
819 } 820 }
820 case BSLeft: { 821 case BSLeft: {
821 bool usePath = m_isRounded && 822 bool usePath = m_isRounded &&
822 (borderStyleHasInnerDetail(edge.borderStyle()) || 823 (borderStyleHasInnerDetail(edge.borderStyle()) ||
823 borderWillArcInnerEdge(m_inner.getRadii().bottomLeft(), 824 borderWillArcInnerEdge(m_inner.getRadii().bottomLeft(),
824 m_inner.getRadii().topLeft())); 825 m_inner.getRadii().topLeft()));
825 if (usePath) 826 if (usePath)
826 path = &borderInfo.roundedBorderPath; 827 path = &borderInfo.roundedBorderPath;
827 else 828 else
828 sideRect.setWidth(edge.width); 829 sideRect.setWidth(roundf(edge.width()));
829 830
830 paintOneBorderSide(context, sideRect, BSLeft, BSTop, BSBottom, path, 831 paintOneBorderSide(context, sideRect, BSLeft, BSTop, BSBottom, path,
831 borderInfo.antiAlias, color, completedEdges); 832 borderInfo.antiAlias, color, completedEdges);
832 break; 833 break;
833 } 834 }
834 case BSRight: { 835 case BSRight: {
835 bool usePath = m_isRounded && 836 bool usePath = m_isRounded &&
836 (borderStyleHasInnerDetail(edge.borderStyle()) || 837 (borderStyleHasInnerDetail(edge.borderStyle()) ||
837 borderWillArcInnerEdge(m_inner.getRadii().bottomRight(), 838 borderWillArcInnerEdge(m_inner.getRadii().bottomRight(),
838 m_inner.getRadii().topRight())); 839 m_inner.getRadii().topRight()));
839 if (usePath) 840 if (usePath)
840 path = &borderInfo.roundedBorderPath; 841 path = &borderInfo.roundedBorderPath;
841 else 842 else
842 sideRect.shiftXEdgeTo(sideRect.maxX() - edge.width); 843 sideRect.shiftXEdgeTo(sideRect.maxX() - roundf(edge.width()));
843 844
844 paintOneBorderSide(context, sideRect, BSRight, BSTop, BSBottom, path, 845 paintOneBorderSide(context, sideRect, BSRight, BSTop, BSBottom, path,
845 borderInfo.antiAlias, color, completedEdges); 846 borderInfo.antiAlias, color, completedEdges);
846 break; 847 break;
847 } 848 }
848 default: 849 default:
849 ASSERT_NOT_REACHED(); 850 ASSERT_NOT_REACHED();
850 } 851 }
851 } 852 }
852 853
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 GraphicsContext& graphicsContext, 902 GraphicsContext& graphicsContext,
902 const FloatRect& sideRect, 903 const FloatRect& sideRect,
903 BoxSide side, 904 BoxSide side,
904 BoxSide adjacentSide1, 905 BoxSide adjacentSide1,
905 BoxSide adjacentSide2, 906 BoxSide adjacentSide2,
906 const Path* path, 907 const Path* path,
907 bool antialias, 908 bool antialias,
908 Color color, 909 Color color,
909 BorderEdgeFlags completedEdges) const { 910 BorderEdgeFlags completedEdges) const {
910 const BorderEdge& edgeToRender = m_edges[side]; 911 const BorderEdge& edgeToRender = m_edges[side];
911 DCHECK(edgeToRender.width); 912 DCHECK(edgeToRender.width());
912 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1]; 913 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1];
913 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2]; 914 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2];
914 915
915 if (path) { 916 if (path) {
916 MiterType miter1 = colorsMatchAtCorner(side, adjacentSide1, m_edges) 917 MiterType miter1 = colorsMatchAtCorner(side, adjacentSide1, m_edges)
917 ? HardMiter 918 ? HardMiter
918 : SoftMiter; 919 : SoftMiter;
919 MiterType miter2 = colorsMatchAtCorner(side, adjacentSide2, m_edges) 920 MiterType miter2 = colorsMatchAtCorner(side, adjacentSide2, m_edges)
920 ? HardMiter 921 ? HardMiter
921 : SoftMiter; 922 : SoftMiter;
922 923
923 GraphicsContextStateSaver stateSaver(graphicsContext); 924 GraphicsContextStateSaver stateSaver(graphicsContext);
924 if (m_inner.isRenderable()) 925 if (m_inner.isRenderable())
925 clipBorderSidePolygon(graphicsContext, side, miter1, miter2); 926 clipBorderSidePolygon(graphicsContext, side, miter1, miter2);
926 else 927 else
927 clipBorderSideForComplexInnerPath(graphicsContext, side); 928 clipBorderSideForComplexInnerPath(graphicsContext, side);
928 float thickness = std::max( 929 float thickness =
929 std::max(edgeToRender.width, adjacentEdge1.width), adjacentEdge2.width); 930 std::max(std::max(edgeToRender.width(), adjacentEdge1.width()),
931 adjacentEdge2.width());
930 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path, 932 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path,
931 edgeToRender.width, thickness, side, color, 933 edgeToRender.width(), thickness, side, color,
932 edgeToRender.borderStyle()); 934 edgeToRender.borderStyle());
933 } else { 935 } else {
934 MiterType miter1 = 936 MiterType miter1 =
935 computeMiter(side, adjacentSide1, completedEdges, antialias); 937 computeMiter(side, adjacentSide1, completedEdges, antialias);
936 MiterType miter2 = 938 MiterType miter2 =
937 computeMiter(side, adjacentSide2, completedEdges, antialias); 939 computeMiter(side, adjacentSide2, completedEdges, antialias);
938 bool shouldClip = mitersRequireClipping( 940 bool shouldClip = mitersRequireClipping(
939 miter1, miter2, edgeToRender.borderStyle(), antialias); 941 miter1, miter2, edgeToRender.borderStyle(), antialias);
940 942
941 GraphicsContextStateSaver clipStateSaver(graphicsContext, shouldClip); 943 GraphicsContextStateSaver clipStateSaver(graphicsContext, shouldClip);
942 if (shouldClip) { 944 if (shouldClip) {
943 clipBorderSidePolygon(graphicsContext, side, miter1, miter2); 945 clipBorderSidePolygon(graphicsContext, side, miter1, miter2);
944 946
945 // Miters are applied via clipping, no need to draw them. 947 // Miters are applied via clipping, no need to draw them.
946 miter1 = miter2 = NoMiter; 948 miter1 = miter2 = NoMiter;
947 } 949 }
948 950
949 ObjectPainter::drawLineForBoxSide( 951 ObjectPainter::drawLineForBoxSide(
950 graphicsContext, sideRect.x(), sideRect.y(), sideRect.maxX(), 952 graphicsContext, sideRect.x(), sideRect.y(), sideRect.maxX(),
951 sideRect.maxY(), side, color, edgeToRender.borderStyle(), 953 sideRect.maxY(), side, color, edgeToRender.borderStyle(),
952 miter1 != NoMiter ? adjacentEdge1.width : 0, 954 miter1 != NoMiter ? roundf(adjacentEdge1.width()) : 0,
953 miter2 != NoMiter ? adjacentEdge2.width : 0, antialias); 955 miter2 != NoMiter ? roundf(adjacentEdge2.width()) : 0, antialias);
954 } 956 }
955 } 957 }
956 958
957 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext& graphicsContext, 959 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext& graphicsContext,
958 const LayoutRect& borderRect, 960 const LayoutRect& borderRect,
959 const Path& borderPath, 961 const Path& borderPath,
960 float thickness, 962 float thickness,
961 float drawThickness, 963 float drawThickness,
962 BoxSide side, 964 BoxSide side,
963 Color color, 965 Color color,
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 s1 = BorderStyleOutset; 1069 s1 = BorderStyleOutset;
1068 s2 = BorderStyleInset; 1070 s2 = BorderStyleInset;
1069 } 1071 }
1070 1072
1071 // Paint full border 1073 // Paint full border
1072 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, 1074 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness,
1073 drawThickness, side, color, s1); 1075 drawThickness, side, color, s1);
1074 1076
1075 // Paint inner only 1077 // Paint inner only
1076 GraphicsContextStateSaver stateSaver(graphicsContext); 1078 GraphicsContextStateSaver stateSaver(graphicsContext);
1077 LayoutUnit topWidth(m_edges[BSTop].usedWidth() / 2); 1079 int topWidth = m_edges[BSTop].usedWidth() / 2;
1078 LayoutUnit bottomWidth(m_edges[BSBottom].usedWidth() / 2); 1080 int bottomWidth = m_edges[BSBottom].usedWidth() / 2;
1079 LayoutUnit leftWidth(m_edges[BSLeft].usedWidth() / 2); 1081 int leftWidth = m_edges[BSLeft].usedWidth() / 2;
1080 LayoutUnit rightWidth(m_edges[BSRight].usedWidth() / 2); 1082 int rightWidth = m_edges[BSRight].usedWidth() / 2;
1081 1083
1082 FloatRoundedRect clipRect = m_style.getRoundedInnerBorderFor( 1084 FloatRoundedRect clipRect = m_style.getRoundedInnerBorderFor(
1083 borderRect, 1085 borderRect,
1084 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth), 1086 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth),
1085 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); 1087 m_includeLogicalLeftEdge, m_includeLogicalRightEdge);
1086 1088
1087 graphicsContext.clipRoundedRect(clipRect); 1089 graphicsContext.clipRoundedRect(clipRect);
1088 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, 1090 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness,
1089 drawThickness, side, color, s2); 1091 drawThickness, side, color, s2);
1090 return; 1092 return;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 FloatPoint secondQuad[4]; 1294 FloatPoint secondQuad[4];
1293 secondQuad[0] = quad[0]; 1295 secondQuad[0] = quad[0];
1294 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); 1296 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy);
1295 secondQuad[2] = quad[2]; 1297 secondQuad[2] = quad[2];
1296 secondQuad[3] = quad[3]; 1298 secondQuad[3] = quad[3];
1297 clipQuad(graphicsContext, secondQuad, secondMiter == SoftMiter); 1299 clipQuad(graphicsContext, secondQuad, secondMiter == SoftMiter);
1298 } 1300 }
1299 } 1301 }
1300 1302
1301 } // namespace blink 1303 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698