Bug 34185 - REGRESSION: Mask not invalidating
Summary: REGRESSION: Mask not invalidating
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC OS X 10.5
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar, Regression
Depends on:
Blocks:
 
Reported: 2010-01-26 14:39 PST by Beth Dakin
Modified: 2010-02-11 00:27 PST (History)
3 users (show)

See Also:


Attachments
Reduction (45.92 KB, application/octet-stream)
2010-01-26 14:39 PST, Beth Dakin
no flags Details
shrinked test (1.17 KB, image/svg+xml)
2010-01-27 01:00 PST, Dirk Schulze
no flags Details
Patch (10.56 KB, patch)
2010-02-10 16:06 PST, Beth Dakin
simon.fraser: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Beth Dakin 2010-01-26 14:39:15 PST
Created attachment 47450 [details]
Reduction

This regressed with: http://trac.webkit.org/changeset/52449

Open the attached test case and click "Move object." The masked image should shift to the right keeping everything intact. But in reality the mask is left behind and is clipped to the left.

<rdar://problem/7577782>
Comment 1 Dirk Schulze 2010-01-26 15:58:19 PST
(In reply to comment #0)
> Created an attachment (id=47450) [details]
> Reduction
> 
> This regressed with: http://trac.webkit.org/changeset/52449
> 
> Open the attached test case and click "Move object." The masked image should
> shift to the right keeping everything intact. But in reality the mask is left
> behind and is clipped to the left.
> 
> <rdar://problem/7577782>

Hi Beth, do you have a more simple test case for reduction? Not sure what causes this problem at the moment. Is the problem related to the patterns?
Comment 2 Beth Dakin 2010-01-26 16:00:45 PST
Unfortunately, I don't have a more reduced test case right now :-(. Someone else filed the bug in Radar, and I just moved it here. I have been looking at it as well, and I will let you know if I come up with a simpler test or an idea of what in the patch caused this.
Comment 3 Dirk Schulze 2010-01-26 16:01:50 PST
Btw, I can't reproduce it with a one week old build. Checking trunk now.
Comment 4 Beth Dakin 2010-01-26 16:02:49 PST
You often have to click "Move object" and "Restore object" several times to see the bug.
Comment 5 Dirk Schulze 2010-01-26 16:39:12 PST
Still can't reproduce it with trunk. I pressed the 2 buttons about 50 times. I don't see any problems. The apple image moves from left to right and back, no clipping problems on WebKitGtk. Just much faster than in the past :-)
Comment 6 Beth Dakin 2010-01-26 16:40:08 PST
It reproduces within a maximum of 5 clicks on the Mac. Odd that is is platform-dependent.
Comment 7 Dirk Schulze 2010-01-27 01:00:13 PST
Created attachment 47506 [details]
shrinked test

This is the basic version of the test above. The green rect should just move but not resize on clicking the text.

The author deletes and recreates the element that uses the mask on every click. Saddly this doesn't cause a invalidation of the mask. We make the assignment of an element to it's resource (mask here) with the elements RenderObject. I'm not sure why, but mask can't differentiate between the RenderObject of the old element and the one of the new element here.

Note: if the author would just modify the attributes instead of recreating the element, the mask would invalidate and we don't see the clipping. :-/
Comment 8 Beth Dakin 2010-02-10 14:35:42 PST
I have a patch for this. Will post shortly.
Comment 9 Beth Dakin 2010-02-10 16:06:03 PST
Created attachment 48529 [details]
Patch
Comment 10 Simon Fraser (smfr) 2010-02-10 16:19:05 PST
Comment on attachment 48529 [details]
Patch

> Index: WebCore/ChangeLog
> ===================================================================
> --- WebCore/ChangeLog	(revision 54627)
> +++ WebCore/ChangeLog	(working copy)
> @@ -1,3 +1,25 @@
> +2010-02-10  Beth Dakin  <bdakin@apple.com>
> +
> +        Reviewed by NOBODY (OOPS!).
> +
> +        Fix for https://bugs.webkit.org/show_bug.cgi?id=34185 REGRESSION: 
> +        Mask not updated according to transform
> +
> +        SVGMaskElement is the only class that keeps a HashMap of canvas 
> +        resources rather than just a since pointer to a resource. This 

mis-typing here: "since pointer".


> Index: WebCore/svg/SVGMaskElement.cpp
> ===================================================================
> --- WebCore/svg/SVGMaskElement.cpp	(revision 54613)
> +++ WebCore/svg/SVGMaskElement.cpp	(working copy)
> @@ -105,9 +105,6 @@ void SVGMaskElement::svgAttributeChanged
>  {
>      SVGStyledElement::svgAttributeChanged(attrName);
>  
> -    if (m_masker.isEmpty())
> -        return;

I'm not sure why this early return can go away, and the changelog doesn't say?

> +void SVGMaskElement::invalidateCanvasResources()
> +{
> +    if (m_masker.isEmpty())
> +        return;
> +
> +    for (HashMap<const RenderObject*, RefPtr<SVGResourceMasker> >::iterator it = m_masker.begin(); it != m_masker.end(); ++it)
> +        it->second->invalidate();

Can that be a const_iterator? You may have to make a local variable to store m_masker.end().

> Index: WebCore/svg/SVGStyledElement.h
> ===================================================================
> --- WebCore/svg/SVGStyledElement.h	(revision 54613)
> +++ WebCore/svg/SVGStyledElement.h	(working copy)
> @@ -62,6 +62,7 @@ namespace WebCore {
>  
>          void invalidateResourcesInAncestorChain() const;
>          void invalidateResources();
> +        virtual void invalidateCanvasResources();

It's unfortunate to propagate the 'canvas' syntax because that is easily confused with HTML canvas. Perhaps add a comment here to explain how invalidateResources() is different from invalidateCanvasResources().

r=me
Comment 11 Darin Adler 2010-02-10 16:27:50 PST
Comment on attachment 48529 [details]
Patch

I reviewed too. Some comments:

> +    if (m_masker.isEmpty())
> +        return;
> +
> +    for (HashMap<const RenderObject*, RefPtr<SVGResourceMasker> >::iterator it = m_masker.begin(); it != m_masker.end(); ++it)
> +        it->second->invalidate();

The early return here (you moved it but did not write it) is not needed. The loop below will efficiently handle the case where m_masker is empty without an explicit empty check.

We are intentionally not calling through to the base class version of invalidateCanvasResources? Maybe a brief comment in this function explaining why that's the right thing to do would be a good addition.

I suggest making the SVGStyledElement invalidateCanvasResources protected and the SVGMaskElement override of invalidateCanvasResources private. Unless you feel strongly they should be public.

Making such functions private can help catch cases where we do a needless virtual function call. Like in the two places in SVGMaskElement. It's a slight shame to call a virtual function when we know it's never overridden, but probably OK to leave as-is.

SVGStyledElement::svgAttributeChanged already calls both invalidateResourcesInAncestorChain and invalidateResources. I'm surprised that we still need an override in SVGMaskElement ::svgAttributeChanged  to call invalidateCanvasResources. But maybe it is still needed; it does seem that invalidateResourcesInAncestorChain does not invalidate its own resources.

r=me
Comment 12 Beth Dakin 2010-02-10 16:50:42 PST
(In reply to comment #11)
> 
> SVGStyledElement::svgAttributeChanged already calls both
> invalidateResourcesInAncestorChain and invalidateResources. I'm surprised that
> we still need an override in SVGMaskElement ::svgAttributeChanged  to call
> invalidateCanvasResources. But maybe it is still needed; it does seem that
> invalidateResourcesInAncestorChain does not invalidate its own resources.
> 

In this particular case, the SVGMaskElement is one of the ancestors, so ::svgAttributeChanged is not called for this mask; the code that I changed in invalidateResourcesInAncestorChain() does the invalidating. In the case where the mask is not the ancestor, you are correct that the problem is that invalidateResourcesInAncestorChain() does not invalidate itself.

Thanks for the reviews! I am addressing your comments now.
Comment 13 Beth Dakin 2010-02-10 19:05:12 PST
Fixed with r54638.
Comment 14 Dirk Schulze 2010-02-11 00:11:16 PST
(In reply to comment #13)
> Fixed with r54638.

I think the changes in SVGStyledElement are not correct. The goal was to just invalidate one Resource, not all.
Imagine one Mask with multiple objects calling it. One object has attribute changes. Why should we invalidate all Resources? This is a performance lost.
Comment 15 Dirk Schulze 2010-02-11 00:27:14 PST
(In reply to comment #14)
> (In reply to comment #13)
> > Fixed with r54638.
> 
> I think the changes in SVGStyledElement are not correct. The goal was to just
> invalidate one Resource, not all.
> Imagine one Mask with multiple objects calling it. One object has attribute
> changes. Why should we invalidate all Resources? This is a performance lost.

hehe sorry. Looks like I have ignored SVGStyledElement::invalidateCanvasResources :-)