| 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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 LayoutRectOutsets doubleStripeInsets(const BorderEdge edges[], BorderEdge::Doubl
eBorderStripe stripe) | 244 LayoutRectOutsets doubleStripeInsets(const BorderEdge edges[], BorderEdge::Doubl
eBorderStripe stripe) |
| 245 { | 245 { |
| 246 // Insets are representes as negative outsets. | 246 // Insets are representes as negative outsets. |
| 247 return LayoutRectOutsets( | 247 return LayoutRectOutsets( |
| 248 -edges[BSTop].getDoubleBorderStripeWidth(stripe), | 248 -edges[BSTop].getDoubleBorderStripeWidth(stripe), |
| 249 -edges[BSRight].getDoubleBorderStripeWidth(stripe), | 249 -edges[BSRight].getDoubleBorderStripeWidth(stripe), |
| 250 -edges[BSBottom].getDoubleBorderStripeWidth(stripe), | 250 -edges[BSBottom].getDoubleBorderStripeWidth(stripe), |
| 251 -edges[BSLeft].getDoubleBorderStripeWidth(stripe)); | 251 -edges[BSLeft].getDoubleBorderStripeWidth(stripe)); |
| 252 } | 252 } |
| 253 | 253 |
| 254 void drawSolidBorderRect(GraphicsContext* context, const FloatRect& borderRect, | 254 void drawSolidBorderRect(GraphicsContext& context, const FloatRect& borderRect, |
| 255 float borderWidth, const Color& color) | 255 float borderWidth, const Color& color) |
| 256 { | 256 { |
| 257 FloatRect strokeRect(borderRect); | 257 FloatRect strokeRect(borderRect); |
| 258 strokeRect.inflate(-borderWidth / 2); | 258 strokeRect.inflate(-borderWidth / 2); |
| 259 | 259 |
| 260 bool wasAntialias = context->shouldAntialias(); | 260 bool wasAntialias = context.shouldAntialias(); |
| 261 if (!wasAntialias) | 261 if (!wasAntialias) |
| 262 context->setShouldAntialias(true); | 262 context.setShouldAntialias(true); |
| 263 | 263 |
| 264 context->setStrokeStyle(SolidStroke); | 264 context.setStrokeStyle(SolidStroke); |
| 265 context->setStrokeColor(color); | 265 context.setStrokeColor(color); |
| 266 context->strokeRect(strokeRect, borderWidth); | 266 context.strokeRect(strokeRect, borderWidth); |
| 267 | 267 |
| 268 if (!wasAntialias) | 268 if (!wasAntialias) |
| 269 context->setShouldAntialias(false); | 269 context.setShouldAntialias(false); |
| 270 } | 270 } |
| 271 | 271 |
| 272 void drawBleedAdjustedDRRect(GraphicsContext* context, BackgroundBleedAvoidance
bleedAvoidance, | 272 void drawBleedAdjustedDRRect(GraphicsContext& context, BackgroundBleedAvoidance
bleedAvoidance, |
| 273 const FloatRoundedRect& outer, const FloatRoundedRect& inner, Color color) | 273 const FloatRoundedRect& outer, const FloatRoundedRect& inner, Color color) |
| 274 { | 274 { |
| 275 switch (bleedAvoidance) { | 275 switch (bleedAvoidance) { |
| 276 case BackgroundBleedClipLayer: { | 276 case BackgroundBleedClipLayer: { |
| 277 // BackgroundBleedClipLayer clips the outer rrect for the whole layer. B
ased on this, | 277 // BackgroundBleedClipLayer clips the outer rrect for the whole layer. B
ased on this, |
| 278 // we can avoid background bleeding by filling the *outside* of inner rr
ect, all the | 278 // we can avoid background bleeding by filling the *outside* of inner rr
ect, all the |
| 279 // way to the layer bounds (enclosing int rect for the clip, in device s
pace). | 279 // way to the layer bounds (enclosing int rect for the clip, in device s
pace). |
| 280 ASSERT(outer.isRounded()); | 280 ASSERT(outer.isRounded()); |
| 281 | 281 |
| 282 SkPath path; | 282 SkPath path; |
| 283 path.addRRect(inner); | 283 path.addRRect(inner); |
| 284 path.setFillType(SkPath::kInverseWinding_FillType); | 284 path.setFillType(SkPath::kInverseWinding_FillType); |
| 285 | 285 |
| 286 SkPaint paint; | 286 SkPaint paint; |
| 287 paint.setColor(color.rgb()); | 287 paint.setColor(color.rgb()); |
| 288 paint.setStyle(SkPaint::kFill_Style); | 288 paint.setStyle(SkPaint::kFill_Style); |
| 289 paint.setAntiAlias(true); | 289 paint.setAntiAlias(true); |
| 290 context->drawPath(path, paint); | 290 context.drawPath(path, paint); |
| 291 | 291 |
| 292 break; | 292 break; |
| 293 } | 293 } |
| 294 case BackgroundBleedClipOnly: | 294 case BackgroundBleedClipOnly: |
| 295 if (outer.isRounded()) { | 295 if (outer.isRounded()) { |
| 296 // BackgroundBleedClipOnly clips the outer rrect corners for us. | 296 // BackgroundBleedClipOnly clips the outer rrect corners for us. |
| 297 FloatRoundedRect adjustedOuter = outer; | 297 FloatRoundedRect adjustedOuter = outer; |
| 298 adjustedOuter.setRadii(FloatRoundedRect::Radii()); | 298 adjustedOuter.setRadii(FloatRoundedRect::Radii()); |
| 299 context->fillDRRect(adjustedOuter, inner, color); | 299 context.fillDRRect(adjustedOuter, inner, color); |
| 300 break; | 300 break; |
| 301 } | 301 } |
| 302 // fall through | 302 // fall through |
| 303 default: | 303 default: |
| 304 context->fillDRRect(outer, inner, color); | 304 context.fillDRRect(outer, inner, color); |
| 305 break; | 305 break; |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 | 308 |
| 309 bool bleedAvoidanceIsClipping(BackgroundBleedAvoidance bleedAvoidance) | 309 bool bleedAvoidanceIsClipping(BackgroundBleedAvoidance bleedAvoidance) |
| 310 { | 310 { |
| 311 return bleedAvoidance == BackgroundBleedClipOnly || bleedAvoidance == Backgr
oundBleedClipLayer; | 311 return bleedAvoidance == BackgroundBleedClipOnly || bleedAvoidance == Backgr
oundBleedClipLayer; |
| 312 } | 312 } |
| 313 | 313 |
| 314 // The LUTs below assume specific enum values. | 314 // The LUTs below assume specific enum values. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 ASSERT(!opacityGroups.isEmpty()); | 432 ASSERT(!opacityGroups.isEmpty()); |
| 433 OpacityGroup& currentGroup = opacityGroups.last(); | 433 OpacityGroup& currentGroup = opacityGroups.last(); |
| 434 currentGroup.sides.append(side); | 434 currentGroup.sides.append(side); |
| 435 currentGroup.edgeFlags |= edgeFlagForSide(side); | 435 currentGroup.edgeFlags |= edgeFlagForSide(side); |
| 436 } | 436 } |
| 437 | 437 |
| 438 ASSERT(!opacityGroups.isEmpty()); | 438 ASSERT(!opacityGroups.isEmpty()); |
| 439 } | 439 } |
| 440 }; | 440 }; |
| 441 | 441 |
| 442 void BoxBorderPainter::drawDoubleBorder(GraphicsContext* context, const LayoutRe
ct& borderRect) const | 442 void BoxBorderPainter::drawDoubleBorder(GraphicsContext& context, const LayoutRe
ct& borderRect) const |
| 443 { | 443 { |
| 444 ASSERT(m_isUniformColor); | 444 ASSERT(m_isUniformColor); |
| 445 ASSERT(m_isUniformStyle); | 445 ASSERT(m_isUniformStyle); |
| 446 ASSERT(firstEdge().borderStyle() == DOUBLE); | 446 ASSERT(firstEdge().borderStyle() == DOUBLE); |
| 447 ASSERT(m_visibleEdgeSet == AllBorderEdges); | 447 ASSERT(m_visibleEdgeSet == AllBorderEdges); |
| 448 | 448 |
| 449 const Color color = firstEdge().color; | 449 const Color color = firstEdge().color; |
| 450 | 450 |
| 451 // outer stripe | 451 // outer stripe |
| 452 const LayoutRectOutsets outerThirdInsets = | 452 const LayoutRectOutsets outerThirdInsets = |
| 453 doubleStripeInsets(m_edges, BorderEdge::DoubleBorderStripeOuter); | 453 doubleStripeInsets(m_edges, BorderEdge::DoubleBorderStripeOuter); |
| 454 const FloatRoundedRect outerThirdRect = m_style.getRoundedInnerBorderFor(bor
derRect, | 454 const FloatRoundedRect outerThirdRect = m_style.getRoundedInnerBorderFor(bor
derRect, |
| 455 outerThirdInsets, m_includeLogicalLeftEdge, m_includeLogicalRightEdge); | 455 outerThirdInsets, m_includeLogicalLeftEdge, m_includeLogicalRightEdge); |
| 456 drawBleedAdjustedDRRect(context, m_bleedAvoidance, m_outer, outerThirdRect,
color); | 456 drawBleedAdjustedDRRect(context, m_bleedAvoidance, m_outer, outerThirdRect,
color); |
| 457 | 457 |
| 458 // inner stripe | 458 // inner stripe |
| 459 const LayoutRectOutsets innerThirdInsets = | 459 const LayoutRectOutsets innerThirdInsets = |
| 460 doubleStripeInsets(m_edges, BorderEdge::DoubleBorderStripeInner); | 460 doubleStripeInsets(m_edges, BorderEdge::DoubleBorderStripeInner); |
| 461 const FloatRoundedRect innerThirdRect = m_style.getRoundedInnerBorderFor(bor
derRect, | 461 const FloatRoundedRect innerThirdRect = m_style.getRoundedInnerBorderFor(bor
derRect, |
| 462 innerThirdInsets, m_includeLogicalLeftEdge, m_includeLogicalRightEdge); | 462 innerThirdInsets, m_includeLogicalLeftEdge, m_includeLogicalRightEdge); |
| 463 context->fillDRRect(innerThirdRect, m_inner, color); | 463 context.fillDRRect(innerThirdRect, m_inner, color); |
| 464 } | 464 } |
| 465 | 465 |
| 466 bool BoxBorderPainter::paintBorderFastPath(GraphicsContext* context, const Layou
tRect& borderRect) const | 466 bool BoxBorderPainter::paintBorderFastPath(GraphicsContext& context, const Layou
tRect& borderRect) const |
| 467 { | 467 { |
| 468 if (!m_isUniformColor || !m_isUniformStyle || !m_inner.isRenderable()) | 468 if (!m_isUniformColor || !m_isUniformStyle || !m_inner.isRenderable()) |
| 469 return false; | 469 return false; |
| 470 | 470 |
| 471 if (firstEdge().borderStyle() != SOLID && firstEdge().borderStyle() != DOUBL
E) | 471 if (firstEdge().borderStyle() != SOLID && firstEdge().borderStyle() != DOUBL
E) |
| 472 return false; | 472 return false; |
| 473 | 473 |
| 474 if (m_visibleEdgeSet == AllBorderEdges) { | 474 if (m_visibleEdgeSet == AllBorderEdges) { |
| 475 if (firstEdge().borderStyle() == SOLID) { | 475 if (firstEdge().borderStyle() == SOLID) { |
| 476 if (m_isUniformWidth && !m_outer.isRounded()) { | 476 if (m_isUniformWidth && !m_outer.isRounded()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 496 // solid, rectangular border => one drawPath() | 496 // solid, rectangular border => one drawPath() |
| 497 Path path; | 497 Path path; |
| 498 path.setWindRule(RULE_NONZERO); | 498 path.setWindRule(RULE_NONZERO); |
| 499 | 499 |
| 500 for (int i = BSTop; i <= BSLeft; ++i) { | 500 for (int i = BSTop; i <= BSLeft; ++i) { |
| 501 const BorderEdge& currEdge = m_edges[i]; | 501 const BorderEdge& currEdge = m_edges[i]; |
| 502 if (currEdge.shouldRender()) | 502 if (currEdge.shouldRender()) |
| 503 path.addRect(calculateSideRect(m_outer, currEdge, i)); | 503 path.addRect(calculateSideRect(m_outer, currEdge, i)); |
| 504 } | 504 } |
| 505 | 505 |
| 506 context->setFillColor(firstEdge().color); | 506 context.setFillColor(firstEdge().color); |
| 507 context->fillPath(path); | 507 context.fillPath(path); |
| 508 return true; | 508 return true; |
| 509 } | 509 } |
| 510 | 510 |
| 511 return false; | 511 return false; |
| 512 } | 512 } |
| 513 | 513 |
| 514 BoxBorderPainter::BoxBorderPainter(const LayoutRect& borderRect, const ComputedS
tyle& style, | 514 BoxBorderPainter::BoxBorderPainter(const LayoutRect& borderRect, const ComputedS
tyle& style, |
| 515 BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, | 515 BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, |
| 516 bool includeLogicalRightEdge) | 516 bool includeLogicalRightEdge) |
| 517 : m_style(style) | 517 : m_style(style) |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 m_isUniformWidth &= edge.width == m_edges[m_firstVisibleEdge].width; | 593 m_isUniformWidth &= edge.width == m_edges[m_firstVisibleEdge].width; |
| 594 m_isUniformColor &= edge.color == m_edges[m_firstVisibleEdge].color; | 594 m_isUniformColor &= edge.color == m_edges[m_firstVisibleEdge].color; |
| 595 } | 595 } |
| 596 } | 596 } |
| 597 | 597 |
| 598 void BoxBorderPainter::paintBorder(const PaintInfo& info, const LayoutRect& rect
) const | 598 void BoxBorderPainter::paintBorder(const PaintInfo& info, const LayoutRect& rect
) const |
| 599 { | 599 { |
| 600 if (!m_visibleEdgeCount || m_outer.rect().isEmpty()) | 600 if (!m_visibleEdgeCount || m_outer.rect().isEmpty()) |
| 601 return; | 601 return; |
| 602 | 602 |
| 603 GraphicsContext* graphicsContext = info.context; | 603 GraphicsContext& graphicsContext = info.context; |
| 604 | 604 |
| 605 if (paintBorderFastPath(graphicsContext, rect)) | 605 if (paintBorderFastPath(graphicsContext, rect)) |
| 606 return; | 606 return; |
| 607 | 607 |
| 608 bool clipToOuterBorder = m_outer.isRounded(); | 608 bool clipToOuterBorder = m_outer.isRounded(); |
| 609 GraphicsContextStateSaver stateSaver(*graphicsContext, clipToOuterBorder); | 609 GraphicsContextStateSaver stateSaver(graphicsContext, clipToOuterBorder); |
| 610 if (clipToOuterBorder) { | 610 if (clipToOuterBorder) { |
| 611 // For BackgroundBleedClip{Only,Layer}, the outer rrect clip is already
applied. | 611 // For BackgroundBleedClip{Only,Layer}, the outer rrect clip is already
applied. |
| 612 if (!bleedAvoidanceIsClipping(m_bleedAvoidance)) | 612 if (!bleedAvoidanceIsClipping(m_bleedAvoidance)) |
| 613 graphicsContext->clipRoundedRect(m_outer); | 613 graphicsContext.clipRoundedRect(m_outer); |
| 614 | 614 |
| 615 if (m_inner.isRenderable() && !m_inner.isEmpty()) | 615 if (m_inner.isRenderable() && !m_inner.isEmpty()) |
| 616 graphicsContext->clipOutRoundedRect(m_inner); | 616 graphicsContext.clipOutRoundedRect(m_inner); |
| 617 } | 617 } |
| 618 | 618 |
| 619 const ComplexBorderInfo borderInfo(*this, true); | 619 const ComplexBorderInfo borderInfo(*this, true); |
| 620 paintOpacityGroup(graphicsContext, borderInfo, 0, 1); | 620 paintOpacityGroup(graphicsContext, borderInfo, 0, 1); |
| 621 } | 621 } |
| 622 | 622 |
| 623 // In order to maximize the use of overdraw as a corner seam avoidance technique
, we draw | 623 // In order to maximize the use of overdraw as a corner seam avoidance technique
, we draw |
| 624 // translucent border sides using the following algorithm: | 624 // translucent border sides using the following algorithm: |
| 625 // | 625 // |
| 626 // 1) cluster sides sharing the same opacity into "opacity groups" [ComplexBor
derInfo] | 626 // 1) cluster sides sharing the same opacity into "opacity groups" [ComplexBor
derInfo] |
| (...skipping 28 matching lines...) Expand all Loading... |
| 655 // beginLayer(0.5) // layer for group 2 (effective opacity: 0.5
* 0.5 == 0.25) | 655 // beginLayer(0.5) // layer for group 2 (effective opacity: 0.5
* 0.5 == 0.25) |
| 656 // paintSides(right, left) // paint group 2 | 656 // paintSides(right, left) // paint group 2 |
| 657 // endLayer | 657 // endLayer |
| 658 // paintSides(bottom) // paint group 1 | 658 // paintSides(bottom) // paint group 1 |
| 659 // endLayer | 659 // endLayer |
| 660 // paintSides(top) // paint group 0 | 660 // paintSides(top) // paint group 0 |
| 661 // | 661 // |
| 662 // Note that we're always drawing using opaque paints on top of less-opaque cont
ent - hence | 662 // Note that we're always drawing using opaque paints on top of less-opaque cont
ent - hence |
| 663 // we can use overdraw to mask portions of the previous sides. | 663 // we can use overdraw to mask portions of the previous sides. |
| 664 // | 664 // |
| 665 BorderEdgeFlags BoxBorderPainter::paintOpacityGroup(GraphicsContext* context, | 665 BorderEdgeFlags BoxBorderPainter::paintOpacityGroup(GraphicsContext& context, |
| 666 const ComplexBorderInfo& borderInfo, unsigned index, float effectiveOpacity)
const | 666 const ComplexBorderInfo& borderInfo, unsigned index, float effectiveOpacity)
const |
| 667 { | 667 { |
| 668 ASSERT(effectiveOpacity > 0 && effectiveOpacity <= 1); | 668 ASSERT(effectiveOpacity > 0 && effectiveOpacity <= 1); |
| 669 | 669 |
| 670 const size_t opacityGroupCount = borderInfo.opacityGroups.size(); | 670 const size_t opacityGroupCount = borderInfo.opacityGroups.size(); |
| 671 | 671 |
| 672 // For overdraw logic purposes, treat missing/transparent edges as completed
. | 672 // For overdraw logic purposes, treat missing/transparent edges as completed
. |
| 673 if (index >= opacityGroupCount) | 673 if (index >= opacityGroupCount) |
| 674 return ~m_visibleEdgeSet; | 674 return ~m_visibleEdgeSet; |
| 675 | 675 |
| 676 // Groups are sorted in increasing opacity order, but we need to create laye
rs in | 676 // Groups are sorted in increasing opacity order, but we need to create laye
rs in |
| 677 // decreasing opacity order - hence the reverse iteration. | 677 // decreasing opacity order - hence the reverse iteration. |
| 678 const OpacityGroup& group = borderInfo.opacityGroups[opacityGroupCount - ind
ex - 1]; | 678 const OpacityGroup& group = borderInfo.opacityGroups[opacityGroupCount - ind
ex - 1]; |
| 679 | 679 |
| 680 // Adjust this group's paint opacity to account for ancestor transparency la
yers | 680 // Adjust this group's paint opacity to account for ancestor transparency la
yers |
| 681 // (needed in case we avoid creating a layer below). | 681 // (needed in case we avoid creating a layer below). |
| 682 unsigned paintAlpha = group.alpha / effectiveOpacity; | 682 unsigned paintAlpha = group.alpha / effectiveOpacity; |
| 683 ASSERT(paintAlpha <= 255); | 683 ASSERT(paintAlpha <= 255); |
| 684 | 684 |
| 685 // For the last (bottom) group, we can skip the layer even in the presence o
f opacity iff | 685 // For the last (bottom) group, we can skip the layer even in the presence o
f opacity iff |
| 686 // it contains no adjecent edges (no in-group overdraw possibility). | 686 // it contains no adjecent edges (no in-group overdraw possibility). |
| 687 bool needsLayer = group.alpha != 255 | 687 bool needsLayer = group.alpha != 255 |
| 688 && (includesAdjacentEdges(group.edgeFlags) || (index + 1 < borderInfo.op
acityGroups.size())); | 688 && (includesAdjacentEdges(group.edgeFlags) || (index + 1 < borderInfo.op
acityGroups.size())); |
| 689 | 689 |
| 690 if (needsLayer) { | 690 if (needsLayer) { |
| 691 const float groupOpacity = static_cast<float>(group.alpha) / 255; | 691 const float groupOpacity = static_cast<float>(group.alpha) / 255; |
| 692 ASSERT(groupOpacity < effectiveOpacity); | 692 ASSERT(groupOpacity < effectiveOpacity); |
| 693 | 693 |
| 694 context->beginLayer(groupOpacity / effectiveOpacity); | 694 context.beginLayer(groupOpacity / effectiveOpacity); |
| 695 effectiveOpacity = groupOpacity; | 695 effectiveOpacity = groupOpacity; |
| 696 | 696 |
| 697 // Group opacity is applied via a layer => we draw the members using opa
que paint. | 697 // Group opacity is applied via a layer => we draw the members using opa
que paint. |
| 698 paintAlpha = 255; | 698 paintAlpha = 255; |
| 699 } | 699 } |
| 700 | 700 |
| 701 // Recursion may seem unpalatable here, but | 701 // Recursion may seem unpalatable here, but |
| 702 // a) it has an upper bound of 4 | 702 // a) it has an upper bound of 4 |
| 703 // b) only triggers at all when mixing border sides with different opaciti
es | 703 // b) only triggers at all when mixing border sides with different opaciti
es |
| 704 // c) it allows us to express the layer nesting algorithm more naturally | 704 // c) it allows us to express the layer nesting algorithm more naturally |
| 705 BorderEdgeFlags completedEdges = paintOpacityGroup(context, borderInfo, inde
x + 1, effectiveOpacity); | 705 BorderEdgeFlags completedEdges = paintOpacityGroup(context, borderInfo, inde
x + 1, effectiveOpacity); |
| 706 | 706 |
| 707 // Paint the actual group edges with an alpha adjusted to account for ancens
tor layers opacity. | 707 // Paint the actual group edges with an alpha adjusted to account for ancens
tor layers opacity. |
| 708 for (BoxSide side : group.sides) { | 708 for (BoxSide side : group.sides) { |
| 709 paintSide(context, borderInfo, side, paintAlpha, completedEdges); | 709 paintSide(context, borderInfo, side, paintAlpha, completedEdges); |
| 710 completedEdges |= edgeFlagForSide(side); | 710 completedEdges |= edgeFlagForSide(side); |
| 711 } | 711 } |
| 712 | 712 |
| 713 if (needsLayer) | 713 if (needsLayer) |
| 714 context->endLayer(); | 714 context.endLayer(); |
| 715 | 715 |
| 716 return completedEdges; | 716 return completedEdges; |
| 717 } | 717 } |
| 718 | 718 |
| 719 void BoxBorderPainter::paintSide(GraphicsContext* context, const ComplexBorderIn
fo& borderInfo, | 719 void BoxBorderPainter::paintSide(GraphicsContext& context, const ComplexBorderIn
fo& borderInfo, |
| 720 BoxSide side, unsigned alpha, BorderEdgeFlags completedEdges) const | 720 BoxSide side, unsigned alpha, BorderEdgeFlags completedEdges) const |
| 721 { | 721 { |
| 722 const BorderEdge& edge = m_edges[side]; | 722 const BorderEdge& edge = m_edges[side]; |
| 723 ASSERT(edge.shouldRender()); | 723 ASSERT(edge.shouldRender()); |
| 724 const Color color(edge.color.red(), edge.color.green(), edge.color.blue(), a
lpha); | 724 const Color color(edge.color.red(), edge.color.green(), edge.color.blue(), a
lpha); |
| 725 | 725 |
| 726 FloatRect sideRect = m_outer.rect(); | 726 FloatRect sideRect = m_outer.rect(); |
| 727 const Path* path = nullptr; | 727 const Path* path = nullptr; |
| 728 | 728 |
| 729 // TODO(fmalita): find a way to consolidate these without sacrificing readab
ility. | 729 // TODO(fmalita): find a way to consolidate these without sacrificing readab
ility. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 ? miter1 == HardMiter || miter2 == HardMiter | 815 ? miter1 == HardMiter || miter2 == HardMiter |
| 816 : miter1 == SoftMiter || miter2 == SoftMiter; | 816 : miter1 == SoftMiter || miter2 == SoftMiter; |
| 817 | 817 |
| 818 // Some styles require clipping for any type of miter. | 818 // Some styles require clipping for any type of miter. |
| 819 shouldClip = shouldClip | 819 shouldClip = shouldClip |
| 820 || ((miter1 != NoMiter || miter2 != NoMiter) && styleRequiresClipPolygon
(style)); | 820 || ((miter1 != NoMiter || miter2 != NoMiter) && styleRequiresClipPolygon
(style)); |
| 821 | 821 |
| 822 return shouldClip; | 822 return shouldClip; |
| 823 } | 823 } |
| 824 | 824 |
| 825 void BoxBorderPainter::paintOneBorderSide(GraphicsContext* graphicsContext, | 825 void BoxBorderPainter::paintOneBorderSide(GraphicsContext& graphicsContext, |
| 826 const FloatRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adja
centSide2, | 826 const FloatRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adja
centSide2, |
| 827 const Path* path, bool antialias, Color color, BorderEdgeFlags completedEdge
s) const | 827 const Path* path, bool antialias, Color color, BorderEdgeFlags completedEdge
s) const |
| 828 { | 828 { |
| 829 const BorderEdge& edgeToRender = m_edges[side]; | 829 const BorderEdge& edgeToRender = m_edges[side]; |
| 830 ASSERT(edgeToRender.width); | 830 ASSERT(edgeToRender.width); |
| 831 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1]; | 831 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1]; |
| 832 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2]; | 832 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2]; |
| 833 | 833 |
| 834 if (path) { | 834 if (path) { |
| 835 MiterType miter1 = colorsMatchAtCorner(side, adjacentSide1, m_edges) ? H
ardMiter : SoftMiter; | 835 MiterType miter1 = colorsMatchAtCorner(side, adjacentSide1, m_edges) ? H
ardMiter : SoftMiter; |
| 836 MiterType miter2 = colorsMatchAtCorner(side, adjacentSide2, m_edges) ? H
ardMiter : SoftMiter; | 836 MiterType miter2 = colorsMatchAtCorner(side, adjacentSide2, m_edges) ? H
ardMiter : SoftMiter; |
| 837 | 837 |
| 838 GraphicsContextStateSaver stateSaver(*graphicsContext); | 838 GraphicsContextStateSaver stateSaver(graphicsContext); |
| 839 if (m_inner.isRenderable()) | 839 if (m_inner.isRenderable()) |
| 840 clipBorderSidePolygon(graphicsContext, side, miter1, miter2); | 840 clipBorderSidePolygon(graphicsContext, side, miter1, miter2); |
| 841 else | 841 else |
| 842 clipBorderSideForComplexInnerPath(graphicsContext, side); | 842 clipBorderSideForComplexInnerPath(graphicsContext, side); |
| 843 float thickness = std::max(std::max(edgeToRender.width, adjacentEdge1.wi
dth), adjacentEdge2.width); | 843 float thickness = std::max(std::max(edgeToRender.width, adjacentEdge1.wi
dth), adjacentEdge2.width); |
| 844 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path,
edgeToRender.width, | 844 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path,
edgeToRender.width, |
| 845 thickness, side, color, edgeToRender.borderStyle()); | 845 thickness, side, color, edgeToRender.borderStyle()); |
| 846 } else { | 846 } else { |
| 847 MiterType miter1 = computeMiter(side, adjacentSide1, completedEdges, ant
ialias); | 847 MiterType miter1 = computeMiter(side, adjacentSide1, completedEdges, ant
ialias); |
| 848 MiterType miter2 = computeMiter(side, adjacentSide2, completedEdges, ant
ialias); | 848 MiterType miter2 = computeMiter(side, adjacentSide2, completedEdges, ant
ialias); |
| 849 bool shouldClip = mitersRequireClipping(miter1, miter2, edgeToRender.bor
derStyle(), antialias); | 849 bool shouldClip = mitersRequireClipping(miter1, miter2, edgeToRender.bor
derStyle(), antialias); |
| 850 | 850 |
| 851 GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip); | 851 GraphicsContextStateSaver clipStateSaver(graphicsContext, shouldClip); |
| 852 if (shouldClip) { | 852 if (shouldClip) { |
| 853 clipBorderSidePolygon(graphicsContext, side, miter1, miter2); | 853 clipBorderSidePolygon(graphicsContext, side, miter1, miter2); |
| 854 | 854 |
| 855 // Miters are applied via clipping, no need to draw them. | 855 // Miters are applied via clipping, no need to draw them. |
| 856 miter1 = miter2 = NoMiter; | 856 miter1 = miter2 = NoMiter; |
| 857 } | 857 } |
| 858 | 858 |
| 859 ObjectPainter::drawLineForBoxSide(graphicsContext, sideRect.x(), sideRec
t.y(), | 859 ObjectPainter::drawLineForBoxSide(graphicsContext, sideRect.x(), sideRec
t.y(), |
| 860 sideRect.maxX(), sideRect.maxY(), side, color, edgeToRender.borderSt
yle(), | 860 sideRect.maxX(), sideRect.maxY(), side, color, edgeToRender.borderSt
yle(), |
| 861 miter1 != NoMiter ? adjacentEdge1.width : 0, miter2 != NoMiter ? adj
acentEdge2.width : 0, | 861 miter1 != NoMiter ? adjacentEdge1.width : 0, miter2 != NoMiter ? adj
acentEdge2.width : 0, |
| 862 antialias); | 862 antialias); |
| 863 } | 863 } |
| 864 } | 864 } |
| 865 | 865 |
| 866 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext* graphicsContext, | 866 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext& graphicsContext, |
| 867 const LayoutRect& borderRect, const Path& borderPath, float thickness, float
drawThickness, | 867 const LayoutRect& borderRect, const Path& borderPath, float thickness, float
drawThickness, |
| 868 BoxSide side, Color color, EBorderStyle borderStyle) const | 868 BoxSide side, Color color, EBorderStyle borderStyle) const |
| 869 { | 869 { |
| 870 if (thickness <= 0) | 870 if (thickness <= 0) |
| 871 return; | 871 return; |
| 872 | 872 |
| 873 if (borderStyle == DOUBLE && thickness < 3) | 873 if (borderStyle == DOUBLE && thickness < 3) |
| 874 borderStyle = SOLID; | 874 borderStyle = SOLID; |
| 875 | 875 |
| 876 switch (borderStyle) { | 876 switch (borderStyle) { |
| 877 case BNONE: | 877 case BNONE: |
| 878 case BHIDDEN: | 878 case BHIDDEN: |
| 879 return; | 879 return; |
| 880 case DOTTED: | 880 case DOTTED: |
| 881 case DASHED: { | 881 case DASHED: { |
| 882 graphicsContext->setStrokeColor(color); | 882 graphicsContext.setStrokeColor(color); |
| 883 | 883 |
| 884 // The stroke is doubled here because the provided path is the | 884 // The stroke is doubled here because the provided path is the |
| 885 // outside edge of the border so half the stroke is clipped off. | 885 // outside edge of the border so half the stroke is clipped off. |
| 886 // The extra multiplier is so that the clipping mask can antialias | 886 // The extra multiplier is so that the clipping mask can antialias |
| 887 // the edges to prevent jaggies. | 887 // the edges to prevent jaggies. |
| 888 graphicsContext->setStrokeThickness(drawThickness * 2 * 1.1f); | 888 graphicsContext.setStrokeThickness(drawThickness * 2 * 1.1f); |
| 889 graphicsContext->setStrokeStyle(borderStyle == DASHED ? DashedStroke : D
ottedStroke); | 889 graphicsContext.setStrokeStyle(borderStyle == DASHED ? DashedStroke : Do
ttedStroke); |
| 890 | 890 |
| 891 // If the number of dashes that fit in the path is odd and non-integral
then we | 891 // If the number of dashes that fit in the path is odd and non-integral
then we |
| 892 // will have an awkwardly-sized dash at the end of the path. To try to a
void that | 892 // will have an awkwardly-sized dash at the end of the path. To try to a
void that |
| 893 // here, we simply make the whitespace dashes ever so slightly bigger. | 893 // here, we simply make the whitespace dashes ever so slightly bigger. |
| 894 // FIXME: This could be even better if we tried to manipulate the dash o
ffset | 894 // FIXME: This could be even better if we tried to manipulate the dash o
ffset |
| 895 // and possibly the gapLength to get the corners dash-symmetrical. | 895 // and possibly the gapLength to get the corners dash-symmetrical. |
| 896 float dashLength = thickness * ((borderStyle == DASHED) ? 3.0f : 1.0f); | 896 float dashLength = thickness * ((borderStyle == DASHED) ? 3.0f : 1.0f); |
| 897 float gapLength = dashLength; | 897 float gapLength = dashLength; |
| 898 float numberOfDashes = borderPath.length() / dashLength; | 898 float numberOfDashes = borderPath.length() / dashLength; |
| 899 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. | 899 // Don't try to show dashes if we have less than 2 dashes + 2 gaps. |
| 900 // FIXME: should do this test per side. | 900 // FIXME: should do this test per side. |
| 901 if (numberOfDashes >= 4) { | 901 if (numberOfDashes >= 4) { |
| 902 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); | 902 bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); |
| 903 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes
); | 903 bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes
); |
| 904 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { | 904 if (!evenNumberOfFullDashes && !integralNumberOfDashes) { |
| 905 float numberOfGaps = numberOfDashes / 2; | 905 float numberOfGaps = numberOfDashes / 2; |
| 906 gapLength += (dashLength / numberOfGaps); | 906 gapLength += (dashLength / numberOfGaps); |
| 907 } | 907 } |
| 908 | 908 |
| 909 DashArray lineDash; | 909 DashArray lineDash; |
| 910 lineDash.append(dashLength); | 910 lineDash.append(dashLength); |
| 911 lineDash.append(gapLength); | 911 lineDash.append(gapLength); |
| 912 graphicsContext->setLineDash(lineDash, dashLength); | 912 graphicsContext.setLineDash(lineDash, dashLength); |
| 913 } | 913 } |
| 914 | 914 |
| 915 // FIXME: stroking the border path causes issues with tight corners: | 915 // FIXME: stroking the border path causes issues with tight corners: |
| 916 // https://bugs.webkit.org/show_bug.cgi?id=58711 | 916 // https://bugs.webkit.org/show_bug.cgi?id=58711 |
| 917 // Also, to get the best appearance we should stroke a path between the
two borders. | 917 // Also, to get the best appearance we should stroke a path between the
two borders. |
| 918 graphicsContext->strokePath(borderPath); | 918 graphicsContext.strokePath(borderPath); |
| 919 return; | 919 return; |
| 920 } | 920 } |
| 921 case DOUBLE: { | 921 case DOUBLE: { |
| 922 // Draw inner border line | 922 // Draw inner border line |
| 923 { | 923 { |
| 924 GraphicsContextStateSaver stateSaver(*graphicsContext); | 924 GraphicsContextStateSaver stateSaver(graphicsContext); |
| 925 const LayoutRectOutsets innerInsets = doubleStripeInsets(m_edges, Bo
rderEdge::DoubleBorderStripeInner); | 925 const LayoutRectOutsets innerInsets = doubleStripeInsets(m_edges, Bo
rderEdge::DoubleBorderStripeInner); |
| 926 FloatRoundedRect innerClip = m_style.getRoundedInnerBorderFor(border
Rect, innerInsets, | 926 FloatRoundedRect innerClip = m_style.getRoundedInnerBorderFor(border
Rect, innerInsets, |
| 927 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); | 927 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); |
| 928 | 928 |
| 929 graphicsContext->clipRoundedRect(innerClip); | 929 graphicsContext.clipRoundedRect(innerClip); |
| 930 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickne
ss, drawThickness, | 930 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickne
ss, drawThickness, |
| 931 side, color, SOLID); | 931 side, color, SOLID); |
| 932 } | 932 } |
| 933 | 933 |
| 934 // Draw outer border line | 934 // Draw outer border line |
| 935 { | 935 { |
| 936 GraphicsContextStateSaver stateSaver(*graphicsContext); | 936 GraphicsContextStateSaver stateSaver(graphicsContext); |
| 937 LayoutRect outerRect = borderRect; | 937 LayoutRect outerRect = borderRect; |
| 938 LayoutRectOutsets outerInsets = doubleStripeInsets(m_edges, BorderEd
ge::DoubleBorderStripeOuter); | 938 LayoutRectOutsets outerInsets = doubleStripeInsets(m_edges, BorderEd
ge::DoubleBorderStripeOuter); |
| 939 | 939 |
| 940 if (bleedAvoidanceIsClipping(m_bleedAvoidance)) { | 940 if (bleedAvoidanceIsClipping(m_bleedAvoidance)) { |
| 941 outerRect.inflate(1); | 941 outerRect.inflate(1); |
| 942 outerInsets.setTop(outerInsets.top() - 1); | 942 outerInsets.setTop(outerInsets.top() - 1); |
| 943 outerInsets.setRight(outerInsets.right() - 1); | 943 outerInsets.setRight(outerInsets.right() - 1); |
| 944 outerInsets.setBottom(outerInsets.bottom() - 1); | 944 outerInsets.setBottom(outerInsets.bottom() - 1); |
| 945 outerInsets.setLeft(outerInsets.left() - 1); | 945 outerInsets.setLeft(outerInsets.left() - 1); |
| 946 } | 946 } |
| 947 | 947 |
| 948 FloatRoundedRect outerClip = m_style.getRoundedInnerBorderFor(outerR
ect, outerInsets, | 948 FloatRoundedRect outerClip = m_style.getRoundedInnerBorderFor(outerR
ect, outerInsets, |
| 949 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); | 949 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); |
| 950 graphicsContext->clipOutRoundedRect(outerClip); | 950 graphicsContext.clipOutRoundedRect(outerClip); |
| 951 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickne
ss, drawThickness, | 951 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickne
ss, drawThickness, |
| 952 side, color, SOLID); | 952 side, color, SOLID); |
| 953 } | 953 } |
| 954 return; | 954 return; |
| 955 } | 955 } |
| 956 case RIDGE: | 956 case RIDGE: |
| 957 case GROOVE: | 957 case GROOVE: |
| 958 { | 958 { |
| 959 EBorderStyle s1; | 959 EBorderStyle s1; |
| 960 EBorderStyle s2; | 960 EBorderStyle s2; |
| 961 if (borderStyle == GROOVE) { | 961 if (borderStyle == GROOVE) { |
| 962 s1 = INSET; | 962 s1 = INSET; |
| 963 s2 = OUTSET; | 963 s2 = OUTSET; |
| 964 } else { | 964 } else { |
| 965 s1 = OUTSET; | 965 s1 = OUTSET; |
| 966 s2 = INSET; | 966 s2 = INSET; |
| 967 } | 967 } |
| 968 | 968 |
| 969 // Paint full border | 969 // Paint full border |
| 970 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness,
drawThickness, | 970 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness,
drawThickness, |
| 971 side, color, s1); | 971 side, color, s1); |
| 972 | 972 |
| 973 // Paint inner only | 973 // Paint inner only |
| 974 GraphicsContextStateSaver stateSaver(*graphicsContext); | 974 GraphicsContextStateSaver stateSaver(graphicsContext); |
| 975 LayoutUnit topWidth = m_edges[BSTop].usedWidth() / 2; | 975 LayoutUnit topWidth = m_edges[BSTop].usedWidth() / 2; |
| 976 LayoutUnit bottomWidth = m_edges[BSBottom].usedWidth() / 2; | 976 LayoutUnit bottomWidth = m_edges[BSBottom].usedWidth() / 2; |
| 977 LayoutUnit leftWidth = m_edges[BSLeft].usedWidth() / 2; | 977 LayoutUnit leftWidth = m_edges[BSLeft].usedWidth() / 2; |
| 978 LayoutUnit rightWidth = m_edges[BSRight].usedWidth() / 2; | 978 LayoutUnit rightWidth = m_edges[BSRight].usedWidth() / 2; |
| 979 | 979 |
| 980 FloatRoundedRect clipRect = m_style.getRoundedInnerBorderFor(borderRect, | 980 FloatRoundedRect clipRect = m_style.getRoundedInnerBorderFor(borderRect, |
| 981 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth), | 981 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth), |
| 982 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); | 982 m_includeLogicalLeftEdge, m_includeLogicalRightEdge); |
| 983 | 983 |
| 984 graphicsContext->clipRoundedRect(clipRect); | 984 graphicsContext.clipRoundedRect(clipRect); |
| 985 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness,
drawThickness, | 985 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness,
drawThickness, |
| 986 side, color, s2); | 986 side, color, s2); |
| 987 return; | 987 return; |
| 988 } | 988 } |
| 989 case INSET: | 989 case INSET: |
| 990 if (side == BSTop || side == BSLeft) | 990 if (side == BSTop || side == BSLeft) |
| 991 color = color.dark(); | 991 color = color.dark(); |
| 992 break; | 992 break; |
| 993 case OUTSET: | 993 case OUTSET: |
| 994 if (side == BSBottom || side == BSRight) | 994 if (side == BSBottom || side == BSRight) |
| 995 color = color.dark(); | 995 color = color.dark(); |
| 996 break; | 996 break; |
| 997 default: | 997 default: |
| 998 break; | 998 break; |
| 999 } | 999 } |
| 1000 | 1000 |
| 1001 graphicsContext->setStrokeStyle(NoStroke); | 1001 graphicsContext.setStrokeStyle(NoStroke); |
| 1002 graphicsContext->setFillColor(color); | 1002 graphicsContext.setFillColor(color); |
| 1003 graphicsContext->drawRect(pixelSnappedIntRect(borderRect)); | 1003 graphicsContext.drawRect(pixelSnappedIntRect(borderRect)); |
| 1004 } | 1004 } |
| 1005 | 1005 |
| 1006 void BoxBorderPainter::clipBorderSideForComplexInnerPath(GraphicsContext* graphi
csContext, | 1006 void BoxBorderPainter::clipBorderSideForComplexInnerPath(GraphicsContext& graphi
csContext, |
| 1007 BoxSide side) const | 1007 BoxSide side) const |
| 1008 { | 1008 { |
| 1009 graphicsContext->clip(calculateSideRectIncludingInner(m_outer, m_edges, side
)); | 1009 graphicsContext.clip(calculateSideRectIncludingInner(m_outer, m_edges, side)
); |
| 1010 FloatRoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(m_inner, s
ide); | 1010 FloatRoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(m_inner, s
ide); |
| 1011 if (!adjustedInnerRect.isEmpty()) | 1011 if (!adjustedInnerRect.isEmpty()) |
| 1012 graphicsContext->clipOutRoundedRect(adjustedInnerRect); | 1012 graphicsContext.clipOutRoundedRect(adjustedInnerRect); |
| 1013 } | 1013 } |
| 1014 | 1014 |
| 1015 void BoxBorderPainter::clipBorderSidePolygon(GraphicsContext* graphicsContext, B
oxSide side, | 1015 void BoxBorderPainter::clipBorderSidePolygon(GraphicsContext& graphicsContext, B
oxSide side, |
| 1016 MiterType firstMiter, MiterType secondMiter) const | 1016 MiterType firstMiter, MiterType secondMiter) const |
| 1017 { | 1017 { |
| 1018 ASSERT(firstMiter != NoMiter || secondMiter != NoMiter); | 1018 ASSERT(firstMiter != NoMiter || secondMiter != NoMiter); |
| 1019 | 1019 |
| 1020 FloatPoint quad[4]; | 1020 FloatPoint quad[4]; |
| 1021 | 1021 |
| 1022 const LayoutRect outerRect(m_outer.rect()); | 1022 const LayoutRect outerRect(m_outer.rect()); |
| 1023 const LayoutRect innerRect(m_inner.rect()); | 1023 const LayoutRect innerRect(m_inner.rect()); |
| 1024 | 1024 |
| 1025 // For each side, create a quad that encompasses all parts of that side that
may draw, | 1025 // For each side, create a quad that encompasses all parts of that side that
may draw, |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 quad[2].y()), | 1148 quad[2].y()), |
| 1149 FloatPoint( | 1149 FloatPoint( |
| 1150 quad[2].x(), | 1150 quad[2].x(), |
| 1151 quad[2].y() - m_inner.radii().bottomRight().height()), | 1151 quad[2].y() - m_inner.radii().bottomRight().height()), |
| 1152 quad[2]); | 1152 quad[2]); |
| 1153 } | 1153 } |
| 1154 break; | 1154 break; |
| 1155 } | 1155 } |
| 1156 | 1156 |
| 1157 if (firstMiter == secondMiter) { | 1157 if (firstMiter == secondMiter) { |
| 1158 graphicsContext->clipPolygon(4, quad, firstMiter == SoftMiter); | 1158 graphicsContext.clipPolygon(4, quad, firstMiter == SoftMiter); |
| 1159 return; | 1159 return; |
| 1160 } | 1160 } |
| 1161 | 1161 |
| 1162 // If antialiasing settings for the first edge and second edge is different, | 1162 // If antialiasing settings for the first edge and second edge is different, |
| 1163 // they have to be addressed separately. We do this by breaking the quad int
o | 1163 // they have to be addressed separately. We do this by breaking the quad int
o |
| 1164 // two parallelograms, made by moving quad[1] and quad[2]. | 1164 // two parallelograms, made by moving quad[1] and quad[2]. |
| 1165 float ax = quad[1].x() - quad[0].x(); | 1165 float ax = quad[1].x() - quad[0].x(); |
| 1166 float ay = quad[1].y() - quad[0].y(); | 1166 float ay = quad[1].y() - quad[0].y(); |
| 1167 float bx = quad[2].x() - quad[1].x(); | 1167 float bx = quad[2].x() - quad[1].x(); |
| 1168 float by = quad[2].y() - quad[1].y(); | 1168 float by = quad[2].y() - quad[1].y(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1181 r1 = (-ax * by + ay * bx) / (cx * by - cy * bx) + kExtendFill; | 1181 r1 = (-ax * by + ay * bx) / (cx * by - cy * bx) + kExtendFill; |
| 1182 r2 = (-cx * by + cy * bx) / (ax * by - ay * bx) + kExtendFill; | 1182 r2 = (-cx * by + cy * bx) / (ax * by - ay * bx) + kExtendFill; |
| 1183 } | 1183 } |
| 1184 | 1184 |
| 1185 if (firstMiter != NoMiter) { | 1185 if (firstMiter != NoMiter) { |
| 1186 FloatPoint firstQuad[4]; | 1186 FloatPoint firstQuad[4]; |
| 1187 firstQuad[0] = quad[0]; | 1187 firstQuad[0] = quad[0]; |
| 1188 firstQuad[1] = quad[1]; | 1188 firstQuad[1] = quad[1]; |
| 1189 firstQuad[2] = FloatPoint(quad[3].x() + r2 * ax, quad[3].y() + r2 * ay); | 1189 firstQuad[2] = FloatPoint(quad[3].x() + r2 * ax, quad[3].y() + r2 * ay); |
| 1190 firstQuad[3] = quad[3]; | 1190 firstQuad[3] = quad[3]; |
| 1191 graphicsContext->clipPolygon(4, firstQuad, firstMiter == SoftMiter); | 1191 graphicsContext.clipPolygon(4, firstQuad, firstMiter == SoftMiter); |
| 1192 } | 1192 } |
| 1193 | 1193 |
| 1194 if (secondMiter != NoMiter) { | 1194 if (secondMiter != NoMiter) { |
| 1195 FloatPoint secondQuad[4]; | 1195 FloatPoint secondQuad[4]; |
| 1196 secondQuad[0] = quad[0]; | 1196 secondQuad[0] = quad[0]; |
| 1197 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy)
; | 1197 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy)
; |
| 1198 secondQuad[2] = quad[2]; | 1198 secondQuad[2] = quad[2]; |
| 1199 secondQuad[3] = quad[3]; | 1199 secondQuad[3] = quad[3]; |
| 1200 graphicsContext->clipPolygon(4, secondQuad, secondMiter == SoftMiter); | 1200 graphicsContext.clipPolygon(4, secondQuad, secondMiter == SoftMiter); |
| 1201 } | 1201 } |
| 1202 } | 1202 } |
| 1203 | 1203 |
| 1204 } // namespace blink | 1204 } // namespace blink |
| OLD | NEW |