Bug 10403

Summary: SVG example exposes problems with <feImage>
Product: WebKit Reporter: Eric Seidel (no email) <eric>
Component: SVGAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: krit, rhodovan.u-szeged, thorton, webkit-bug-importer, zherczeg, zimmermann
Priority: P4 Keywords: InRadar, NeedsReduction
Version: 420+   
Hardware: Mac   
OS: OS X 10.4   
URL: http://srufaculty.sru.edu/david.dailey/svg/waves.html
Bug Depends on: 15505, 71780, 73860, 76559, 76780, 76800, 77205    
Bug Blocks: 68469, 26389    
Attachments:
Description Flags
Test image for testcase
none
Reduced testcase showing filter problem
none
ImageBuffer jpg dump of SVGFEImageElement m_targetImage
none
Another simpler reduction w/o feDispMap none

Description Eric Seidel (no email) 2006-08-14 23:43:41 PDT
Failed to find resource with id: f
Failed to find resource with id: f
Failed to find resource with id: f
Failed to find resource with id: f
Failed to find resource with id: f
(event handler):Null value
Failed to find resource with id: f
Comment 1 Eric Seidel (no email) 2006-09-24 22:13:48 PDT
Hum... that log has been removed since.  This SVG doesnt' work quite right yet.  still have the null value to debug.
Comment 2 Eric Seidel (no email) 2007-01-31 05:06:41 PST
This no longer has trouble finding resources.  However there are a few errors printed to the console:

(event handler):Null value
(event handler):Can't find variable: im
(event handler):Can't find variable: svgdoc
(event handler):Can't find variable: svgdoc
Comment 3 Eric Seidel (no email) 2007-06-01 16:22:32 PDT
I think this might come from <embed name="sv"> not making the embed available via document.getElementById("sv").  But I'm not sure.
Comment 4 Eric Seidel (no email) 2007-06-12 11:47:22 PDT
Someone just needs to reduce this.
Comment 5 Nikolas Zimmermann 2009-10-05 08:51:43 PDT
Even after all these years, it still has bugs, this time it leads to JSC crashes. Needs further investigation.

Backtrace:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000bbadbeef
Crashed Thread:  0

Thread 0 Crashed:
0   com.apple.JavaScriptCore      	0x006dd60a JSC::Interpreter::execute(JSC::FunctionExecutable*, JSC::ExecState*, JSC::JSFunction*, JSC::JSObject*, JSC::ArgList const&, JSC::ScopeChainNode*, JSC::JSValue*) + 88 (Interpreter.cpp:678)
1   com.apple.JavaScriptCore      	0x00642a2f JSC::JSFunction::call(JSC::ExecState*, JSC::JSValue, JSC::ArgList const&) + 223 (JSFunction.cpp:121)
2   com.apple.JavaScriptCore      	0x00642b0b JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 211 (CallData.cpp:39)
3   com.apple.WebCore             	0x04084b48 WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) + 1020
4   com.apple.WebCore             	0x03e45439 WebCore::EventTarget::fireEventListeners(WebCore::Event*) + 631
5   com.apple.WebCore             	0x03e059d1 WebCore::DOMWindow::dispatchEvent(WTF::PassRefPtr<WebCore::Event>, WTF::PassRefPtr<WebCore::EventTarget>) + 215
6   com.apple.WebCore             	0x03e0654d WebCore::DOMWindow::dispatchLoadEvent() + 101
7   com.apple.WebCore             	0x03d2d29b WebCore::Document::dispatchWindowLoadEvent() + 113
8   com.apple.WebCore             	0x03d382fb WebCore::Document::implicitClose() + 957
9   com.apple.WebCore             	0x03e8bc0c WebCore::FrameLoader::checkCallImplicitClose() + 122
10  com.apple.WebCore             	0x03e8ebab WebCore::FrameLoader::checkCompleted() + 199
11  com.apple.WebCore             	0x03e8ed18 WebCore::FrameLoader::completed() + 156
12  com.apple.WebCore             	0x03e8ebc1 WebCore::FrameLoader::checkCompleted() + 221
13  com.apple.WebCore             	0x03e900bd WebCore::FrameLoader::loadDone() + 17
14  com.apple.WebCore             	0x03d218b6 WebCore::DocLoader::setLoadInProgress(bool) + 116
15  com.apple.WebCore             	0x04225ded WebCore::Loader::Host::didFinishLoading(WebCore::SubresourceLoader*) + 545
16  com.apple.WebCore             	0x04451260 WebCore::SubresourceLoader::didFinishLoading() + 176
17  com.apple.WebCore             	0x043d4b82 WebCore::ResourceLoader::didFinishLoading(WebCore::ResourceHandle*) + 24
18  com.apple.WebCore             	0x043d13b7 -[WebCoreResourceHandleAsDelegate connectionDidFinishLoading:] + 215
19  com.apple.Foundation          	0x90d96497 -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] + 87
20  com.apple.Foundation          	0x90d96403 _NSURLConnectionDidFinishLoading + 147
21  com.apple.CFNetwork           	0x971e1ba4 URLConnectionClient::_clientDidFinishLoading(URLConnectionClient::ClientConnectionEventQueue*) + 212
22  com.apple.CFNetwork           	0x971e28fa URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) + 310
23  com.apple.CFNetwork           	0x971e1370 URLConnectionClient::processEvents() + 104
24  com.apple.CFNetwork           	0x9718ed03 MultiplexerSource::perform() + 189
25  com.apple.CoreFoundation      	0x932883c5 CFRunLoopRunSpecific + 3141
26  com.apple.CoreFoundation      	0x93288aa8 CFRunLoopRunInMode + 88
27  com.apple.HIToolbox           	0x967e52ac RunCurrentEventLoopInMode + 283
28  com.apple.HIToolbox           	0x967e50c5 ReceiveNextEventCommon + 374
29  com.apple.HIToolbox           	0x967e4f39 BlockUntilNextEventMatchingListInMode + 106
30  com.apple.AppKit              	0x947316d5 _DPSNextEvent + 657
31  com.apple.AppKit              	0x94730f88 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
32  com.apple.Safari              	0x0000c303 0x1000 + 45827
33  com.apple.AppKit              	0x94729f9f -[NSApplication run] + 795
34  com.apple.AppKit              	0x946f71d8 NSApplicationMain + 574
Comment 6 Nikolas Zimmermann 2010-07-27 02:20:33 PDT
I don't see JSC crashes anymore in trunk, but still doesn't work. Maybe a filter hacker can have a look?
Comment 7 Nikolas Zimmermann 2011-05-31 00:27:37 PDT
CC'ing Reni, who might have a clue?
Comment 8 Nikolas Zimmermann 2011-10-19 03:04:41 PDT
Created attachment 111583 [details]
Test image for testcase

I looked into the ripple.svg document contained in Davids waves testcase, we have a problem with the feDispMap filter, which is causing trouble. I've reduced it to a simpler testcase. You'll need foo.jpg as input.
Comment 9 Nikolas Zimmermann 2011-10-19 03:05:34 PDT
Created attachment 111584 [details]
Reduced testcase showing filter problem
Comment 10 Nikolas Zimmermann 2011-10-19 04:21:56 PDT
Created attachment 111590 [details]
ImageBuffer jpg dump of SVGFEImageElement m_targetImage

Fun! I've dumped the ImageBuffer at rx="160" ry="160" that SVGFEImageElement::build() produces.
Obviously the way renderSubtreeToImageBuffer is used here is flawed, more to come.
Comment 11 Nikolas Zimmermann 2011-10-19 05:38:08 PDT
Created attachment 111600 [details]
Another simpler reduction w/o feDispMap
Comment 12 Radar WebKit Bug Importer 2011-12-15 11:58:39 PST
<rdar://problem/10588362>
Comment 13 Nikolas Zimmermann 2012-01-21 05:08:31 PST
I fixed the filter problem locally, though there's still a dynamic invalidation problem, which is tricky:
The embedded document looks like this:
<defs>
<filter id="d" >
	<feImage xlink:href="#r" result="grad" />
	<feDisplacementMap scale="20" id="feDM"
	 xChannelSelector="R" 
	in="SourceGraphic" in2="grad"/>
</filter> </defs>
<ellipse id="r" cx="50%" cy="50%" rx="80%" ry="80%"
style="fill:url(#f)"/>
<image filter='url(#d)' id="M" xlink:href='Manjbah4.jpg'  width="100%" 
height="100%" preserveAspectRatio="none"/>
</svg>

The host documents, add an <radialGradient id="f"><stop offset="..."> to the embedded document, and then changes the stop offsets using a <script>.

That _only_ invalidates the <ellipse> as it uses the fill="url(#f). There's no link between the <ellipse> and the <feImage/> so this filter is never going to be invalidated.

We don't support invalidation of any indirect references like this.
If the <ellipse> would be a child of the <feImage> everything would work...
Comment 14 Tim Horton 2012-01-21 12:12:26 PST
(In reply to comment #13)
> I fixed the filter problem locally, though there's still a dynamic invalidation problem, which is tricky:
> The embedded document looks like this:
> <defs>
> <filter id="d" >
>     <feImage xlink:href="#r" result="grad" />
>     <feDisplacementMap scale="20" id="feDM"
>      xChannelSelector="R" 
>     in="SourceGraphic" in2="grad"/>
> </filter> </defs>
> <ellipse id="r" cx="50%" cy="50%" rx="80%" ry="80%"
> style="fill:url(#f)"/>
> <image filter='url(#d)' id="M" xlink:href='Manjbah4.jpg'  width="100%" 
> height="100%" preserveAspectRatio="none"/>
> </svg>
> 
> The host documents, add an <radialGradient id="f"><stop offset="..."> to the embedded document, and then changes the stop offsets using a <script>.
> 
> That _only_ invalidates the <ellipse> as it uses the fill="url(#f). There's no link between the <ellipse> and the <feImage/> so this filter is never going to be invalidated.
> 
> We don't support invalidation of any indirect references like this.
> If the <ellipse> would be a child of the <feImage> everything would work...

Technically <use> supports invalidation when a target referenced element changes, no? I wonder if we could adapt some of that mechanism?
Comment 15 Nikolas Zimmermann 2012-01-21 14:01:54 PST
(In reply to comment #14)
> Technically <use> supports invalidation when a target referenced element changes, no? I wonder if we could adapt some of that mechanism?
Well it clones the target into its shadow tree, so this is not really comparable.
Consider:
<filter id="foo">
<feImage xlink:href="#somerect"/>
</filter>
<rect id="someRect" fill="url(#gradient")/>
<linearGradient id="gradient"><stop/></linearGradient>
<image filter="url(#foo)"/>

Say I change the linearGradient stop offset using JS. That would invalidate the <linearGradient>, and cause a repaint of the "someRect". And that's where it stops. There's no connectionb etween "someRect" and the <feImage> that references it.

Note: I have already fixed this locally, by introducing a new HashMap<SVGElement*, OwnPtr<HashSet<SVGElement*>> > in SVGDocumentExtensions. SVGFEImageElement registers the hrefElement with itself there. I'll write up more details tomorrow, about to sleep :-)
Comment 16 Nikolas Zimmermann 2012-01-22 12:45:12 PST
While I got the test case working locally, I still have to reload a few times before it eventually works, because of bug 15505 - onload sometimes fires too early.
The onload handler of the host document tries to access "document.sv", and the document contains <embed name="sv" src="some.svg">. The unload handler is often fired before the some.svg document is loaded, leading to wrong results.
When chaining onload="prepare()" to onload="setTimeout(prepare, 0)" it seems to work always, but this is only a hack - the document onload event should be delayed until the embed is loaded.

Once bugs 76559 and 76800 landed, I'll post the patch which fixes this test case, except for the onload problem.
Comment 17 Dirk Schulze 2012-02-01 21:26:09 PST
(In reply to comment #16)

> Once bugs 76559 and 76800 landed, I'll post the patch which fixes this test case, except for the onload problem.

76559 and 76800 landed, where is the patch? :)
Comment 18 Nikolas Zimmermann 2012-02-08 00:57:06 PST
(In reply to comment #17)
> (In reply to comment #16)
> 
> > Once bugs 76559 and 76800 landed, I'll post the patch which fixes this test case, except for the onload problem.
> 
> 76559 and 76800 landed, where is the patch? :)

Will post it as soon as the SVGLoad & repainting issues are resolved.
Comment 19 Nikolas Zimmermann 2012-02-08 03:57:59 PST
(In reply to comment #18)
> (In reply to comment #17)
> > (In reply to comment #16)
> > 
> > > Once bugs 76559 and 76800 landed, I'll post the patch which fixes this test case, except for the onload problem.
> > 
> > 76559 and 76800 landed, where is the patch? :)
Waiting at bug 73860.
Comment 20 Nikolas Zimmermann 2012-02-08 04:20:07 PST
Davids example now works in webkit trunk >r107067. Sometimes it takes one or two reloads until it starts animating, due to bug 15505 -- the SVG bugs are all resolved.