Bug 26380 - SVG Filters and big sized filterRegions
: SVG Filters and big sized filterRegions
Status: RESOLVED FIXED
: WebKit
SVG
: 528+ (Nightly build)
: PC Mac OS X 10.5
: P2 Normal
Assigned To:
:
:
:
: 26389
  Show dependency treegraph
 
Reported: 2009-06-13 22:35 PST by
Modified: 2009-11-23 09:30 PST (History)


Attachments
big svg filter (5.32 KB, patch)
2009-06-14 11:46 PST, Dirk Schulze
oliver: review-
Review Patch | Details | Formatted Diff | Diff
big svg filter (5.53 KB, patch)
2009-08-04 12:49 PST, Dirk Schulze
no flags Review Patch | Details | Formatted Diff | Diff
clip filter to viewport (4.69 KB, patch)
2009-11-10 10:37 PST, Dirk Schulze
simon.fraser: review-
Review Patch | Details | Formatted Diff | Diff
Testcase with svg inside 3d transform (952 bytes, application/xhtml+xml)
2009-11-10 14:12 PST, Simon Fraser (smfr)
no flags Details
Better testcase (958 bytes, application/xhtml+xml)
2009-11-10 14:20 PST, Simon Fraser (smfr)
no flags Details


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2009-06-13 22:35:36 PST
We need to take care about very big filterRegions and itemSizes of filters. CI has problems with very big image size.
We could clip the filterRegion after a defined maximum size and don't support bigger filters.

Perhaps we can try to scale down the GraphicsContext and limit the size of all ImageBuffers for source input / filter effects. We could transform the filterRegion and itemsize too. But we will see every pixel. The size of every pixel gets bigger on bigger sized filters.
Or we give the CTM of the scaling to every filter effect and transform the context of every filter effect. But many filter effects need pixel manipulation. Don't know if that is a possible way.

Another way is maybe to just draw the visible area. But I don't have experience with that. And what to do on zooming out of the SVG?
------- Comment #1 From 2009-06-14 11:46:11 PST -------
Created an attachment (id=31267) [details]
big svg filter 

This patch uses one of the solutions above. We scale the context down to a predefined maximum size and transform all necessary rects too. Apply the effects and scale back. It seems, that opera and firefox use simular solutions.
I haven't tested it on a mac. We might use a smaller size than 3000x3000. I'll set the review flag when i'am sure.
------- Comment #2 From 2009-06-14 13:10:43 PST -------
(From update of attachment 31267 [details])
works on mac
------- Comment #3 From 2009-06-18 01:52:51 PST -------
(From update of attachment 31267 [details])
Where does the 3000.0f maxSize come from? It looks like it's actually a constant so i believe you actually probably want a static const float kMaxFilterSize = 3000.0f; in the file, rather than scoped to the function.
------- Comment #4 From 2009-08-04 12:49:02 PST -------
Created an attachment (id=34081) [details]
big svg filter

constant for maximum filter size. At ~3000x3000 px a difference at calculating is sensible.
------- Comment #5 From 2009-08-07 12:29:21 PST -------
(From update of attachment 34081 [details])
Seems like this is an aspect ratio scaling problem which we've already solved in other parts of the code.  I wonder if we could just re-use the scaling code instead of writing it again here.
------- Comment #6 From 2009-08-07 13:00:32 PST -------
(In reply to comment #5)
> (From update of attachment 34081 [details] [details])
> Seems like this is an aspect ratio scaling problem which we've already solved
> in other parts of the code.  I wonder if we could just re-use the scaling code
> instead of writing it again here.

where did we solve this problem?
------- Comment #7 From 2009-08-07 13:02:41 PST -------
Certainly SVGPerserveAspectRatio solves this.
------- Comment #8 From 2009-08-07 13:02:59 PST -------
There are probably less-complicated solutions in the Image code too.
------- Comment #9 From 2009-08-08 09:08:37 PST -------
There was also a recent TransformationMatrix::rectToRect call added, but that won't handle aspect ratios for you.
------- Comment #10 From 2009-09-03 00:53:37 PST -------
(From update of attachment 34081 [details])
So this is just about limiting the size of the intermediate buffers?  Doesn't SVG have some sort of attribute to control this kind of thing anyway?
------- Comment #11 From 2009-09-03 05:52:26 PST -------
(In reply to comment #10)
> (From update of attachment 34081 [details] [details])
> So this is just about limiting the size of the intermediate buffers?  Doesn't
> SVG have some sort of attribute to control this kind of thing anyway?

The size of a filter can be as big as you wish. And it is neccessary to limit the size of a buffer, especially if you have many filters. But as far as I know, we don't have attributes or parameters to limit intermediate buffers with context scaling for big filters.

Another point to add limitations here is filterRes. This code can be used to add different resolutions for filters later.

> Certainly SVGPerserveAspectRatio solves this.
I looked at SVGPerserveAspectRatio during some experiments with feImage. It seems to be a bit to complex for this simple scaling of context and image with. I haven't looked at Image yet.
------- Comment #12 From 2009-09-21 14:14:55 PST -------
Won't scaling the graphics context down cause image aliasing artifacts etc?
------- Comment #13 From 2009-09-21 23:03:58 PST -------
(In reply to comment #12)
> Won't scaling the graphics context down cause image aliasing artifacts etc?
Images will loose quality, yes. But a filter size can be as big as you want. And scaling down the context on a pre defined size, makes it possible to calculate filter effects with pixel manipulation in an acceptable time. It makes it possible to draw the effect at all, if the size is bigger than some platform ImageBuffers are able to render.
------- Comment #14 From 2009-10-14 16:25:57 PST -------
So what about this patch? I think we should settle on a solution.
I think we should introduce a maximum limit right now, given the fact you can easily blow up a target PC using a dozen masks at a large size :-)

When filterRes & friends is taken into account, we need to think about a more clever solution, but I'd vote for an initial "sanitization value", scaling larger filters down, yes with loosing quality.

After that I think we can enable SVG Filters as default, so finally pass SVG 1.0, and advertize ourselves as SVG 1.0 fully compilant, see the 'requiredFeatures' feature of SVG viewers.

Anyone with me?
------- Comment #15 From 2009-10-14 16:59:23 PST -------
> Anyone with me?

From an outsider's perspective:  um, yes please! :)
------- Comment #16 From 2009-11-09 23:52:56 PST -------
(From update of attachment 34081 [details])
Clearing review flag. This would just limit the size of the filter surface but not of the effect surfaces.
------- Comment #17 From 2009-11-10 10:37:23 PST -------
Created an attachment (id=42876) [details]
clip filter to viewport

This patch clips the filter and all it's effects to the current viewport. This will limit the filter size to the current viewable window content. I'll upload the test results as soon as I have access to a Mac.
------- Comment #18 From 2009-11-10 10:58:49 PST -------
(From update of attachment 42876 [details])

> Index: WebCore/svg/SVGFilterElement.cpp
> ===================================================================

> @@ -125,6 +127,7 @@ void SVGFilterElement::buildFilter(const
>                                 filterRect.width() * targetRect.width(),
>                                 filterRect.height() * targetRect.height());
>  
> +    m_filter->setViewPort(document()->view()->visibleContentRect());

But is this rect in the same coordinate system as the rest of the filter rects? What if the filter is on a child of a transformed element?

> Index: WebCore/svg/graphics/SVGResourceFilter.cpp
> ===================================================================
> --- WebCore/svg/graphics/SVGResourceFilter.cpp	(revision 50732)
> +++ WebCore/svg/graphics/SVGResourceFilter.cpp	(working copy)
> @@ -63,6 +63,9 @@ void SVGResourceFilter::prepareFilter(Gr
>      FloatRect targetRect = object->objectBoundingBox();
>      m_ownerElement->buildFilter(targetRect);
>  
> +    // clip filterRect to viewPort
> +    m_filterBBox.intersect(m_viewPort);

This isn't going to do the right thing for filtered SVG inside a HTML with CSS 3D transforms; element content that is outside the viewport can be made visible with a rotateY(), for example. And, yes the visible filtered content may be arbitrarily large in that case.

> Index: WebCore/svg/graphics/SVGResourceFilter.h
> ===================================================================
> --- WebCore/svg/graphics/SVGResourceFilter.h	(revision 50732)
> +++ WebCore/svg/graphics/SVGResourceFilter.h	(working copy)
> @@ -65,6 +65,9 @@ public:
>      FloatRect filterBoundingBox() { return m_filterBBox; }
>      void setFilterBoundingBox(const FloatRect& rect) { m_filterBBox = rect; }
>  
> +    IntRect viewPort() { return m_viewPort; }
> +    void setViewPort(const IntRect& rect) { m_viewPort = rect; }

I question the need for these methods, but if you do have them, then viewPort() should be const.
------- Comment #19 From 2009-11-10 11:11:59 PST -------
(In reply to comment #18)
> (From update of attachment 42876 [details] [details])
> But is this rect in the same coordinate system as the rest of the filter rects?
> What if the filter is on a child of a transformed element?
Yes, it's the same coordinate space. I tested it on the W3C test suite, where SVG is embeded to html.
We already use this on pattern and others via clampImageBufferSizeToViewport.

> This isn't going to do the right thing for filtered SVG inside a HTML with CSS
> 3D transforms; element content that is outside the viewport can be made visible
> with a rotateY(), for example. And, yes the visible filtered content may be
> arbitrarily large in that case.
I don't like the idea of activating css transforms for SVG. What happens if we transform an SVG element with <animation>, JS and CSS transform (2D or 3D)?

> I question the need for these methods, but if you do have them, then viewPort()
> should be const.
Ok, viewPort() is not needed atm. setViewPort is needed to get the viewPort in SVGResourceFilter from SVGFilterElement.
------- Comment #20 From 2009-11-10 11:20:40 PST -------
(In reply to comment #19)

> > This isn't going to do the right thing for filtered SVG inside a HTML with CSS
> > 3D transforms; element content that is outside the viewport can be made visible
> > with a rotateY(), for example. And, yes the visible filtered content may be
> > arbitrarily large in that case.
> I don't like the idea of activating css transforms for SVG. What happens if we
> transform an SVG element with <animation>, JS and CSS transform (2D or 3D)?

I'm not talking about CSS transforms on SVG. I'm concerned about SVG inside HTML, where the HTML has 3d transforms.
------- Comment #21 From 2009-11-10 11:47:42 PST -------
(In reply to comment #20)
> (In reply to comment #19)
> 
> > > This isn't going to do the right thing for filtered SVG inside a HTML with CSS
> > > 3D transforms; element content that is outside the viewport can be made visible
> > > with a rotateY(), for example. And, yes the visible filtered content may be
> > > arbitrarily large in that case.
> > I don't like the idea of activating css transforms for SVG. What happens if we
> > transform an SVG element with <animation>, JS and CSS transform (2D or 3D)?
> 
> I'm not talking about CSS transforms on SVG. I'm concerned about SVG inside
> HTML, where the HTML has 3d transforms.
hm. I'm not familiar with 3d transform on CSS, but I made more tests after you comment. The viewPort size of the SVG, will depend on the <object> when you embed a SVG into a HTML. It will get the currently visible size when SVG is the root element (pure SVG).
------- Comment #22 From 2009-11-10 11:49:25 PST -------
(In reply to comment #21)
> The viewPort size of the SVG, will depend on the <object> when you
> embed a SVG into a HTML.
This means, that the viewPort size is the size of the HTML-element <object>.
------- Comment #23 From 2009-11-10 12:01:30 PST -------
(In reply to comment #22)
> (In reply to comment #21)
> > The viewPort size of the SVG, will depend on the <object> when you
> > embed a SVG into a HTML.
> This means, that the viewPort size is the size of the HTML-element <object>.

document()->view()->visibleContentRect() will return the content rect of the HTML document in the case of HTML with nested SVG.
------- Comment #24 From 2009-11-10 12:12:54 PST -------
(In reply to comment #23)
> (In reply to comment #22)
> > (In reply to comment #21)
> > > The viewPort size of the SVG, will depend on the <object> when you
> > > embed a SVG into a HTML.
> > This means, that the viewPort size is the size of the HTML-element <object>.
> 
> document()->view()->visibleContentRect() will return the content rect of the
> HTML document in the case of HTML with nested SVG.
Well, this example:

<html>
<div style="margin: 20px;">
<object data="filter.svg" type="image/svg+xml" width="5000">
</div>
</body></html>

gives me 0,0,5000,150 as contentRect, is it that what you mean?
------- Comment #25 From 2009-11-10 12:21:52 PST -------
Try xhtml with mixed SVG and HTML. <object> is different.
------- Comment #26 From 2009-11-10 12:32:01 PST -------
(In reply to comment #25)
> Try xhtml with mixed SVG and HTML. <object> is different.

Don't we just support embeding svg into html with either <object>, <img> or <embed>?
------- Comment #27 From 2009-11-10 12:42:02 PST -------
(In reply to comment #26)
> (In reply to comment #25)
> > Try xhtml with mixed SVG and HTML. <object> is different.
> 
> Don't we just support embeding svg into html with either <object>, <img> or
> <embed>?

Sorry. I noticed, that there is a difference, if I name the file with .xml or .html :-P Here the exmaple:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body id="body">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <linearGradient id="gradient" gradientUnits="objectBoundingBox"
                            x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stop-color="green" />
            <stop offset="0.01" stop-color="red" />
        </linearGradient>
        <filter id="filter">
            <feOffset/>
        </filter>
    </defs>
    <g>
        <rect x="0" y="0" width="5000" height="5000" style="fill:url(#gradient);filter:url(#filter);"/>
    </g>
</svg>
</body>
</html>

The viewport is now the visible area of the window and changes with resizing the window.
------- Comment #28 From 2009-11-10 12:56:03 PST -------
(In reply to comment #25)
> Try xhtml with mixed SVG and HTML. <object> is different.
When I look at the exmaple above, I still think that the behavior is right, since the HML itself limits the size of the SVG. So clipping here is ok. And even with 3D transform, the SVG shouldn't get more content.
------- Comment #29 From 2009-11-10 14:12:38 PST -------
Created an attachment (id=42894) [details]
Testcase with svg inside 3d transform
------- Comment #30 From 2009-11-10 14:20:52 PST -------
Created an attachment (id=42897) [details]
Better testcase
------- Comment #31 From 2009-11-10 14:33:38 PST -------
(In reply to comment #30)
> Created an attachment (id=42897) [details] [details]
> Better testcase

Don't know if this is a bug on Cairo, but this example event don't work without filters. I added
<div style="background-color:green; width:5000px;height:50px"></div>
and the green box is longer than the green to red rect of the SVG (css transformation disabled). But this reflects a general problem with big sized SVG. We do clampImageBufferSizeToViewport on other parts of SVG and every time this could break CSS transformations :-/.

Who decided to combine this techniques ;-)
------- Comment #32 From 2009-11-10 23:57:11 PST -------
I still believe that it is better to clip the filter to viewport for the moment. Even if it causes problems with big filters on CSS transforms. We should figure out a general solution for SVG to aboid this problem, since we clip the size on other parts of SVG too.
Or does someone have a better idea how to limit the calculation complexity?
------- Comment #33 From 2009-11-23 09:30:28 PST -------
Fixed in bug 6021.