Closed Bug 894555 Opened 12 years ago Closed 11 years ago

SVG images do not render correctly when they have extreme viewboxes

Categories

(Core :: SVG, defect)

defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: seth, Unassigned)

References

Details

After bug 600207 and bug 885939, SVG images are no longer rendering correctly when they have extreme viewboxes. It seems that if one dimension of the viewbox is four orders of magnitude or more greater than the other one, we start to see rendering issues. There is a lot of spew to the console about overflow occurring in nsRect.h, but gdb has been uncooperative about letting me break there and so far I haven't been able to track it down. Until this is fixed, the following reftests have been disabled, per bug 885939 part 3: layout/reftests/backgrounds/vector/empty/tall--cover--height.html layout/reftests/backgrounds/vector/empty/tall--cover--width.html layout/reftests/backgrounds/vector/empty/wide--cover--height.html layout/reftests/backgrounds/vector/empty/wide--cover--width.html
[I'm using tall--cover--height.html as a testcase] So per bug 885939 comment 33, if I place a breakpoint in nsSVGOuterSVGFrame::BuildDisplayList and dump the frame tree, the "SVGPathGeometry(rect)" frame has width=1073741824 in a build without bug 885939's patch, but it has width=0 in a build with bug 885939's patch is applied. FRAME DUMP, *WITHOUT* BUG 885939's PATCH: Viewport(-1)@0x7fefb310a420 [view=0x7fefb9a63e10] {0,0,1073741820,46080} [state=000b062000002220] [sc=0x7fefb310a0f8:-moz-viewport]< HTMLScroll(svg)(-1)@0x7fefb310ac40 {0,0,1073741820,46080} [state=000b020000000000] [content=0x7fefbee72840] [sc=0x7fefb310a710:-moz-viewport-scroll]< Canvas(svg)(-1)@0x7fefb310ab30 {0,0,1073741820,46080} [state=000b002000000200] [content=0x7fefbee72840] [sc=0x7fefb310b008:-moz-scrolled-canvas]< SVGOuterSVG(svg)(-1)@0x7fefb310b6a8 {0,0,1073741820,46080} [state=000b060000110000] [content=0x7fefbee72840] [sc=0x7fefb310b3b8]< SVGOuterSVGAnonChild(svg)(-1)@0x7fefb310b858 {0,0,0,0} vis-overflow=0,0,8947849,46080 scr-overflow=0,0,8947849,46080 [state=000b180000010000] [content=0x7fefbee72840] [sc=0x7fefb310b7b8:-moz-svg-outer-svg-anon-child]< SVGPathGeometry(rect)(3)@0x7fefb310bd68 {0,0,1073741824,60} vis-overflow=0,0,8947849,46080 scr-overflow=0,0,8947849,46080 [state=0001084000010000] transformed [content=0x7fefbbb82f80] [sc=0x7fefb310bb70] > > > > > FRAME DUMP, *WITH* BUG 885939's PATCH: Viewport(-1)@0x7fe77100a420 [view=0x7fe76fade390] {0,0,480,46080} [state=000b062000002220] [sc=0x7fe77100a0f8:-moz-viewport]< HTMLScroll(svg)(-1)@0x7fe77100ac40 {0,0,480,46080} [state=000b020000000000] [content=0x7fe772c28f00] [sc=0x7fe77100a710:-moz-viewport-scroll]< Canvas(svg)(-1)@0x7fe77100ab30 {0,0,480,46080} [state=000b002000000200] [content=0x7fe772c28f00] [sc=0x7fe77100b008:-moz-scrolled-canvas]< SVGOuterSVG(svg)(-1)@0x7fe77100b6a8 {0,0,480,46080} [state=000b060000110000] [content=0x7fe772c28f00] [sc=0x7fe77100b3b8]< SVGOuterSVGAnonChild(svg)(-1)@0x7fe77100b858 {0,0,0,0} vis-overflow=0,0,0,46080 scr-overflow=0,0,0,46080 [state=000b180000010000] [content=0x7fe772c28f00] [sc=0x7fe77100b7b8:-moz-svg-outer-svg-anon-child]< SVGPathGeometry(rect)(3)@0x7fe77100bd68 {0,0,0,60} vis-overflow=0,0,0,46080 scr-overflow=0,0,0,46080 [state=0001080000010000] transformed [content=0x7fe7709768c0] [sc=0x7fe77100bb70] > > > > >
So in nsSVGPathGeometryFrame's size is determined in its ReflowSVG() method. In that method, without the patch, I get scaleFactors = <mozilla::gfx::BaseSize<double, gfxSize>> = { width = 0.0083333337679505348, height = 768 } ...whereas with the patch, I get scaleFactors = <mozilla::gfx::BaseSize<double, gfxSize>> = { width = 3.7252902984619141e-09, height = 768 } (note the huge difference in magnitude between "width" there). That means that with the patch, when we hit this chunk... >308 bool applyScaling = fabs(scaleFactors.width) >= 1e-6 && >309 fabs(scaleFactors.height) >= 1e-6; http://mxr.mozilla.org/mozilla-central/source/layout/svg/nsSVGPathGeometryFrame.cpp#308 ...we set applyScaling to **false**. This prevents us from scaling up the floating-point value 'extent.width' before we clamp it to integer app units. So it ends up being clamped from something tiny to 0 app units. This is the most proximate source of the zero width that I called out in my previous comment. It's not the whole story, because even if I force applyScaling to true (and end up with a nonzero-width SVGPathGeometryFrame), I still get nothing painted in a build with the patch applied. But it at least demonstrates one of the places where these testcases' edge-casey behavior ends up triggering a separate throw-up-our-hands code-path.
1e-6 is just an arbitrary figure to avoid divide by zero. Maybe we should clamp the scaling of the image earlier though so if it's really big in width or height then we accept some pixellation?
The scaleFactors code was removed some time ago.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.