diff options
Diffstat (limited to 'Source/WebCore/rendering/shapes/BoxShape.cpp')
-rw-r--r-- | Source/WebCore/rendering/shapes/BoxShape.cpp | 161 |
1 files changed, 77 insertions, 84 deletions
diff --git a/Source/WebCore/rendering/shapes/BoxShape.cpp b/Source/WebCore/rendering/shapes/BoxShape.cpp index 25c966875..dba19e76f 100644 --- a/Source/WebCore/rendering/shapes/BoxShape.cpp +++ b/Source/WebCore/rendering/shapes/BoxShape.cpp @@ -12,7 +12,7 @@ * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -30,10 +30,70 @@ #include "config.h" #include "BoxShape.h" +#include "RenderBox.h" #include <wtf/MathExtras.h> namespace WebCore { +static inline LayoutUnit adjustRadiusForMarginBoxShape(LayoutUnit radius, LayoutUnit margin) +{ + // This algorithm is defined in the CSS Shapes specifcation + if (!margin) + return radius; + + LayoutUnit ratio = radius / margin; + if (ratio < 1) + return radius + (margin * (1 + pow(ratio - 1, 3.0))); + + return radius + margin; +} + +static inline LayoutSize computeMarginBoxShapeRadius(const LayoutSize& radius, const LayoutSize& adjacentMargins) +{ + return LayoutSize(adjustRadiusForMarginBoxShape(radius.width(), adjacentMargins.width()), + adjustRadiusForMarginBoxShape(radius.height(), adjacentMargins.height())); +} + +static inline RoundedRect::Radii computeMarginBoxShapeRadii(const RoundedRect::Radii& radii, const RenderBox& renderer) +{ + return RoundedRect::Radii(computeMarginBoxShapeRadius(radii.topLeft(), LayoutSize(renderer.marginLeft(), renderer.marginTop())), + computeMarginBoxShapeRadius(radii.topRight(), LayoutSize(renderer.marginRight(), renderer.marginTop())), + computeMarginBoxShapeRadius(radii.bottomLeft(), LayoutSize(renderer.marginLeft(), renderer.marginBottom())), + computeMarginBoxShapeRadius(radii.bottomRight(), LayoutSize(renderer.marginRight(), renderer.marginBottom()))); +} + +RoundedRect computeRoundedRectForBoxShape(CSSBoxType box, const RenderBox& renderer) +{ + const RenderStyle& style = renderer.style(); + switch (box) { + case MarginBox: { + if (!style.hasBorderRadius()) + return RoundedRect(renderer.marginBoxRect(), RoundedRect::Radii()); + + LayoutRect marginBox = renderer.marginBoxRect(); + RoundedRect::Radii radii = computeMarginBoxShapeRadii(style.getRoundedBorderFor(renderer.borderBoxRect()).radii(), renderer); + radii.scale(calcBorderRadiiConstraintScaleFor(marginBox, radii)); + return RoundedRect(marginBox, radii); + } + case PaddingBox: + return style.getRoundedInnerBorderFor(renderer.borderBoxRect()); + case ContentBox: + return style.getRoundedInnerBorderFor(renderer.borderBoxRect(), + renderer.paddingTop() + renderer.borderTop(), renderer.paddingBottom() + renderer.borderBottom(), + renderer.paddingLeft() + renderer.borderLeft(), renderer.paddingRight() + renderer.borderRight()); + // fill, stroke, view-box compute to border-box for HTML elements. + case BorderBox: + case Fill: + case Stroke: + case ViewBox: + case BoxMissing: + return style.getRoundedBorderFor(renderer.borderBoxRect()); + } + + ASSERT_NOT_REACHED(); + return style.getRoundedBorderFor(renderer.borderBoxRect()); +} + LayoutRect BoxShape::shapeMarginLogicalBoundingBox() const { FloatRect marginBounds(m_bounds.rect()); @@ -42,14 +102,6 @@ LayoutRect BoxShape::shapeMarginLogicalBoundingBox() const return static_cast<LayoutRect>(marginBounds); } -LayoutRect BoxShape::shapePaddingLogicalBoundingBox() const -{ - FloatRect paddingBounds(m_bounds.rect()); - if (shapePadding() > 0) - paddingBounds.inflate(-shapePadding()); - return static_cast<LayoutRect>(paddingBounds); -} - FloatRoundedRect BoxShape::shapeMarginBounds() const { FloatRoundedRect marginBounds(m_bounds); @@ -60,44 +112,36 @@ FloatRoundedRect BoxShape::shapeMarginBounds() const return marginBounds; } -FloatRoundedRect BoxShape::shapePaddingBounds() const -{ - FloatRoundedRect paddingBounds(m_bounds); - if (shapePadding() > 0) { - paddingBounds.inflate(-shapePadding()); - paddingBounds.expandRadii(-shapePadding()); - } - return paddingBounds; -} - -void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const +LineSegment BoxShape::getExcludedInterval(LayoutUnit logicalTop, LayoutUnit logicalHeight) const { const FloatRoundedRect& marginBounds = shapeMarginBounds(); if (marginBounds.isEmpty() || !lineOverlapsShapeMarginBounds(logicalTop, logicalHeight)) - return; + return LineSegment(); float y1 = logicalTop; float y2 = logicalTop + logicalHeight; const FloatRect& rect = marginBounds.rect(); - if (!marginBounds.isRounded()) { - result.append(LineSegment(rect.x(), rect.maxX())); - return; - } + if (!marginBounds.isRounded()) + return LineSegment(rect.x(), rect.maxX()); float topCornerMaxY = std::max<float>(marginBounds.topLeftCorner().maxY(), marginBounds.topRightCorner().maxY()); float bottomCornerMinY = std::min<float>(marginBounds.bottomLeftCorner().y(), marginBounds.bottomRightCorner().y()); - if (y1 <= topCornerMaxY && y2 >= bottomCornerMinY) { - result.append(LineSegment(rect.x(), rect.maxX())); - return; - } + if (topCornerMaxY <= bottomCornerMinY && y1 <= topCornerMaxY && y2 >= bottomCornerMinY) + return LineSegment(rect.x(), rect.maxX()); float x1 = rect.maxX(); float x2 = rect.x(); float minXIntercept; float maxXIntercept; + if (y1 <= marginBounds.topLeftCorner().maxY() && y2 >= marginBounds.bottomLeftCorner().y()) + x1 = rect.x(); + + if (y1 <= marginBounds.topRightCorner().maxY() && y2 >= marginBounds.bottomRightCorner().y()) + x2 = rect.maxX(); + if (marginBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) { x1 = std::min<float>(x1, minXIntercept); x2 = std::max<float>(x2, maxXIntercept); @@ -109,65 +153,14 @@ void BoxShape::getExcludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHei } ASSERT(x2 >= x1); - result.append(LineSegment(x1, x2)); -} - -void BoxShape::getIncludedIntervals(LayoutUnit logicalTop, LayoutUnit logicalHeight, SegmentList& result) const -{ - const FloatRoundedRect& paddingBounds = shapePaddingBounds(); - if (paddingBounds.isEmpty()) - return; - - const FloatRect& rect = paddingBounds.rect(); - float y1 = logicalTop; - float y2 = logicalTop + logicalHeight; - - if (y1 < rect.y() || y2 > rect.maxY()) - return; - - if (!paddingBounds.isRounded()) { - result.append(LineSegment(rect.x(), rect.maxX())); - return; - } - - float x1 = rect.x(); - float x2 = rect.maxX(); - float minXIntercept; - float maxXIntercept; - - if (paddingBounds.xInterceptsAtY(y1, minXIntercept, maxXIntercept)) { - x1 = std::max<float>(x1, minXIntercept); - x2 = std::min<float>(x2, maxXIntercept); - } - - if (paddingBounds.xInterceptsAtY(y2, minXIntercept, maxXIntercept)) { - x1 = std::max<float>(x1, minXIntercept); - x2 = std::min<float>(x2, maxXIntercept); - } - - result.append(LineSegment(x1, x2)); -} - -bool BoxShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const FloatSize&, LayoutUnit& result) const -{ - // FIXME: this method is only a stub, https://bugs.webkit.org/show_bug.cgi?id=124606. - - result = minLogicalIntervalTop; - return true; -} - -static void addRoundedRect(Path& path, const FloatRect& rect, const FloatRoundedRect::Radii& radii) -{ - path.addRoundedRect(rect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight(), Path::PreferBezierRoundedRect); + return LineSegment(x1, x2); } void BoxShape::buildDisplayPaths(DisplayPaths& paths) const { - addRoundedRect(paths.shape, m_bounds.rect(), m_bounds.radii()); - if (shapeMargin()) { - const FloatRoundedRect& marginBounds = shapeMarginBounds(); - addRoundedRect(paths.marginShape, marginBounds.rect(), marginBounds.radii()); - } + paths.shape.addRoundedRect(m_bounds, Path::PreferBezierRoundedRect); + if (shapeMargin()) + paths.marginShape.addRoundedRect(shapeMarginBounds(), Path::PreferBezierRoundedRect); } } // namespace WebCore |