Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply globalAlpha on the canvas filter source #10674

Merged
merged 1 commit into from
Oct 9, 2024

Conversation

graveljp
Copy link
Contributor

@graveljp graveljp commented Oct 4, 2024

The current specification for canvas filters applies the globalAlpha
on the filter result. The drawing model essentially says:

  • Render the shape, creating image A.
  • When the current filter is set, use it on image A to create image B.
  • Multiply the alpha component of every pixel in B by global alpha.

This leads to a unexpected behavior. When drawing a transparent shape
with a drop-shadow filter, the shadow should be visible through the
transparent foreground. This should be true whether the drawing is made
transparent via fillStyle or via globalAlpha. This is how Chrome and
Firefox behaves. Following the specification to the letter however,
the shadow wouldn't be visible through the foreground.

This PR aligns the specification with Chrome's and Firefox's behavior:

  • Render the shape, creating image A.
  • Multiply the alpha component of every pixel in A by global alpha,
    creating image B.
  • When the current filter is set, use it on image B to create image C.

(See WHATWG Working Mode: Changes for more details.)


/canvas.html ( diff )

The current specification for canvas filters applies the globalAlpha
on the filter result. The drawing model essentially says:
 - Render the shape, creating image A.
 - When the current filter is set, use it on image A to create image B.
 - Multiply the alpha component of every pixel in B by global alpha.

This leads to a unexpected behavior. When drawing a transparent shape
with a drop-shadow filter, the shadow should be visible through the
transparent foreground. This should be true whether the drawing is made
transparent via fillStyle or via globalAlpha. This is how Chrome and
Firefox behaves. Following the specification to the letter however,
the shadow wouldn't be visible through the foreground.

This PR aligns the specification with Chrome's and Firefox's behavior:
 - Render the shape, creating image A.
 - Multiply the alpha component of every pixel in A by global alpha,
   creating image B.
 - When the current filter is set, use it on image B to create image C.
Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editorially LGTM; will give a few more days in case people with more domain expertise from @whatwg/canvas want to review.

Thanks for the great PR description outlining the problem and solution!

@Kaiido
Copy link
Member

Kaiido commented Oct 4, 2024

Just to note, there is a very old interop issue right in this algo regarding when the compositing of the shadow (ctx.shadowXXX) is to be done: https://jsfiddle.net/aw5gr913/ No 2 browsers do the same thing for all modes.

I'm not sure this change would affect that since I guess it's the same to apply the global alpha over the source image and use the new "local" alpha to make the shadow, or to apply the global alpha on the shadowed result, but still, I may miss something and this compositing discrepancy might be problematic here too.

Ps: That'd be https://bugzilla.mozilla.org/show_bug.cgi?id=1072548 for Firefox.

@shallawa
Copy link

shallawa commented Oct 4, 2024

For WebKit, this change seems correct. Currently WebKit does not behave the correct way. I filed https://bugs.webkit.org/show_bug.cgi?id=280894 to track this issue.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Oct 7, 2024
The specification currently says that the globalAlpha should be
applied on the result of the context's filter. This however leads to
an unexpected behavior because if the filter is a drop-shadow, we
can't see the shadow through the foreground even though the foreground
is made transparent by the globalAlpha.

This is not what Chrome and Firefox do. These browsers instead apply
the globalAlpha on the source of the filter, therefore making the
foreground transparent.

The specification issue is addressed in:
whatwg/html#10674

Change-Id: I3832c3cf6390933770a08669f62e9b1b29caccf8
aarongable pushed a commit to chromium/chromium that referenced this pull request Oct 8, 2024
The specification currently says that the globalAlpha should be
applied on the result of the context's filter. This however leads to
an unexpected behavior because if the filter is a drop-shadow, we
can't see the shadow through the foreground even though the foreground
is made transparent by the globalAlpha.

This is not what Chrome and Firefox do. These browsers instead apply
the globalAlpha on the source of the filter, therefore making the
foreground transparent.

The specification issue is addressed in:
whatwg/html#10674

Change-Id: I3832c3cf6390933770a08669f62e9b1b29caccf8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5904448
Reviewed-by: Aaron Krajeski <[email protected]>
Commit-Queue: Jean-Philippe Gravel <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1365599}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Oct 8, 2024
The specification currently says that the globalAlpha should be
applied on the result of the context's filter. This however leads to
an unexpected behavior because if the filter is a drop-shadow, we
can't see the shadow through the foreground even though the foreground
is made transparent by the globalAlpha.

This is not what Chrome and Firefox do. These browsers instead apply
the globalAlpha on the source of the filter, therefore making the
foreground transparent.

The specification issue is addressed in:
whatwg/html#10674

Change-Id: I3832c3cf6390933770a08669f62e9b1b29caccf8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5904448
Reviewed-by: Aaron Krajeski <[email protected]>
Commit-Queue: Jean-Philippe Gravel <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1365599}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Oct 8, 2024
The specification currently says that the globalAlpha should be
applied on the result of the context's filter. This however leads to
an unexpected behavior because if the filter is a drop-shadow, we
can't see the shadow through the foreground even though the foreground
is made transparent by the globalAlpha.

This is not what Chrome and Firefox do. These browsers instead apply
the globalAlpha on the source of the filter, therefore making the
foreground transparent.

The specification issue is addressed in:
whatwg/html#10674

Change-Id: I3832c3cf6390933770a08669f62e9b1b29caccf8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5904448
Reviewed-by: Aaron Krajeski <[email protected]>
Commit-Queue: Jean-Philippe Gravel <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1365599}
@domenic domenic merged commit 8a94842 into whatwg:main Oct 9, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants