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

LibWeb: Support blending in CSS and the canvas #3267

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

skyz1
Copy link
Contributor

@skyz1 skyz1 commented Jan 15, 2025

This PR adds support for the mix-blend-mode CSS property.
It also implements compositing and various blending modes via the globalCompositeOperation attribute in the canvas.

This makes some more tests in https://wpt.fyi/results/html/canvas/element/compositing pass.

Libraries/LibGfx/PainterSkia.cpp Outdated Show resolved Hide resolved
Libraries/LibGfx/PainterSkia.cpp Outdated Show resolved Hide resolved
Canvas now supports compositing and various blending modes via the
`globalCompositeOperation` attribute.
@skyz1
Copy link
Contributor Author

skyz1 commented Jan 16, 2025

I adapted the code to use blender instead of blend mode. However I am not sure if "plus-darken" works correctly, as the Spec seems to have an incorrect formula, the implementation differs between popular Browsers, and and I don't know how it should look like.

@skyz1 skyz1 requested a review from konradekk January 16, 2025 15:52
Copy link
Contributor

@konradekk konradekk left a comment

Choose a reason for hiding this comment

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

oh! neatly structured! 👍🏻

if (current_compositing_and_blending_operator == "plus-darker"sv) {
return SkRuntimeEffect::MakeForBlender(SkString(R"(
vec4 main(vec4 source, vec4 destination) {
return max(vec4(0.0), source + destination - vec4(1.0));
Copy link
Contributor

Choose a reason for hiding this comment

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

how does this behave?

Suggested change
return max(vec4(0.0), source + destination - vec4(1.0));
return max(vec4(0.0), vec4(1.0) - ((vec4(1.0) - destination) + (vec4(1.0) - source))));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sadly, this does not work either...

I failed to find an implementation of this mode using Skia on Github. Even WebKit, the only Engine that supports it, has no implementation using Skia. I think the problem is the transparent black background, but I currently have no workaround.

@skyz1 skyz1 requested a review from AtkinsSJ as a code owner January 17, 2025 00:11
This adds support for the `mix-blend-mode` CSS property.
@skyz1 skyz1 changed the title LibWeb/Canvas: Support globalCompositionOperation attribute LibWeb: Support blending in CSS and the Canvas Jan 17, 2025
@skyz1 skyz1 changed the title LibWeb: Support blending in CSS and the Canvas LibWeb: Support blending in CSS and the canvas Jan 17, 2025
@skyz1
Copy link
Contributor Author

skyz1 commented Jan 17, 2025

I extended the scope of this PR and also implemented the mi-blend-mode CSS property. Now blending can be tested using this demo. It seems like all modes except plus-darker work pretty well, although there are some slight deviations from WebKit and Chromium. This may be caused by the pre-multiplied alpha.

Copy link
Contributor

@konradekk konradekk left a comment

Choose a reason for hiding this comment

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

it seems that it is enough to

  • pass .isolate = computed_values.isolation() == CSS::Isolation::Isolate in push_stacking_context_params,
  • propagate from there to PushStackingContext, and
  • use in DisplayListPlayerSkia like this
    if (command.opacity < 1 || command.mix_blend_mode != "normal"sv || command.isolate) {

to have working isolation on the mdn page you mentioned.

Comment on lines +233 to +241
// FIXME: This value is only correctly supported by Safari in combination with Core Graphics.
// It looks like the spec is wrong about the formula. We therefore use the one from
// https://developer.apple.com/documentation/coregraphics/cgblendmode/plusdarker for now.
// However it also does not work.
return SkRuntimeEffect::MakeForBlender(SkString(R"(
vec4 main(vec4 source, vec4 destination) {
return max(vec4(0.0), source + destination - vec4(1.0));
}
)"))
Copy link
Contributor

Choose a reason for hiding this comment

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

could you try the following?

Suggested change
// FIXME: This value is only correctly supported by Safari in combination with Core Graphics.
// It looks like the spec is wrong about the formula. We therefore use the one from
// https://developer.apple.com/documentation/coregraphics/cgblendmode/plusdarker for now.
// However it also does not work.
return SkRuntimeEffect::MakeForBlender(SkString(R"(
vec4 main(vec4 source, vec4 destination) {
return max(vec4(0.0), source + destination - vec4(1.0));
}
)"))
return SkRuntimeEffect::MakeForBlender(SkString(R"(
vec4 main(vec4 source, vec4 destination) {
return saturate(saturate(destination.a + source.a) - saturate(destination.a - destination) - saturate(source.a - source));
}
)"))
.effect->makeBlender(nullptr);

Comment on lines +246 to +248
vec4 main(vec4 source, vec4 destination) {
return min(vec4(1.0), source + destination);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: to align with hinted code, you can also switch to

Suggested change
vec4 main(vec4 source, vec4 destination) {
return min(vec4(1.0), source + destination);
}
vec4 main(vec4 source, vec4 destination) {
return saturate(source + destination);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants