CanvasRenderingContext2D.filter doesn't work with SVG filters
Categories
(Core :: SVG, defect)
Tracking
()
People
(Reporter: steiner.thomas, Unassigned, NeedInfo)
References
Details
Attachments
(5 files)
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36
Steps to reproduce:
Go to https://canvas-svg-filter.glitch.me/ in Firefox and compare the output to Chrome.
Actual results:
You will notice that Firefox doesn't support SVG filters, only regular CSS filters like brightness().
Expected results:
Firefox should support SVG filters.
Reporter | ||
Comment 1•3 years ago
|
||
Comment 2•3 years ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::Canvas: 2D' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.
Comment 3•3 years ago
|
||
Hi Thomas, thanks for the bug report!
Svg filters can work just fine in firefox. I'm not a web developer but I believe the problem here is that the stylesheet has display: none
set for svgs. Removing that fixes one of the filters. I think you can use width: 0; height: 0;
to avoid it interfering with page layout instead.
The data URI one still doesn't work for some reason, and I'm not sure why, as setting the filter property to the exact same string works in the devtools. I'm taking a guess this is a DOM issue and moving the bug there, apologies if that's incorrect!
Reporter | ||
Comment 5•3 years ago
|
||
Svg filters can work just fine in firefox. I'm not a web developer but I believe the problem here is that the stylesheet has
display: none
set for svgs. Removing that fixes one of the filters. I think you can usewidth: 0; height: 0;
to avoid it interfering with page layout instead.
Oh, that's interesting. I have changed the demo accordingly so it now hides the SVG width width
and height
set both to 0
. Since the SVG barely serves as the carrier for the filter that gets referenced, I think svg { display: none; }
should still work. Is this a bug or the correct behavior?
The data URI one still doesn't work for some reason, and I'm not sure why, as setting the filter property to the exact same string works in the devtools. I'm taking a guess this is a DOM issue and moving the bug there, apologies if that's incorrect!
I let the Firefox developers investigate then. It's a weird issue indeed. As you're at it, you might want to look into blob:
URLs as well. See https://bugs.chromium.org/p/chromium/issues/detail?id=1298071 for a meta question if this should work at all. (For the record: It currently doesn't in Chrome.)
Comment 6•3 years ago
|
||
Perhaps, should be handled in SVG component.
Comment 7•3 years ago
|
||
(In reply to steiner.thomas from comment #5)
Svg filters can work just fine in firefox. I'm not a web developer but I believe the problem here is that the stylesheet has
display: none
set for svgs. Removing that fixes one of the filters. I think you can usewidth: 0; height: 0;
to avoid it interfering with page layout instead.Oh, that's interesting. I have changed the demo accordingly so it now hides the SVG width
width
andheight
set both to0
. Since the SVG barely serves as the carrier for the filter that gets referenced, I thinksvg { display: none; }
should still work. Is this a bug or the correct behavior?
Just to be sure we're looking at & reasoning about the same thing, would you mind linking a version of the testcase that is still broken-in-Firefox?
(It looks like you've fixed the version at https://canvas-svg-filter.glitch.me/ such that it now behaves the same in Firefox and Chrome, which is great :) but it means it no longer serves as a testcase to demonstrate the issue.)
Comment 8•3 years ago
|
||
(In reply to Daniel Holbert [:dholbert] from comment #7)
Just to be sure we're looking at & reasoning about the same thing, would you mind linking a version of the testcase that is still broken-in-Firefox?
(Just to clarify that this isn't just me-being-lazy: I did try some due-diligence by loading https://canvas-svg-filter.glitch.me/ and adding display:none
to the svg { ... }
CSS rule in Firefox devtools, but that didn't seem to influence the rendering at all. I'm not sure if that's because I'm just successfully bypassing a race condition [via display:none arriving too late to trigger the issue], vs. if there was something additional that was necessary to cause the problem, vs. something else.)
Reporter | ||
Comment 9•3 years ago
|
||
Thanks for looking into this. The original test case with svg { display: none; }
has been re-established here: https://liberating-honorable-shallot.glitch.me/.
Comment 10•3 years ago
|
||
Side note: while poking at variants of the testcase here, I managed to trigger a crash, which I filed as bug 1758029.
Comment 11•3 years ago
|
||
So there are two distinct problems that we seem to be having here (in Firefox):
(1) SVG filters that are provided via data-URI-encoded documents don't seem to work in the ctx.filter
(i.e. CanvasRenderingContext2D.filter) JS-property -- though they do work via CSS filter
.
(2) SVG filters referenced via the ID of a same-document-element simply don't work if the <filter> element is in a display:none
subtree.
I'll attach two reduced testcases to demonstrate each distinct issue.
Comment 12•3 years ago
|
||
Here's a testcase to demonstrate comment 11 part (1).
Comment 13•3 years ago
|
||
Comment 14•3 years ago
|
||
Here's a reference case for both attached testcases, which is identical to testcase 2 except that I've removed display:none
from the filter element's <svg>
ancestor (and I've used width:0;height:0;
instead, as a way of preventing that element from influencing layout, per comment 3).
Comment 15•3 years ago
|
||
Chrome renders testcase 1, testcase 2, and testcase 3 identically (though for me at least, they sometimes fail-to-paint one or both canvases until you force a repaint by switching tabs).
Firefox renders testcase 1 with the left square unexpectedly-crisp (i.e. the data-URI filter is not being applied at all, via the CanvasRenderingContext2D.filter JS-property).
Firefox renders testcase 2 with the left square unexpectedly-crisp and the right square missing entirely (both of which I suspect correspond to the respective rendering models' behaviors for "filter not found", basically).
Comment 16•3 years ago
|
||
Focusing on issue (2) for the moment, RE display:none on same-doc SVG filters, I dug a bit and found two associated bugs:
(a) it looks like bug 376027 tracks a similar (maybe the same?) longstanding issue.
(b) It looks like there was a 2019 SVG Working Group resolution quoted in https://bugzilla.mozilla.org/show_bug.cgi?id=1463336#c1 which says essentially that the element should be treated as if it did not have a filter, which happens to match what we do for CanvasRenderingContext2D.filter (but doesn't match what we're doing for CSS filter
). So: in that part of the reporter's original testcase, Firefox is compliant and Chrome is noncompliant in honoring the filter, I think.
(We are still wrong to hide the element when the filter is applied via CSS, which is what bug 1463336 is about.)
Comment 17•3 years ago
|
||
Focusing on issue (1) about using a data-URI with #foo suffix in CanvasRenderingContext2D.filter: that feels like a legit bug, though I'm not sure it's tracked elsewhere, and it doesn't seem to be a regression -- I'm seeing the same behavior (crisp left rect in testcase 1) in a few old builds that I spot-tested: Nightly 2019-01-01, 2018-01-01, and 2016-01-01.
I know jwatt's done some work on our canvas<-->SVG-filter glue code; jwatt, maybe you have cycles to take a look here at some point?
Comment 18•2 years ago
|
||
Issue 1 isn't a "bug" either. It's per specs that Canvas filters can be loaded asynchronously, which is what happens here.
Waiting the next task to paint that filter on the canvas will make it work: https://jsfiddle.net/qLyhwmed/
If the value of the current filter is a string parseable as a
<filter-value-list>
with a reference to an SVG filter in an external resource document and that document is not loaded when a drawing operation is invoked, then the drawing operation must proceed with no filtering.
Description
•