Mask work
This commit is contained in:
parent
3c38405a71
commit
28f0ce3c83
|
@ -27,6 +27,9 @@ pub trait RenderBackend {
|
||||||
fn end_frame(&mut self);
|
fn end_frame(&mut self);
|
||||||
fn draw_pause_overlay(&mut self);
|
fn draw_pause_overlay(&mut self);
|
||||||
fn draw_letterbox(&mut self, letterbox: Letterbox);
|
fn draw_letterbox(&mut self, letterbox: Letterbox);
|
||||||
|
fn push_mask(&mut self);
|
||||||
|
fn activate_mask(&mut self);
|
||||||
|
fn pop_mask(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -80,6 +83,9 @@ impl RenderBackend for NullRenderer {
|
||||||
fn render_shape(&mut self, _shape: ShapeHandle, _transform: &Transform) {}
|
fn render_shape(&mut self, _shape: ShapeHandle, _transform: &Transform) {}
|
||||||
fn draw_pause_overlay(&mut self) {}
|
fn draw_pause_overlay(&mut self) {}
|
||||||
fn draw_letterbox(&mut self, _letterbox: Letterbox) {}
|
fn draw_letterbox(&mut self, _letterbox: Letterbox) {}
|
||||||
|
fn push_mask(&mut self) {}
|
||||||
|
fn activate_mask(&mut self) {}
|
||||||
|
fn pop_mask(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glue_swf_jpeg_to_tables(jpeg_tables: &[u8], jpeg_data: &[u8]) -> Vec<u8> {
|
pub fn glue_swf_jpeg_to_tables(jpeg_tables: &[u8], jpeg_data: &[u8]) -> Vec<u8> {
|
||||||
|
|
|
@ -196,9 +196,7 @@ impl<'gc> DisplayObject<'gc> for Button<'gc> {
|
||||||
fn render(&self, context: &mut RenderContext<'_, 'gc>) {
|
fn render(&self, context: &mut RenderContext<'_, 'gc>) {
|
||||||
context.transform_stack.push(self.transform());
|
context.transform_stack.push(self.transform());
|
||||||
|
|
||||||
for child in self.children.values() {
|
crate::display_object::render_children(context, &self.children);
|
||||||
child.read().render(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.transform_stack.pop();
|
context.transform_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ impl<'gc> Default for DisplayObjectBase<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> DisplayObject<'gc> for DisplayObjectBase<'gc> {
|
impl<'gc> DisplayObject<'gc> for DisplayObjectBase<'gc> {
|
||||||
|
fn depth(&self) -> Depth {
|
||||||
|
self.depth
|
||||||
|
}
|
||||||
fn transform(&self) -> &Transform {
|
fn transform(&self) -> &Transform {
|
||||||
&self.transform
|
&self.transform
|
||||||
}
|
}
|
||||||
|
@ -71,6 +74,7 @@ impl<'gc> DisplayObject<'gc> for DisplayObjectBase<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DisplayObject<'gc>: 'gc + Collect + Debug {
|
pub trait DisplayObject<'gc>: 'gc + Collect + Debug {
|
||||||
|
fn depth(&self) -> Depth;
|
||||||
fn local_bounds(&self) -> BoundingBox {
|
fn local_bounds(&self) -> BoundingBox {
|
||||||
BoundingBox::default()
|
BoundingBox::default()
|
||||||
}
|
}
|
||||||
|
@ -148,6 +152,9 @@ impl<'gc> Clone for Box<dyn DisplayObject<'gc>> {
|
||||||
|
|
||||||
macro_rules! impl_display_object {
|
macro_rules! impl_display_object {
|
||||||
($field:ident) => {
|
($field:ident) => {
|
||||||
|
fn depth(&self) -> crate::prelude::Depth {
|
||||||
|
self.$field.depth()
|
||||||
|
}
|
||||||
fn transform(&self) -> &crate::transform::Transform {
|
fn transform(&self) -> &crate::transform::Transform {
|
||||||
self.$field.transform()
|
self.$field.transform()
|
||||||
}
|
}
|
||||||
|
@ -190,6 +197,43 @@ macro_rules! impl_display_object {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders the children of a display object, taking masking into account.
|
||||||
|
// TODO(Herschel): Move this into an IDisplayObject/IDisplayObjectContainer trait when
|
||||||
|
// we figure out inheritance
|
||||||
|
pub fn render_children<'gc>(
|
||||||
|
context: &mut RenderContext<'_, 'gc>,
|
||||||
|
children: &std::collections::BTreeMap<Depth, DisplayNode<'gc>>,
|
||||||
|
) {
|
||||||
|
let mut clip_depth = 0;
|
||||||
|
let mut clip_depth_stack = vec![];
|
||||||
|
for (&depth, &child) in children {
|
||||||
|
// Check if we need to pop off a mask.
|
||||||
|
// This must be a while loop because multiple masks can be popped
|
||||||
|
// at the same dpeth.
|
||||||
|
while clip_depth > 0 && depth >= clip_depth {
|
||||||
|
context.renderer.pop_mask();
|
||||||
|
clip_depth = clip_depth_stack.pop().unwrap();
|
||||||
|
}
|
||||||
|
let child = child.read();
|
||||||
|
if child.clip_depth() > 0 {
|
||||||
|
// Push and render the mask.
|
||||||
|
clip_depth_stack.push(clip_depth);
|
||||||
|
clip_depth = child.clip_depth();
|
||||||
|
context.renderer.push_mask();
|
||||||
|
child.render(context);
|
||||||
|
context.renderer.activate_mask();
|
||||||
|
} else {
|
||||||
|
// Normal child.
|
||||||
|
child.render(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while !clip_depth_stack.is_empty() {
|
||||||
|
context.renderer.pop_mask();
|
||||||
|
clip_depth_stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `DisplayNode` is the garbage-collected pointer between display objects.
|
/// `DisplayNode` is the garbage-collected pointer between display objects.
|
||||||
/// TODO(Herschel): The extra Box here is necessary to hold the trait object inside a GC pointer,
|
/// TODO(Herschel): The extra Box here is necessary to hold the trait object inside a GC pointer,
|
||||||
/// but this is an extra allocation... Can we avoid this, maybe with a DST?
|
/// but this is an extra allocation... Can we avoid this, maybe with a DST?
|
||||||
|
|
|
@ -330,11 +330,7 @@ impl<'gc> DisplayObject<'gc> for MovieClip<'gc> {
|
||||||
|
|
||||||
fn render(&self, context: &mut RenderContext<'_, 'gc>) {
|
fn render(&self, context: &mut RenderContext<'_, 'gc>) {
|
||||||
context.transform_stack.push(self.transform());
|
context.transform_stack.push(self.transform());
|
||||||
|
crate::display_object::render_children(context, &self.children);
|
||||||
for child in self.children.values() {
|
|
||||||
child.read().render(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.transform_stack.pop();
|
context.transform_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,6 +1004,9 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
character
|
character
|
||||||
.write(context.gc_context)
|
.write(context.gc_context)
|
||||||
.set_color_transform(prev_character.read().color_transform());
|
.set_color_transform(prev_character.read().color_transform());
|
||||||
|
character
|
||||||
|
.write(context.gc_context)
|
||||||
|
.set_clip_depth(prev_character.read().clip_depth());
|
||||||
}
|
}
|
||||||
character
|
character
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,6 +431,7 @@ impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
||||||
library: gc_root.library.read(),
|
library: gc_root.library.read(),
|
||||||
transform_stack,
|
transform_stack,
|
||||||
view_bounds,
|
view_bounds,
|
||||||
|
clip_depth_stack: vec![],
|
||||||
};
|
};
|
||||||
gc_root.root.read().render(&mut render_context);
|
gc_root.root.read().render(&mut render_context);
|
||||||
});
|
});
|
||||||
|
@ -543,4 +544,5 @@ pub struct RenderContext<'a, 'gc> {
|
||||||
pub library: std::cell::Ref<'a, Library<'gc>>,
|
pub library: std::cell::Ref<'a, Library<'gc>>,
|
||||||
pub transform_stack: &'a mut TransformStack,
|
pub transform_stack: &'a mut TransformStack,
|
||||||
pub view_bounds: BoundingBox,
|
pub view_bounds: BoundingBox,
|
||||||
|
pub clip_depth_stack: Vec<Depth>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.with_vsync(true)
|
.with_vsync(true)
|
||||||
.with_multisampling(4)
|
.with_multisampling(4)
|
||||||
.with_srgb(true)
|
.with_srgb(true)
|
||||||
|
.with_stencil_buffer(8)
|
||||||
.build_windowed(window_builder, &events_loop)?;
|
.build_windowed(window_builder, &events_loop)?;
|
||||||
let audio = audio::RodioAudioBackend::new()?;
|
let audio = audio::RodioAudioBackend::new()?;
|
||||||
let renderer = GliumRenderBackend::new(windowed_context)?;
|
let renderer = GliumRenderBackend::new(windowed_context)?;
|
||||||
|
|
|
@ -22,6 +22,12 @@ pub struct GliumRenderBackend {
|
||||||
bitmap_shader_program: glium::Program,
|
bitmap_shader_program: glium::Program,
|
||||||
meshes: Vec<Mesh>,
|
meshes: Vec<Mesh>,
|
||||||
textures: Vec<(swf::CharacterId, Texture)>,
|
textures: Vec<(swf::CharacterId, Texture)>,
|
||||||
|
num_masks: u32,
|
||||||
|
num_masks_active: u32,
|
||||||
|
write_stencil_mask: u32,
|
||||||
|
test_stencil_mask: u32,
|
||||||
|
next_stencil_mask: u32,
|
||||||
|
mask_stack: Vec<(u32, u32)>,
|
||||||
viewport_width: f32,
|
viewport_width: f32,
|
||||||
viewport_height: f32,
|
viewport_height: f32,
|
||||||
view_matrix: [[f32; 4]; 4],
|
view_matrix: [[f32; 4]; 4],
|
||||||
|
@ -87,6 +93,12 @@ impl GliumRenderBackend {
|
||||||
viewport_width: 500.0,
|
viewport_width: 500.0,
|
||||||
viewport_height: 500.0,
|
viewport_height: 500.0,
|
||||||
view_matrix: [[0.0; 4]; 4],
|
view_matrix: [[0.0; 4]; 4],
|
||||||
|
num_masks: 0,
|
||||||
|
num_masks_active: 0,
|
||||||
|
write_stencil_mask: 0,
|
||||||
|
test_stencil_mask: 0,
|
||||||
|
next_stencil_mask: 1,
|
||||||
|
mask_stack: vec![],
|
||||||
};
|
};
|
||||||
renderer.build_matrices();
|
renderer.build_matrices();
|
||||||
Ok(renderer)
|
Ok(renderer)
|
||||||
|
@ -104,9 +116,6 @@ impl GliumRenderBackend {
|
||||||
|
|
||||||
let mut mesh = Mesh { draws: vec![] };
|
let mut mesh = Mesh { draws: vec![] };
|
||||||
|
|
||||||
//let mut vertices: Vec<Vertex> = vec![];
|
|
||||||
//let mut indices: Vec<u32> = vec![];
|
|
||||||
|
|
||||||
let mut fill_tess = FillTessellator::new();
|
let mut fill_tess = FillTessellator::new();
|
||||||
let mut stroke_tess = StrokeTessellator::new();
|
let mut stroke_tess = StrokeTessellator::new();
|
||||||
let mut lyon_mesh: VertexBuffers<_, u32> = VertexBuffers::new();
|
let mut lyon_mesh: VertexBuffers<_, u32> = VertexBuffers::new();
|
||||||
|
@ -571,22 +580,29 @@ impl RenderBackend for GliumRenderBackend {
|
||||||
fn begin_frame(&mut self) {
|
fn begin_frame(&mut self) {
|
||||||
assert!(self.target.is_none());
|
assert!(self.target.is_none());
|
||||||
self.target = Some(self.display.draw());
|
self.target = Some(self.display.draw());
|
||||||
|
self.num_masks = 0;
|
||||||
|
self.num_masks_active = 0;
|
||||||
|
self.write_stencil_mask = 0;
|
||||||
|
self.test_stencil_mask = 0;
|
||||||
|
self.next_stencil_mask = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_frame(&mut self) {
|
fn end_frame(&mut self) {
|
||||||
assert!(self.target.is_some());
|
assert!(self.target.is_some());
|
||||||
|
|
||||||
let target = self.target.take().unwrap();
|
let target = self.target.take().unwrap();
|
||||||
target.finish().unwrap();
|
target.finish().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&mut self, color: Color) {
|
fn clear(&mut self, color: Color) {
|
||||||
let target = self.target.as_mut().unwrap();
|
let target = self.target.as_mut().unwrap();
|
||||||
target.clear_color_srgb(
|
target.clear_color_srgb_and_stencil(
|
||||||
|
(
|
||||||
f32::from(color.r) / 255.0,
|
f32::from(color.r) / 255.0,
|
||||||
f32::from(color.g) / 255.0,
|
f32::from(color.g) / 255.0,
|
||||||
f32::from(color.b) / 255.0,
|
f32::from(color.b) / 255.0,
|
||||||
f32::from(color.a) / 255.0,
|
f32::from(color.a) / 255.0,
|
||||||
|
),
|
||||||
|
0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,16 +637,27 @@ impl RenderBackend for GliumRenderBackend {
|
||||||
transform.color_transform.a_add,
|
transform.color_transform.a_add,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let mut draw_parameters = DrawParameters::default();
|
||||||
|
mask_draw_parameters(
|
||||||
|
&mut draw_parameters,
|
||||||
|
self.num_masks,
|
||||||
|
self.num_masks_active,
|
||||||
|
self.write_stencil_mask,
|
||||||
|
self.test_stencil_mask,
|
||||||
|
);
|
||||||
|
|
||||||
for draw in &mesh.draws {
|
for draw in &mesh.draws {
|
||||||
match &draw.draw_type {
|
match &draw.draw_type {
|
||||||
DrawType::Color => {
|
DrawType::Color => {
|
||||||
|
draw_parameters.blend = color_blend();
|
||||||
|
|
||||||
target
|
target
|
||||||
.draw(
|
.draw(
|
||||||
&draw.vertex_buffer,
|
&draw.vertex_buffer,
|
||||||
&draw.index_buffer,
|
&draw.index_buffer,
|
||||||
&self.shader_program,
|
&self.shader_program,
|
||||||
&uniform! { view_matrix: self.view_matrix, world_matrix: world_matrix, mult_color: mult_color, add_color: add_color },
|
&uniform! { view_matrix: self.view_matrix, world_matrix: world_matrix, mult_color: mult_color, add_color: add_color },
|
||||||
&color_draw_parameters()
|
&draw_parameters
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -643,13 +670,15 @@ impl RenderBackend for GliumRenderBackend {
|
||||||
gradient: gradient_uniforms.clone(),
|
gradient: gradient_uniforms.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
draw_parameters.blend = color_blend();
|
||||||
|
|
||||||
target
|
target
|
||||||
.draw(
|
.draw(
|
||||||
&draw.vertex_buffer,
|
&draw.vertex_buffer,
|
||||||
&draw.index_buffer,
|
&draw.index_buffer,
|
||||||
&self.gradient_shader_program,
|
&self.gradient_shader_program,
|
||||||
&uniforms,
|
&uniforms,
|
||||||
&color_draw_parameters(),
|
&draw_parameters,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -697,13 +726,15 @@ impl RenderBackend for GliumRenderBackend {
|
||||||
texture,
|
texture,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
draw_parameters.blend = bitmap_blend();
|
||||||
|
|
||||||
target
|
target
|
||||||
.draw(
|
.draw(
|
||||||
&draw.vertex_buffer,
|
&draw.vertex_buffer,
|
||||||
&draw.index_buffer,
|
&draw.index_buffer,
|
||||||
&self.bitmap_shader_program,
|
&self.bitmap_shader_program,
|
||||||
&uniforms,
|
&uniforms,
|
||||||
&bitmap_draw_parameters(),
|
&draw_parameters,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -772,6 +803,44 @@ impl RenderBackend for GliumRenderBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn push_mask(&mut self) {
|
||||||
|
// Desktop draws the masker to the stencil buffer, one bit per mask.
|
||||||
|
// Masks-within-masks are handled as a bitmask.
|
||||||
|
// This does unfortunately mean we are limited in the number of masks at once (usually 8 bits).
|
||||||
|
if self.next_stencil_mask == 0 {
|
||||||
|
// If we've reached the limit of masks, clear the stencil buffer and start over.
|
||||||
|
// But this may not be correct if there is still a mask active (mask-within-mask).
|
||||||
|
let target = self.target.as_mut().unwrap();
|
||||||
|
if self.test_stencil_mask != 0 {
|
||||||
|
log::warn!(
|
||||||
|
"Too many masks active for stencil buffer; possibly inccorect rendering"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.next_stencil_mask = 0;
|
||||||
|
target.clear_stencil(self.test_stencil_mask as i32);
|
||||||
|
}
|
||||||
|
self.num_masks += 1;
|
||||||
|
self.mask_stack
|
||||||
|
.push((self.write_stencil_mask, self.test_stencil_mask));
|
||||||
|
self.write_stencil_mask = self.next_stencil_mask;
|
||||||
|
self.test_stencil_mask |= self.next_stencil_mask;
|
||||||
|
self.next_stencil_mask <<= 1;
|
||||||
|
}
|
||||||
|
fn activate_mask(&mut self) {
|
||||||
|
self.num_masks_active += 1;
|
||||||
|
}
|
||||||
|
fn pop_mask(&mut self) {
|
||||||
|
if !self.mask_stack.is_empty() {
|
||||||
|
self.num_masks -= 1;
|
||||||
|
self.num_masks_active -= 1;
|
||||||
|
let (write, test) = self.mask_stack.pop().unwrap();
|
||||||
|
self.write_stencil_mask = write;
|
||||||
|
self.test_stencil_mask = test;
|
||||||
|
} else {
|
||||||
|
log::warn!("Mask stack underflow\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Texture {
|
struct Texture {
|
||||||
|
@ -1124,21 +1193,65 @@ fn swf_bitmap_to_gl_matrix(m: swf::Matrix, bitmap_width: u32, bitmap_height: u32
|
||||||
[[a, d, 0.0], [b, e, 0.0], [c, f, 1.0]]
|
[[a, d, 0.0], [b, e, 0.0], [c, f, 1.0]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the drawing parameters for masking.
|
||||||
|
#[inline]
|
||||||
|
fn mask_draw_parameters(
|
||||||
|
params: &mut DrawParameters,
|
||||||
|
num_masks: u32,
|
||||||
|
num_masks_active: u32,
|
||||||
|
write_stencil_mask: u32,
|
||||||
|
test_stencil_mask: u32,
|
||||||
|
) {
|
||||||
|
use glium::draw_parameters::{Stencil, StencilOperation, StencilTest};
|
||||||
|
if num_masks > 0 {
|
||||||
|
let (value, test, pass_op, color_mask, write_mask) = if num_masks_active < num_masks {
|
||||||
|
(
|
||||||
|
write_stencil_mask as i32,
|
||||||
|
StencilTest::AlwaysPass,
|
||||||
|
StencilOperation::Replace,
|
||||||
|
(false, false, false, false),
|
||||||
|
write_stencil_mask,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
test_stencil_mask as i32,
|
||||||
|
StencilTest::IfEqual {
|
||||||
|
mask: test_stencil_mask,
|
||||||
|
},
|
||||||
|
StencilOperation::Keep,
|
||||||
|
(true, true, true, true),
|
||||||
|
test_stencil_mask,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
params.color_mask = color_mask;
|
||||||
|
params.stencil = Stencil {
|
||||||
|
test_clockwise: test,
|
||||||
|
reference_value_clockwise: value,
|
||||||
|
write_mask_clockwise: write_mask,
|
||||||
|
fail_operation_clockwise: StencilOperation::Keep,
|
||||||
|
pass_depth_fail_operation_clockwise: StencilOperation::Keep,
|
||||||
|
depth_pass_operation_clockwise: pass_op,
|
||||||
|
test_counter_clockwise: test,
|
||||||
|
reference_value_counter_clockwise: value,
|
||||||
|
write_mask_counter_clockwise: write_mask,
|
||||||
|
fail_operation_counter_clockwise: StencilOperation::Keep,
|
||||||
|
pass_depth_fail_operation_counter_clockwise: StencilOperation::Keep,
|
||||||
|
depth_pass_operation_counter_clockwise: pass_op,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the drawing parameters for standard color/gradient fills.
|
/// Returns the drawing parameters for standard color/gradient fills.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn color_draw_parameters() -> DrawParameters<'static> {
|
fn color_blend() -> glium::Blend {
|
||||||
DrawParameters {
|
glium::Blend::alpha_blending()
|
||||||
blend: glium::Blend::alpha_blending(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the drawing parameters for bitmaps with pre-multipled alpha.
|
/// Returns the drawing parameters for bitmaps with pre-multipled alpha.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitmap_draw_parameters() -> DrawParameters<'static> {
|
fn bitmap_blend() -> glium::Blend {
|
||||||
use glium::{BlendingFunction, LinearBlendingFactor};
|
use glium::{BlendingFunction, LinearBlendingFactor};
|
||||||
DrawParameters {
|
glium::Blend {
|
||||||
blend: glium::Blend {
|
|
||||||
color: BlendingFunction::Addition {
|
color: BlendingFunction::Addition {
|
||||||
source: LinearBlendingFactor::One,
|
source: LinearBlendingFactor::One,
|
||||||
destination: LinearBlendingFactor::OneMinusSourceAlpha,
|
destination: LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
|
@ -1148,7 +1261,5 @@ fn bitmap_draw_parameters() -> DrawParameters<'static> {
|
||||||
destination: LinearBlendingFactor::OneMinusSourceAlpha,
|
destination: LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,6 +440,10 @@ impl RenderBackend for WebCanvasRenderBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn push_mask(&mut self) {}
|
||||||
|
fn activate_mask(&mut self) {}
|
||||||
|
fn pop_mask(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swf_shape_to_svg(
|
fn swf_shape_to_svg(
|
||||||
|
|
Loading…
Reference in New Issue