inline SVG image mask not resizing when parent is resized

#41081602 (ex crbug.com/330815) Filed 2013-12-27 Status: New / P3 / S5 Blink>Paint>Invalidation

Summary

When an inline <svg> is resized (its container grows or shrinks), the parts of the graphic painted through an SVG <mask> (and, per a later comment, <clipPath>) can be left at the old size. Everything else in the graphic scales, but the mask region does not -- until something forces a full repaint (for example opening DevTools), after which the mask snaps to the correct size. Using the same SVG as a CSS background-image is unaffected.

pdr@ in 2014: "this mask bug ... I think we're not updating the dependent resources when RenderSVGRoot changes size." schenney@ in 2017: "we get it right once the animation hits the edge of the viewport, and for all time after."

Live reproduction

The container below animates its size continuously (this mirrors the original jsfiddle which used a CSS resize). Watch the masked (green) shape: on affected builds it lags behind / does not track the container while everything around it scales. Click Force repaint to mimic the DevTools workaround.

mask (objectBoundingBox)

clipPath

same SVG as background-image (control - always correct)

Expected: all three cells render identically at every size (left half + a circle, clipped to a circle for the middle cell). Bug: the inline mask / clipPath cells stop tracking the container size.

Minimal markup

<div style="width:120px;height:120px">     <!-- animate width/height -->
  <svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
    <defs>
      <mask id="m" maskContentUnits="userSpaceOnUse">
        <rect width="50" height="100" fill="white"/>
      </mask>
    </defs>
    <rect width="100" height="100" fill="green" mask="url(#m)"/>
  </svg>
</div>

Investigation (M151 / main)

repro target Where the size change is handled

LayoutSVGRoot::LayoutRoot() rebuilds the local-to-border-box transform and, when the content bounds or the viewport change, marks the subtree for paint invalidation and a paint-property update. Effects on individual SVG children are invalidated in LayoutSVGContainer::UpdateAfterSVGLayout() only when the child's own bounding box changed (bbox_changed) or it needs full layout -- a scale-only change does not by itself re-invalidate a child's mask/clip resource.

status on current main

The straightforward inline cases (mask & clipPath, userSpaceOnUse and objectBoundingBox, with and without viewBox) now re-paint correctly on a discrete resize. I verified this with repaint reftests under third_party/blink/web_tests/paint/invalidation/svg/ (and confirmed the harness detects a stale mask via a deliberately-wrong control). The remaining, DevTools-fixable symptom matches a compositor raster-invalidation gap that software reftests do not exercise, which is why this sampler is interactive: open it on the Chrome build you care about (the bug was last re-confirmed on stable 149) and watch the inline cells against the background-image control.

Links

Issue 41081602 · crbug.com/330815 (original)