Open Bug 1755678 Opened 2 years ago Updated 2 years ago

CanvasRenderingContext2D.filter doesn't work with SVG filters

Categories

(Core :: SVG, defect)

Firefox 98
defect

Tracking

()

People

(Reporter: steiner.thomas, Unassigned, NeedInfo)

References

Details

Attachments

(5 files)

Attached image chrome.png (deleted) —

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.

Attached image firefox.png (deleted) —

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.

Component: Untriaged → Canvas: 2D
Product: Firefox → Core

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!

Severity: -- → S4
Component: Canvas: 2D → DOM: Core & HTML

(Whoops, didn't mean to set the priority)

Severity: S4 → --

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.

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.)

Perhaps, should be handled in SVG component.

Component: DOM: Core & HTML → SVG

(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 use width: 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?

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.)

Flags: needinfo?(steiner.thomas)

(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.)

Thanks for looking into this. The original test case with svg { display: none; } has been re-established here: https://liberating-honorable-shallot.glitch.me/.

Flags: needinfo?(steiner.thomas)

Side note: while poking at variants of the testcase here, I managed to trigger a crash, which I filed as bug 1758029.

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.

Attached file reference case for testcases 1 and 2 (deleted) —

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).

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).

Severity: -- → S3
Status: UNCONFIRMED → NEW
Ever confirmed: true

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.)

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?

Flags: needinfo?(jwatt)

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.

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

Attachment

General

Creator:
Created:
Updated:
Size: