diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 6c2105f2..bb1b62c5 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -524,6 +524,11 @@ pub enum LineJoin { #[derive(Clone, Copy, Debug, PartialEq)] pub enum CompositeOperation { SourceOver, + DestinationOver, + DestinationOut, + SourceAtop, + Xor, + Lighter, Lighten, Darken, } @@ -531,7 +536,12 @@ pub enum CompositeOperation { impl CompositeOperation { fn to_blend_mode(self) -> BlendMode { match self { - CompositeOperation::SourceOver => BlendMode::SourceOver, + CompositeOperation::SourceOver => BlendMode::SrcOver, + CompositeOperation::DestinationOver => BlendMode::DestOver, + CompositeOperation::DestinationOut => BlendMode::DestOut, + CompositeOperation::SourceAtop => BlendMode::SrcAtop, + CompositeOperation::Xor => BlendMode::Xor, + CompositeOperation::Lighter => BlendMode::Lighter, CompositeOperation::Lighten => BlendMode::Lighten, CompositeOperation::Darken => BlendMode::Darken, } diff --git a/content/src/effects.rs b/content/src/effects.rs index 4413e943..bbe6cbb0 100644 --- a/content/src/effects.rs +++ b/content/src/effects.rs @@ -58,14 +58,19 @@ pub enum Filter { #[derive(Clone, Copy, Debug)] pub enum CompositeOp { /// The default. - SourceOver, + SrcOver, } /// Blend modes that can be applied to individual paths without creating layers for them. #[derive(Clone, Copy, PartialEq, Debug)] pub enum BlendMode { - SourceOver, Clear, + SrcOver, + DestOver, + DestOut, + SrcAtop, + Xor, + Lighter, Lighten, Darken, } @@ -76,25 +81,31 @@ pub struct DefringingKernel(pub [f32; 4]); impl Default for CompositeOp { #[inline] fn default() -> CompositeOp { - CompositeOp::SourceOver + CompositeOp::SrcOver } } impl Default for BlendMode { #[inline] fn default() -> BlendMode { - BlendMode::SourceOver + BlendMode::SrcOver } } impl BlendMode { /// Whether the backdrop is irrelevant when applying this blend mode (i.e. destination blend - /// factor is zero). + /// factor is zero when source alpha is one). #[inline] pub fn occludes_backdrop(self) -> bool { match self { - BlendMode::SourceOver | BlendMode::Clear => true, - BlendMode::Lighten | BlendMode::Darken => false, + BlendMode::SrcOver | BlendMode::Clear => true, + BlendMode::DestOver | + BlendMode::DestOut | + BlendMode::SrcAtop | + BlendMode::Xor | + BlendMode::Lighter | + BlendMode::Lighten | + BlendMode::Darken => false, } } } diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 8c26b5ed..c2cd5970 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -965,6 +965,8 @@ impl BlendFactorExt for BlendFactor { BlendFactor::One => gl::ONE, BlendFactor::SrcAlpha => gl::SRC_ALPHA, BlendFactor::OneMinusSrcAlpha => gl::ONE_MINUS_SRC_ALPHA, + BlendFactor::DestAlpha => gl::DST_ALPHA, + BlendFactor::OneMinusDestAlpha => gl::ONE_MINUS_DST_ALPHA, BlendFactor::DestColor => gl::DST_COLOR, } } diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index 2775b268..4787bafe 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -226,6 +226,8 @@ pub enum BlendFactor { One, SrcAlpha, OneMinusSrcAlpha, + DestAlpha, + OneMinusDestAlpha, DestColor, } diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 001412f0..6876c1f0 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -1170,6 +1170,8 @@ impl BlendFactorExt for BlendFactor { BlendFactor::One => MTLBlendFactor::One, BlendFactor::SrcAlpha => MTLBlendFactor::SourceAlpha, BlendFactor::OneMinusSrcAlpha => MTLBlendFactor::OneMinusSourceAlpha, + BlendFactor::DestAlpha => MTLBlendFactor::DestinationAlpha, + BlendFactor::OneMinusDestAlpha => MTLBlendFactor::OneMinusDestinationAlpha, BlendFactor::DestColor => MTLBlendFactor::DestinationColor, } } diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 28305fa6..0d8b5e28 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -762,7 +762,7 @@ where ], viewport: self.draw_viewport(), options: RenderOptions { - blend: Some(BlendMode::SourceOver.to_blend_state()), + blend: Some(BlendMode::SrcOver.to_blend_state()), depth: Some(DepthState { func: DepthFunc::Less, write: false, }), clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, ..RenderOptions::default() @@ -848,7 +848,7 @@ where ]; let blend_state = match composite_op { - CompositeOp::SourceOver => BlendMode::SourceOver.to_blend_state(), + CompositeOp::SrcOver => BlendMode::SrcOver.to_blend_state(), }; self.device.draw_elements(6, &RenderState { @@ -1133,15 +1133,6 @@ trait BlendModeExt { impl BlendModeExt for BlendMode { fn to_blend_state(self) -> BlendState { match self { - BlendMode::SourceOver => { - BlendState { - src_rgb_factor: BlendFactor::SrcAlpha, - dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, - src_alpha_factor: BlendFactor::One, - dest_alpha_factor: BlendFactor::One, - ..BlendState::default() - } - } BlendMode::Clear => { BlendState { src_rgb_factor: BlendFactor::Zero, @@ -1151,9 +1142,63 @@ impl BlendModeExt for BlendMode { ..BlendState::default() } } + BlendMode::SrcOver => { + BlendState { + src_rgb_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::OneMinusSrcAlpha, + ..BlendState::default() + } + } + BlendMode::DestOver => { + BlendState { + src_rgb_factor: BlendFactor::OneMinusDestAlpha, + dest_rgb_factor: BlendFactor::DestAlpha, + src_alpha_factor: BlendFactor::OneMinusDestAlpha, + dest_alpha_factor: BlendFactor::One, + ..BlendState::default() + } + } + BlendMode::DestOut => { + BlendState { + src_rgb_factor: BlendFactor::Zero, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::Zero, + dest_alpha_factor: BlendFactor::OneMinusSrcAlpha, + ..BlendState::default() + } + } + BlendMode::SrcAtop => { + BlendState { + src_rgb_factor: BlendFactor::DestAlpha, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::DestAlpha, + dest_alpha_factor: BlendFactor::OneMinusSrcAlpha, + ..BlendState::default() + } + } + BlendMode::Xor => { + BlendState { + src_rgb_factor: BlendFactor::OneMinusDestAlpha, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::OneMinusDestAlpha, + dest_alpha_factor: BlendFactor::OneMinusSrcAlpha, + ..BlendState::default() + } + } + BlendMode::Lighter => { + BlendState { + src_rgb_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::One, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::One, + ..BlendState::default() + } + } BlendMode::Lighten => { BlendState { - src_rgb_factor: BlendFactor::SrcAlpha, + src_rgb_factor: BlendFactor::One, dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, src_alpha_factor: BlendFactor::One, dest_alpha_factor: BlendFactor::One, @@ -1162,7 +1207,7 @@ impl BlendModeExt for BlendMode { } BlendMode::Darken => { BlendState { - src_rgb_factor: BlendFactor::SrcAlpha, + src_rgb_factor: BlendFactor::One, dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, src_alpha_factor: BlendFactor::One, dest_alpha_factor: BlendFactor::One, diff --git a/resources/shaders/gl3/tile_alpha.fs.glsl b/resources/shaders/gl3/tile_alpha.fs.glsl index ee552817..20056d8f 100644 --- a/resources/shaders/gl3/tile_alpha.fs.glsl +++ b/resources/shaders/gl3/tile_alpha.fs.glsl @@ -27,6 +27,8 @@ out vec4 oFragColor; void main(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 color = texture(uPaintTexture, vColorTexCoord); - oFragColor = vec4(color . rgb, color . a * coverage); + color . a *= coverage; + color . rgb *= color . a; + oFragColor = color; } diff --git a/resources/shaders/metal/tile_alpha.fs.metal b/resources/shaders/metal/tile_alpha.fs.metal index 8bef5f84..7c54f4b7 100644 --- a/resources/shaders/metal/tile_alpha.fs.metal +++ b/resources/shaders/metal/tile_alpha.fs.metal @@ -28,7 +28,10 @@ fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuff main0_out out = {}; float coverage = spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x; float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); - out.oFragColor = float4(color.xyz, color.w * coverage); + color.w *= coverage; + float3 _41 = color.xyz * color.w; + color = float4(_41.x, _41.y, _41.z, color.w); + out.oFragColor = color; return out; } diff --git a/shaders/tile_alpha.fs.glsl b/shaders/tile_alpha.fs.glsl index a1bddfd5..f21d53be 100644 --- a/shaders/tile_alpha.fs.glsl +++ b/shaders/tile_alpha.fs.glsl @@ -25,5 +25,7 @@ out vec4 oFragColor; void main() { float coverage = texture(uStencilTexture, vMaskTexCoord).r; vec4 color = texture(uPaintTexture, vColorTexCoord); - oFragColor = vec4(color.rgb, color.a * coverage); + color.a *= coverage; + color.rgb *= color.a; + oFragColor = color; } diff --git a/svg/src/lib.rs b/svg/src/lib.rs index 022cd574..e954e0cd 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -240,7 +240,7 @@ impl BuiltSVG { style, state.clip_path, fill_rule, - BlendMode::SourceOver, + BlendMode::SrcOver, name)); } } diff --git a/swf/src/lib.rs b/swf/src/lib.rs index 97ea146f..1ab03e2e 100644 --- a/swf/src/lib.rs +++ b/swf/src/lib.rs @@ -201,7 +201,7 @@ pub fn draw_paths_into_scene(library: &SymbolLibrary, scene: &mut Scene) { paint_id, None, FillRule::EvenOdd, - BlendMode::SourceOver, + BlendMode::SrcOver, String::new() )); } diff --git a/text/src/lib.rs b/text/src/lib.rs index 5f6bfc06..443a6439 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -82,7 +82,7 @@ impl SceneExt for Scene { paint_id, None, FillRule::Winding, - BlendMode::SourceOver, + BlendMode::SrcOver, String::new())); Ok(())