wgpu: Introduce ShapeTessellator temporarily
Eventually it'll be replaced with common_tess's one.
This commit is contained in:
parent
4513a5fbda
commit
c1c9542a95
|
@ -90,6 +90,7 @@ pub struct WgpuRenderBackend<T: RenderTarget> {
|
||||||
current_frame: Option<Frame<'static, T>>,
|
current_frame: Option<Frame<'static, T>>,
|
||||||
meshes: Vec<Mesh>,
|
meshes: Vec<Mesh>,
|
||||||
mask_state: MaskState,
|
mask_state: MaskState,
|
||||||
|
shape_tessellator: ShapeTessellator,
|
||||||
textures: Vec<Texture>,
|
textures: Vec<Texture>,
|
||||||
num_masks: u32,
|
num_masks: u32,
|
||||||
quad_vbo: wgpu::Buffer,
|
quad_vbo: wgpu::Buffer,
|
||||||
|
@ -177,6 +178,301 @@ struct IncompleteDraw {
|
||||||
indices: Vec<u32>,
|
indices: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ShapeTessellator {
|
||||||
|
fill_tess: FillTessellator,
|
||||||
|
stroke_tess: StrokeTessellator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShapeTessellator {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
fill_tess: FillTessellator::new(),
|
||||||
|
stroke_tess: StrokeTessellator::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tessellate_shape<F>(&mut self, shape: DistilledShape, get_bitmap: F) -> Vec<IncompleteDraw>
|
||||||
|
where
|
||||||
|
F: Fn(swf::CharacterId) -> Option<(u32, u32, BitmapHandle)>,
|
||||||
|
{
|
||||||
|
use lyon::tessellation::{FillOptions, StrokeOptions};
|
||||||
|
|
||||||
|
let mut draws = Vec::new();
|
||||||
|
|
||||||
|
let mut lyon_mesh: VertexBuffers<_, u32> = VertexBuffers::new();
|
||||||
|
|
||||||
|
fn flush_draw(
|
||||||
|
draw: IncompleteDrawType,
|
||||||
|
draws: &mut Vec<IncompleteDraw>,
|
||||||
|
lyon_mesh: &mut VertexBuffers<GpuVertex, u32>,
|
||||||
|
) {
|
||||||
|
if lyon_mesh.vertices.is_empty() || lyon_mesh.indices.len() < 3 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let draw_mesh = std::mem::replace(lyon_mesh, VertexBuffers::new());
|
||||||
|
draws.push(IncompleteDraw {
|
||||||
|
draw,
|
||||||
|
vertices: draw_mesh.vertices,
|
||||||
|
indices: draw_mesh.indices,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for path in shape.paths {
|
||||||
|
match path {
|
||||||
|
DrawPath::Fill { style, commands } => match style {
|
||||||
|
FillStyle::Color(color) => {
|
||||||
|
let color = [
|
||||||
|
f32::from(color.r) / 255.0,
|
||||||
|
f32::from(color.g) / 255.0,
|
||||||
|
f32::from(color.b) / 255.0,
|
||||||
|
f32::from(color.a) / 255.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut buffers_builder =
|
||||||
|
BuffersBuilder::new(&mut lyon_mesh, RuffleVertexCtor { color });
|
||||||
|
|
||||||
|
if let Err(e) = self.fill_tess.tessellate_path(
|
||||||
|
&ruffle_path_to_lyon_path(commands, true),
|
||||||
|
&FillOptions::even_odd(),
|
||||||
|
&mut buffers_builder,
|
||||||
|
) {
|
||||||
|
// This may just be a degenerate path; skip it.
|
||||||
|
log::error!("Tessellation failure: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FillStyle::LinearGradient(gradient) => {
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Color,
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buffers_builder = BuffersBuilder::new(
|
||||||
|
&mut lyon_mesh,
|
||||||
|
RuffleVertexCtor {
|
||||||
|
color: [1.0, 1.0, 1.0, 1.0],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = self.fill_tess.tessellate_path(
|
||||||
|
&ruffle_path_to_lyon_path(commands, true),
|
||||||
|
&FillOptions::even_odd(),
|
||||||
|
&mut buffers_builder,
|
||||||
|
) {
|
||||||
|
// This may just be a degenerate path; skip it.
|
||||||
|
log::error!("Tessellation failure: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uniforms = swf_gradient_to_uniforms(0, gradient, 0.0);
|
||||||
|
let matrix = swf_to_gl_matrix(gradient.matrix);
|
||||||
|
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Gradient {
|
||||||
|
texture_transform: matrix,
|
||||||
|
gradient: uniforms,
|
||||||
|
},
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FillStyle::RadialGradient(gradient) => {
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Color,
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buffers_builder = BuffersBuilder::new(
|
||||||
|
&mut lyon_mesh,
|
||||||
|
RuffleVertexCtor {
|
||||||
|
color: [1.0, 1.0, 1.0, 1.0],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = self.fill_tess.tessellate_path(
|
||||||
|
&ruffle_path_to_lyon_path(commands, true),
|
||||||
|
&FillOptions::even_odd(),
|
||||||
|
&mut buffers_builder,
|
||||||
|
) {
|
||||||
|
// This may just be a degenerate path; skip it.
|
||||||
|
log::error!("Tessellation failure: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uniforms = swf_gradient_to_uniforms(1, gradient, 0.0);
|
||||||
|
let matrix = swf_to_gl_matrix(gradient.matrix);
|
||||||
|
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Gradient {
|
||||||
|
texture_transform: matrix,
|
||||||
|
gradient: uniforms,
|
||||||
|
},
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FillStyle::FocalGradient {
|
||||||
|
gradient,
|
||||||
|
focal_point,
|
||||||
|
} => {
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Color,
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buffers_builder = BuffersBuilder::new(
|
||||||
|
&mut lyon_mesh,
|
||||||
|
RuffleVertexCtor {
|
||||||
|
color: [1.0, 1.0, 1.0, 1.0],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = self.fill_tess.tessellate_path(
|
||||||
|
&ruffle_path_to_lyon_path(commands, true),
|
||||||
|
&FillOptions::even_odd(),
|
||||||
|
&mut buffers_builder,
|
||||||
|
) {
|
||||||
|
// This may just be a degenerate path; skip it.
|
||||||
|
log::error!("Tessellation failure: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uniforms = swf_gradient_to_uniforms(2, gradient, *focal_point);
|
||||||
|
let matrix = swf_to_gl_matrix(gradient.matrix);
|
||||||
|
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Gradient {
|
||||||
|
texture_transform: matrix,
|
||||||
|
gradient: uniforms,
|
||||||
|
},
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FillStyle::Bitmap {
|
||||||
|
id,
|
||||||
|
matrix,
|
||||||
|
is_smoothed,
|
||||||
|
is_repeating,
|
||||||
|
} => {
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Color,
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buffers_builder = BuffersBuilder::new(
|
||||||
|
&mut lyon_mesh,
|
||||||
|
RuffleVertexCtor {
|
||||||
|
color: [1.0, 1.0, 1.0, 1.0],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = self.fill_tess.tessellate_path(
|
||||||
|
&ruffle_path_to_lyon_path(commands, true),
|
||||||
|
&FillOptions::even_odd(),
|
||||||
|
&mut buffers_builder,
|
||||||
|
) {
|
||||||
|
// This may just be a degenerate path; skip it.
|
||||||
|
log::error!("Tessellation failure: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((bitmap_width, bitmap_height, bitmap)) = get_bitmap(*id) {
|
||||||
|
let bitmap = IncompleteDrawType::Bitmap {
|
||||||
|
texture_transform: swf_bitmap_to_gl_matrix(
|
||||||
|
*matrix,
|
||||||
|
bitmap_width,
|
||||||
|
bitmap_height,
|
||||||
|
),
|
||||||
|
bitmap,
|
||||||
|
is_smoothed: *is_smoothed,
|
||||||
|
is_repeating: *is_repeating,
|
||||||
|
};
|
||||||
|
|
||||||
|
flush_draw(bitmap, &mut draws, &mut lyon_mesh);
|
||||||
|
} else {
|
||||||
|
log::error!("Couldn't fill shape with unknown bitmap {}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DrawPath::Stroke {
|
||||||
|
style,
|
||||||
|
commands,
|
||||||
|
is_closed,
|
||||||
|
} => {
|
||||||
|
let color = [
|
||||||
|
f32::from(style.color.r) / 255.0,
|
||||||
|
f32::from(style.color.g) / 255.0,
|
||||||
|
f32::from(style.color.b) / 255.0,
|
||||||
|
f32::from(style.color.a) / 255.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut buffers_builder =
|
||||||
|
BuffersBuilder::new(&mut lyon_mesh, RuffleVertexCtor { color });
|
||||||
|
|
||||||
|
// TODO(Herschel): 0 width indicates "hairline".
|
||||||
|
let width = if style.width.to_pixels() >= 1.0 {
|
||||||
|
style.width.to_pixels() as f32
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut options = StrokeOptions::default()
|
||||||
|
.with_line_width(width)
|
||||||
|
.with_start_cap(match style.start_cap {
|
||||||
|
swf::LineCapStyle::None => tessellation::LineCap::Butt,
|
||||||
|
swf::LineCapStyle::Round => tessellation::LineCap::Round,
|
||||||
|
swf::LineCapStyle::Square => tessellation::LineCap::Square,
|
||||||
|
})
|
||||||
|
.with_end_cap(match style.end_cap {
|
||||||
|
swf::LineCapStyle::None => tessellation::LineCap::Butt,
|
||||||
|
swf::LineCapStyle::Round => tessellation::LineCap::Round,
|
||||||
|
swf::LineCapStyle::Square => tessellation::LineCap::Square,
|
||||||
|
});
|
||||||
|
|
||||||
|
let line_join = match style.join_style {
|
||||||
|
swf::LineJoinStyle::Round => tessellation::LineJoin::Round,
|
||||||
|
swf::LineJoinStyle::Bevel => tessellation::LineJoin::Bevel,
|
||||||
|
swf::LineJoinStyle::Miter(limit) => {
|
||||||
|
// Avoid lyon assert with small miter limits.
|
||||||
|
if limit >= StrokeOptions::MINIMUM_MITER_LIMIT {
|
||||||
|
options = options.with_miter_limit(limit);
|
||||||
|
tessellation::LineJoin::MiterClip
|
||||||
|
} else {
|
||||||
|
tessellation::LineJoin::Bevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
options = options.with_line_join(line_join);
|
||||||
|
|
||||||
|
if let Err(e) = self.stroke_tess.tessellate_path(
|
||||||
|
&ruffle_path_to_lyon_path(commands, is_closed),
|
||||||
|
&options,
|
||||||
|
&mut buffers_builder,
|
||||||
|
) {
|
||||||
|
// This may just be a degenerate path; skip it.
|
||||||
|
log::error!("Tessellation failure: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flush_draw(
|
||||||
|
IncompleteDrawType::Color,
|
||||||
|
&mut draws,
|
||||||
|
&mut lyon_mesh,
|
||||||
|
);
|
||||||
|
|
||||||
|
draws
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WgpuRenderBackend<SwapChainTarget> {
|
impl WgpuRenderBackend<SwapChainTarget> {
|
||||||
pub fn for_window<W: HasRawWindowHandle>(
|
pub fn for_window<W: HasRawWindowHandle>(
|
||||||
window: &W,
|
window: &W,
|
||||||
|
@ -272,6 +568,7 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
||||||
depth_texture_view,
|
depth_texture_view,
|
||||||
current_frame: None,
|
current_frame: None,
|
||||||
meshes: Vec::new(),
|
meshes: Vec::new(),
|
||||||
|
shape_tessellator: ShapeTessellator::new(),
|
||||||
textures: Vec::new(),
|
textures: Vec::new(),
|
||||||
|
|
||||||
num_masks: 0,
|
num_masks: 0,
|
||||||
|
@ -324,290 +621,6 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
||||||
self.descriptors
|
self.descriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tessellate_shape<F>(&self, shape: DistilledShape, get_bitmap: F) -> Vec<IncompleteDraw>
|
|
||||||
where
|
|
||||||
F: Fn(swf::CharacterId) -> Option<(u32, u32, BitmapHandle)>,
|
|
||||||
{
|
|
||||||
use lyon::tessellation::{FillOptions, StrokeOptions};
|
|
||||||
|
|
||||||
let mut draws = Vec::new();
|
|
||||||
|
|
||||||
let mut fill_tess = FillTessellator::new();
|
|
||||||
let mut stroke_tess = StrokeTessellator::new();
|
|
||||||
|
|
||||||
let mut lyon_mesh: VertexBuffers<_, u32> = VertexBuffers::new();
|
|
||||||
|
|
||||||
fn flush_draw(
|
|
||||||
draw: IncompleteDrawType,
|
|
||||||
draws: &mut Vec<IncompleteDraw>,
|
|
||||||
lyon_mesh: &mut VertexBuffers<GpuVertex, u32>,
|
|
||||||
) {
|
|
||||||
if lyon_mesh.vertices.is_empty() || lyon_mesh.indices.len() < 3 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let draw_mesh = std::mem::replace(lyon_mesh, VertexBuffers::new());
|
|
||||||
draws.push(IncompleteDraw {
|
|
||||||
draw,
|
|
||||||
vertices: draw_mesh.vertices,
|
|
||||||
indices: draw_mesh.indices,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for path in shape.paths {
|
|
||||||
match path {
|
|
||||||
DrawPath::Fill { style, commands } => match style {
|
|
||||||
FillStyle::Color(color) => {
|
|
||||||
let color = [
|
|
||||||
f32::from(color.r) / 255.0,
|
|
||||||
f32::from(color.g) / 255.0,
|
|
||||||
f32::from(color.b) / 255.0,
|
|
||||||
f32::from(color.a) / 255.0,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut buffers_builder =
|
|
||||||
BuffersBuilder::new(&mut lyon_mesh, RuffleVertexCtor { color });
|
|
||||||
|
|
||||||
if let Err(e) = fill_tess.tessellate_path(
|
|
||||||
&ruffle_path_to_lyon_path(commands, true),
|
|
||||||
&FillOptions::even_odd(),
|
|
||||||
&mut buffers_builder,
|
|
||||||
) {
|
|
||||||
// This may just be a degenerate path; skip it.
|
|
||||||
log::error!("Tessellation failure: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FillStyle::LinearGradient(gradient) => {
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Color,
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut buffers_builder = BuffersBuilder::new(
|
|
||||||
&mut lyon_mesh,
|
|
||||||
RuffleVertexCtor {
|
|
||||||
color: [1.0, 1.0, 1.0, 1.0],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(e) = fill_tess.tessellate_path(
|
|
||||||
&ruffle_path_to_lyon_path(commands, true),
|
|
||||||
&FillOptions::even_odd(),
|
|
||||||
&mut buffers_builder,
|
|
||||||
) {
|
|
||||||
// This may just be a degenerate path; skip it.
|
|
||||||
log::error!("Tessellation failure: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let uniforms = swf_gradient_to_uniforms(0, gradient, 0.0);
|
|
||||||
let matrix = swf_to_gl_matrix(gradient.matrix);
|
|
||||||
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Gradient {
|
|
||||||
texture_transform: matrix,
|
|
||||||
gradient: uniforms,
|
|
||||||
},
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
FillStyle::RadialGradient(gradient) => {
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Color,
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut buffers_builder = BuffersBuilder::new(
|
|
||||||
&mut lyon_mesh,
|
|
||||||
RuffleVertexCtor {
|
|
||||||
color: [1.0, 1.0, 1.0, 1.0],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(e) = fill_tess.tessellate_path(
|
|
||||||
&ruffle_path_to_lyon_path(commands, true),
|
|
||||||
&FillOptions::even_odd(),
|
|
||||||
&mut buffers_builder,
|
|
||||||
) {
|
|
||||||
// This may just be a degenerate path; skip it.
|
|
||||||
log::error!("Tessellation failure: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let uniforms = swf_gradient_to_uniforms(1, gradient, 0.0);
|
|
||||||
let matrix = swf_to_gl_matrix(gradient.matrix);
|
|
||||||
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Gradient {
|
|
||||||
texture_transform: matrix,
|
|
||||||
gradient: uniforms,
|
|
||||||
},
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
FillStyle::FocalGradient {
|
|
||||||
gradient,
|
|
||||||
focal_point,
|
|
||||||
} => {
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Color,
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut buffers_builder = BuffersBuilder::new(
|
|
||||||
&mut lyon_mesh,
|
|
||||||
RuffleVertexCtor {
|
|
||||||
color: [1.0, 1.0, 1.0, 1.0],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(e) = fill_tess.tessellate_path(
|
|
||||||
&ruffle_path_to_lyon_path(commands, true),
|
|
||||||
&FillOptions::even_odd(),
|
|
||||||
&mut buffers_builder,
|
|
||||||
) {
|
|
||||||
// This may just be a degenerate path; skip it.
|
|
||||||
log::error!("Tessellation failure: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let uniforms = swf_gradient_to_uniforms(2, gradient, *focal_point);
|
|
||||||
let matrix = swf_to_gl_matrix(gradient.matrix);
|
|
||||||
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Gradient {
|
|
||||||
texture_transform: matrix,
|
|
||||||
gradient: uniforms,
|
|
||||||
},
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
FillStyle::Bitmap {
|
|
||||||
id,
|
|
||||||
matrix,
|
|
||||||
is_smoothed,
|
|
||||||
is_repeating,
|
|
||||||
} => {
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Color,
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut buffers_builder = BuffersBuilder::new(
|
|
||||||
&mut lyon_mesh,
|
|
||||||
RuffleVertexCtor {
|
|
||||||
color: [1.0, 1.0, 1.0, 1.0],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(e) = fill_tess.tessellate_path(
|
|
||||||
&ruffle_path_to_lyon_path(commands, true),
|
|
||||||
&FillOptions::even_odd(),
|
|
||||||
&mut buffers_builder,
|
|
||||||
) {
|
|
||||||
// This may just be a degenerate path; skip it.
|
|
||||||
log::error!("Tessellation failure: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((bitmap_width, bitmap_height, bitmap)) = get_bitmap(*id) {
|
|
||||||
let bitmap = IncompleteDrawType::Bitmap {
|
|
||||||
texture_transform: swf_bitmap_to_gl_matrix(
|
|
||||||
*matrix,
|
|
||||||
bitmap_width,
|
|
||||||
bitmap_height,
|
|
||||||
),
|
|
||||||
bitmap,
|
|
||||||
is_smoothed: *is_smoothed,
|
|
||||||
is_repeating: *is_repeating,
|
|
||||||
};
|
|
||||||
|
|
||||||
flush_draw(bitmap, &mut draws, &mut lyon_mesh);
|
|
||||||
} else {
|
|
||||||
log::error!("Couldn't fill shape with unknown bitmap {}", id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DrawPath::Stroke {
|
|
||||||
style,
|
|
||||||
commands,
|
|
||||||
is_closed,
|
|
||||||
} => {
|
|
||||||
let color = [
|
|
||||||
f32::from(style.color.r) / 255.0,
|
|
||||||
f32::from(style.color.g) / 255.0,
|
|
||||||
f32::from(style.color.b) / 255.0,
|
|
||||||
f32::from(style.color.a) / 255.0,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut buffers_builder =
|
|
||||||
BuffersBuilder::new(&mut lyon_mesh, RuffleVertexCtor { color });
|
|
||||||
|
|
||||||
// TODO(Herschel): 0 width indicates "hairline".
|
|
||||||
let width = if style.width.to_pixels() >= 1.0 {
|
|
||||||
style.width.to_pixels() as f32
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut options = StrokeOptions::default()
|
|
||||||
.with_line_width(width)
|
|
||||||
.with_start_cap(match style.start_cap {
|
|
||||||
swf::LineCapStyle::None => tessellation::LineCap::Butt,
|
|
||||||
swf::LineCapStyle::Round => tessellation::LineCap::Round,
|
|
||||||
swf::LineCapStyle::Square => tessellation::LineCap::Square,
|
|
||||||
})
|
|
||||||
.with_end_cap(match style.end_cap {
|
|
||||||
swf::LineCapStyle::None => tessellation::LineCap::Butt,
|
|
||||||
swf::LineCapStyle::Round => tessellation::LineCap::Round,
|
|
||||||
swf::LineCapStyle::Square => tessellation::LineCap::Square,
|
|
||||||
});
|
|
||||||
|
|
||||||
let line_join = match style.join_style {
|
|
||||||
swf::LineJoinStyle::Round => tessellation::LineJoin::Round,
|
|
||||||
swf::LineJoinStyle::Bevel => tessellation::LineJoin::Bevel,
|
|
||||||
swf::LineJoinStyle::Miter(limit) => {
|
|
||||||
// Avoid lyon assert with small miter limits.
|
|
||||||
if limit >= StrokeOptions::MINIMUM_MITER_LIMIT {
|
|
||||||
options = options.with_miter_limit(limit);
|
|
||||||
tessellation::LineJoin::MiterClip
|
|
||||||
} else {
|
|
||||||
tessellation::LineJoin::Bevel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
options = options.with_line_join(line_join);
|
|
||||||
|
|
||||||
if let Err(e) = stroke_tess.tessellate_path(
|
|
||||||
&ruffle_path_to_lyon_path(commands, is_closed),
|
|
||||||
&options,
|
|
||||||
&mut buffers_builder,
|
|
||||||
) {
|
|
||||||
// This may just be a degenerate path; skip it.
|
|
||||||
log::error!("Tessellation failure: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flush_draw(
|
|
||||||
IncompleteDrawType::Color,
|
|
||||||
&mut draws,
|
|
||||||
&mut lyon_mesh,
|
|
||||||
);
|
|
||||||
|
|
||||||
draws
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_shape_internal(
|
fn register_shape_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
shape: DistilledShape,
|
shape: DistilledShape,
|
||||||
|
@ -615,7 +628,7 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
||||||
) -> Mesh {
|
) -> Mesh {
|
||||||
let shape_id = shape.id; // TODO: remove?
|
let shape_id = shape.id; // TODO: remove?
|
||||||
let textures = &self.textures;
|
let textures = &self.textures;
|
||||||
let lyon_meshes = self.tessellate_shape(shape, |id| {
|
let lyon_meshes = self.shape_tessellator.tessellate_shape(shape, |id| {
|
||||||
library
|
library
|
||||||
.and_then(|lib| lib.get_bitmap(id))
|
.and_then(|lib| lib.get_bitmap(id))
|
||||||
.and_then(|bitmap| {
|
.and_then(|bitmap| {
|
||||||
|
|
Loading…
Reference in New Issue