diff options
Diffstat (limited to 'third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp')
-rw-r--r-- | third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp | 100 |
1 files changed, 40 insertions, 60 deletions
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp index 5d69308..3ed6613 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp @@ -59,63 +59,53 @@ struct SearchCandidate { float candidateDistance; }; -static inline LayoutRect adjustedEnclosingIntRect(const FloatRect& rect, - const AffineTransform& rootTransform, float strokeWidthForHairlinePadding) -{ - FloatRect adjustedRect = rect; - - if (strokeWidthForHairlinePadding) { - // For hairline strokes (stroke-width < 1 in device space), Skia rasterizes up to 0.4(9) off - // the stroke center. That means enclosingIntRect is not enough - we must also pad to 0.5. - // This is still fragile as it misses out on CC/DSF CTM components. - const FloatSize strokeSize = rootTransform.mapSize( - FloatSize(strokeWidthForHairlinePadding, strokeWidthForHairlinePadding)); - if (strokeSize.width() < 1 || strokeSize.height() < 1) { - const float pad = 0.5f - std::min(strokeSize.width(), strokeSize.height()) / 2; - ASSERT(pad > 0); - adjustedRect.inflate(pad); - } - } - - if (adjustedRect.isEmpty()) - return LayoutRect(); - - return LayoutRect(enclosingIntRect(adjustedRect)); -} - -LayoutRect SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(const LayoutObject& object, - const LayoutBoxModelObject* paintInvalidationContainer, - const PaintInvalidationState* paintInvalidationState, float strokeWidthForHairlinePadding) +FloatRect SVGLayoutSupport::localOverflowRectForPaintInvalidation(const LayoutObject& object) { + // This doesn't apply to LayoutSVGRoot. Use LayoutSVGRoot::localOverflowRectForPaintInvalidation() instead. + ASSERT(!object.isSVGRoot()); + // Return early for any cases where we don't actually paint if (object.styleRef().visibility() != VISIBLE && !object.enclosingLayer()->hasVisibleContent()) - return LayoutRect(); + return FloatRect(); FloatRect paintInvalidationRect = object.paintInvalidationRectInLocalSVGCoordinates(); if (int outlineOutset = object.styleRef().outlineOutsetExtent()) paintInvalidationRect.inflate(outlineOutset); + return paintInvalidationRect; +} - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(paintInvalidationContainer)) { - // Compute accumulated SVG transform and apply to local paint rect. - AffineTransform transform = paintInvalidationState->svgTransform() * object.localToSVGParentTransform(); - - // FIXME: These are quirks carried forward from the old paint invalidation infrastructure. - LayoutRect rect = adjustedEnclosingIntRect(transform.mapRect(paintInvalidationRect), - transform, strokeWidthForHairlinePadding); - // Offset by SVG root paint offset and apply clipping as needed. - rect.move(paintInvalidationState->paintOffset()); - if (paintInvalidationState->isClipped()) - rect.intersect(paintInvalidationState->clipRect()); - return rect; - } - +LayoutRect SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(const LayoutObject& object, const LayoutBoxModelObject& paintInvalidationContainer) +{ LayoutRect rect; - const LayoutSVGRoot& svgRoot = mapRectToSVGRootForPaintInvalidation(object, - paintInvalidationRect, rect, strokeWidthForHairlinePadding); - svgRoot.mapToVisibleRectInAncestorSpace(paintInvalidationContainer, rect, nullptr); + mapToVisibleRectInAncestorSpace(object, &paintInvalidationContainer, localOverflowRectForPaintInvalidation(object), rect); return rect; } +LayoutRect SVGLayoutSupport::transformPaintInvalidationRect(const LayoutObject& object, const AffineTransform& rootTransform, const FloatRect& localRect) +{ + FloatRect adjustedRect = rootTransform.mapRect(localRect); + + if (object.isSVGShape() && object.styleRef().svgStyle().hasStroke()) { + if (float strokeWidthForHairlinePadding = toLayoutSVGShape(object).strokeWidth()) { + // For hairline strokes (stroke-width < 1 in device space), Skia rasterizes up to 0.4(9) off + // the stroke center. That means enclosingIntRect is not enough - we must also pad to 0.5. + // This is still fragile as it misses out on CC/DSF CTM components. + const FloatSize strokeSize = rootTransform.mapSize( + FloatSize(strokeWidthForHairlinePadding, strokeWidthForHairlinePadding)); + if (strokeSize.width() < 1 || strokeSize.height() < 1) { + const float pad = 0.5f - std::min(strokeSize.width(), strokeSize.height()) / 2; + ASSERT(pad > 0); + adjustedRect.inflate(pad); + } + } + } + + if (adjustedRect.isEmpty()) + return LayoutRect(); + + return LayoutRect(enclosingIntRect(adjustedRect)); +} + static const LayoutSVGRoot& computeTransformToSVGRoot(const LayoutObject& object, AffineTransform& rootBorderBoxTransform) { ASSERT(object.isSVG() && !object.isSVGRoot()); @@ -129,28 +119,18 @@ static const LayoutSVGRoot& computeTransformToSVGRoot(const LayoutObject& object return svgRoot; } -const LayoutSVGRoot& SVGLayoutSupport::mapRectToSVGRootForPaintInvalidation(const LayoutObject& object, - const FloatRect& localPaintInvalidationRect, LayoutRect& rect, float strokeWidthForHairlinePadding) +bool SVGLayoutSupport::mapToVisibleRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject* ancestor, const FloatRect& localPaintInvalidationRect, LayoutRect& resultRect, VisibleRectFlags visibleRectFlags) { AffineTransform rootBorderBoxTransform; const LayoutSVGRoot& svgRoot = computeTransformToSVGRoot(object, rootBorderBoxTransform); - - rect = adjustedEnclosingIntRect(rootBorderBoxTransform.mapRect(localPaintInvalidationRect), - rootBorderBoxTransform, strokeWidthForHairlinePadding); - return svgRoot; + resultRect = transformPaintInvalidationRect(object, rootBorderBoxTransform, localPaintInvalidationRect); + return svgRoot.mapToVisibleRectInAncestorSpace(ancestor, resultRect, visibleRectFlags); } -void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const LayoutBoxModelObject* ancestor, TransformState& transformState, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) +void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const LayoutBoxModelObject* ancestor, TransformState& transformState, bool* wasFixed) { transformState.applyTransform(object->localToSVGParentTransform()); - if (paintInvalidationState && paintInvalidationState->canMapToAncestor(ancestor)) { - // |svgTransform| contains localToBorderBoxTransform mentioned below. - transformState.applyTransform(paintInvalidationState->svgTransform()); - transformState.move(paintInvalidationState->paintOffset()); - return; - } - LayoutObject* parent = object->parent(); // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the localToBorderBoxTransform @@ -160,7 +140,7 @@ void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const Layo transformState.applyTransform(toLayoutSVGRoot(parent)->localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; - parent->mapLocalToAncestor(ancestor, transformState, mode, wasFixed, paintInvalidationState); + parent->mapLocalToAncestor(ancestor, transformState, mode, wasFixed); } void SVGLayoutSupport::mapAncestorToLocal(const LayoutObject& object, const LayoutBoxModelObject* ancestor, TransformState& transformState) |