diff options
Diffstat (limited to 'wgpu')
-rw-r--r-- | wgpu/src/geometry.rs | 38 | ||||
-rw-r--r-- | wgpu/src/image/vector.rs | 30 | ||||
-rw-r--r-- | wgpu/src/lib.rs | 1 | ||||
-rw-r--r-- | wgpu/src/shader/quad.wgsl | 14 |
4 files changed, 67 insertions, 16 deletions
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index be65ba36..8e6f77d7 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -253,6 +253,44 @@ impl geometry::frame::Backend for Frame { .expect("Stroke path"); } + fn stroke_rectangle<'a>( + &mut self, + top_left: Point, + size: Size, + stroke: impl Into<Stroke<'a>>, + ) { + let stroke = stroke.into(); + + let mut buffer = self + .buffers + .get_stroke(&self.transforms.current.transform_style(stroke.style)); + + let top_left = self + .transforms + .current + .0 + .transform_point(lyon::math::Point::new(top_left.x, top_left.y)); + + let size = + self.transforms.current.0.transform_vector( + lyon::math::Vector::new(size.width, size.height), + ); + + let mut options = tessellation::StrokeOptions::default(); + options.line_width = stroke.width; + options.start_cap = into_line_cap(stroke.line_cap); + options.end_cap = into_line_cap(stroke.line_cap); + options.line_join = into_line_join(stroke.line_join); + + self.stroke_tessellator + .tessellate_rectangle( + &lyon::math::Box2D::new(top_left, top_left + size), + &options, + buffer.as_mut(), + ) + .expect("Stroke rectangle"); + } + fn fill_text(&mut self, text: impl Into<geometry::Text>) { let text = text.into(); diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs index 74e9924d..e55ade38 100644 --- a/wgpu/src/image/vector.rs +++ b/wgpu/src/image/vector.rs @@ -6,6 +6,7 @@ use resvg::tiny_skia; use resvg::usvg; use rustc_hash::{FxHashMap, FxHashSet}; use std::fs; +use std::sync::Arc; /// Entry in cache corresponding to an svg handle pub enum Svg { @@ -37,6 +38,7 @@ pub struct Cache { svg_hits: FxHashSet<u64>, rasterized_hits: FxHashSet<(u64, u32, u32, ColorFilter)>, should_trim: bool, + fontdb: Option<Arc<usvg::fontdb::Database>>, } type ColorFilter = Option<[u8; 4]>; @@ -48,23 +50,33 @@ impl Cache { return self.svgs.get(&handle.id()).unwrap(); } + // TODO: Reuse `cosmic-text` font database + if self.fontdb.is_none() { + let mut fontdb = usvg::fontdb::Database::new(); + fontdb.load_system_fonts(); + + self.fontdb = Some(Arc::new(fontdb)); + } + + let options = usvg::Options { + fontdb: self + .fontdb + .as_ref() + .expect("fontdb must be initialized") + .clone(), + ..usvg::Options::default() + }; + let svg = match handle.data() { svg::Data::Path(path) => fs::read_to_string(path) .ok() .and_then(|contents| { - usvg::Tree::from_str( - &contents, - &usvg::Options::default(), // TODO: Set usvg::Options::fontdb - ) - .ok() + usvg::Tree::from_str(&contents, &options).ok() }) .map(Svg::Loaded) .unwrap_or(Svg::NotFound), svg::Data::Bytes(bytes) => { - match usvg::Tree::from_data( - bytes, - &usvg::Options::default(), // TODO: Set usvg::Options::fontdb - ) { + match usvg::Tree::from_data(bytes, &options) { Ok(tree) => Svg::Loaded(tree), Err(_) => Svg::NotFound, } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 39167514..d79f0dc8 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -408,6 +408,7 @@ impl Renderer { horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, shaping: core::text::Shaping::Basic, + wrapping: core::text::Wrapping::Word, }; renderer.fill_text( diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index a367d5e6..b213c8cf 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -22,14 +22,14 @@ fn rounded_box_sdf(to_center: vec2<f32>, size: vec2<f32>, radius: f32) -> f32 { return length(max(abs(to_center) - size + vec2<f32>(radius, radius), vec2<f32>(0.0, 0.0))) - radius; } -// Based on the fragment position and the center of the quad, select one of the 4 radi. +// Based on the fragment position and the center of the quad, select one of the 4 radii. // Order matches CSS border radius attribute: -// radi.x = top-left, radi.y = top-right, radi.z = bottom-right, radi.w = bottom-left -fn select_border_radius(radi: vec4<f32>, position: vec2<f32>, center: vec2<f32>) -> f32 { - var rx = radi.x; - var ry = radi.y; - rx = select(radi.x, radi.y, position.x > center.x); - ry = select(radi.w, radi.z, position.x > center.x); +// radii.x = top-left, radii.y = top-right, radii.z = bottom-right, radii.w = bottom-left +fn select_border_radius(radii: vec4<f32>, position: vec2<f32>, center: vec2<f32>) -> f32 { + var rx = radii.x; + var ry = radii.y; + rx = select(radii.x, radii.y, position.x > center.x); + ry = select(radii.w, radii.z, position.x > center.x); rx = select(rx, ry, position.y > center.y); return rx; } |