diff options
| author | Martin Haug <mhaug@live.de> | 2022-04-30 21:59:34 +0200 |
|---|---|---|
| committer | Martin Haug <mhaug@live.de> | 2022-05-01 11:50:34 +0200 |
| commit | 5f1499d380e223e7e1b2a8a96eb99e3ec95a56ac (patch) | |
| tree | 44945bc35618c9ce10380016200309e42c2b5ed4 /src/export | |
| parent | f9e115daf54c29358f890b137f50a33a781af680 (diff) | |
Add round corners and change arguments
Diffstat (limited to 'src/export')
| -rw-r--r-- | src/export/pdf.rs | 45 | ||||
| -rw-r--r-- | src/export/render.rs | 38 |
2 files changed, 58 insertions, 25 deletions
diff --git a/src/export/pdf.rs b/src/export/pdf.rs index 067eb277..f5401dfb 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -16,9 +16,9 @@ use ttf_parser::{name_id, GlyphId, Tag}; use super::subset::subset; use crate::font::{find_name, FaceId, FontStore}; -use crate::frame::{Element, Frame, Geometry, Group, Shape, Text}; +use crate::frame::{rect_path, rect_paths, Element, Frame, Geometry, Group, Shape, Text}; use crate::geom::{ - self, Color, Em, Length, Numeric, Paint, Point, Size, Stroke, Transform, + self, Color, Em, Length, Numeric, Paint, Point, Sides, Size, Stroke, Transform, }; use crate::image::{Image, ImageId, ImageStore, RasterImage}; use crate::Context; @@ -499,16 +499,16 @@ impl<'a> PageExporter<'a> { } fn write_shape(&mut self, x: f32, y: f32, shape: &Shape) { - if shape.fill.is_none() && shape.stroke.is_none() { + if shape.fill.is_none() && shape.stroke.iter().all(Option::is_none) { return; } match shape.geometry { - Geometry::Rect(size) => { + Geometry::Rect(size, radius) => { let w = size.x.to_f32(); let h = size.y.to_f32(); if w > 0.0 && h > 0.0 { - self.content.rect(x, y, w, h); + self.write_path(x, y, &rect_path(size, radius)); } } Geometry::Ellipse(size) => { @@ -530,16 +530,37 @@ impl<'a> PageExporter<'a> { self.set_fill(fill); } - if let Some(stroke) = shape.stroke { - self.set_stroke(stroke); + // The stroke does not exist or is non-uniform. + let mut use_stroke = false; + if shape.stroke.is_uniform() || !matches!(shape.geometry, Geometry::Rect(_, _)) { + if let Some(stroke) = shape.stroke.top { + self.set_stroke(stroke); + use_stroke = true; + } } - match (shape.fill, shape.stroke) { - (None, None) => unreachable!(), - (Some(_), None) => self.content.fill_nonzero(), - (None, Some(_)) => self.content.stroke(), - (Some(_), Some(_)) => self.content.fill_nonzero_and_stroke(), + match (shape.fill, use_stroke) { + (None, false) => self.content.end_path(), + (Some(_), false) => self.content.fill_nonzero(), + (None, true) => self.content.stroke(), + (Some(_), true) => self.content.fill_nonzero_and_stroke(), }; + + if let Geometry::Rect(size, radius) = shape.geometry { + if !use_stroke { + for (path, stroke) in rect_paths(size, radius, Some(shape.stroke)) { + if let Some(stroke) = stroke { + self.write_shape(x, y, &Shape { + geometry: Geometry::Path(path), + fill: None, + stroke: Sides::splat(Some(stroke)), + }); + } else { + continue; + } + } + } + } } fn write_path(&mut self, x: f32, y: f32, path: &geom::Path) { diff --git a/src/export/render.rs b/src/export/render.rs index c3b92d31..9c674acb 100644 --- a/src/export/render.rs +++ b/src/export/render.rs @@ -8,8 +8,9 @@ use ttf_parser::{GlyphId, OutlineBuilder}; use usvg::FitTo; use crate::frame::{Element, Frame, Geometry, Group, Shape, Text}; -use crate::geom::{self, Length, Paint, PathElement, Size, Stroke, Transform}; +use crate::geom::{self, Length, Paint, PathElement, Sides, Size, Stroke, Transform}; use crate::image::{Image, RasterImage, Svg}; +use crate::library::prelude::{rect_path, rect_paths}; use crate::Context; /// Export a frame into a rendered image. @@ -298,12 +299,7 @@ fn render_shape( shape: &Shape, ) -> Option<()> { let path = match shape.geometry { - Geometry::Rect(size) => { - let w = size.x.to_f32(); - let h = size.y.to_f32(); - let rect = sk::Rect::from_xywh(0.0, 0.0, w, h)?; - sk::PathBuilder::from_rect(rect) - } + Geometry::Rect(size, radius) => convert_path(&rect_path(size, radius))?, Geometry::Ellipse(size) => convert_path(&geom::Path::ellipse(size))?, Geometry::Line(target) => { let mut builder = sk::PathBuilder::new(); @@ -315,7 +311,7 @@ fn render_shape( if let Some(fill) = shape.fill { let mut paint: sk::Paint = fill.into(); - if matches!(shape.geometry, Geometry::Rect(_)) { + if matches!(shape.geometry, Geometry::Rect(_, _)) { paint.anti_alias = false; } @@ -323,11 +319,27 @@ fn render_shape( canvas.fill_path(&path, &paint, rule, ts, mask); } - if let Some(Stroke { paint, thickness }) = shape.stroke { - let paint = paint.into(); - let mut stroke = sk::Stroke::default(); - stroke.width = thickness.to_f32(); - canvas.stroke_path(&path, &paint, &stroke, ts, mask); + if shape.stroke.is_uniform() || !matches!(shape.geometry, Geometry::Rect(_, _)) { + if let Some(Stroke { paint, thickness }) = shape.stroke.top { + let paint = paint.into(); + let mut stroke = sk::Stroke::default(); + stroke.width = thickness.to_f32(); + canvas.stroke_path(&path, &paint, &stroke, ts, mask); + } + } else { + if let Geometry::Rect(size, radius) = shape.geometry { + for (path, stroke) in rect_paths(size, radius, Some(shape.stroke)) { + if let Some(stroke) = stroke { + render_shape(canvas, ts, mask, &Shape { + geometry: Geometry::Path(path), + fill: None, + stroke: Sides::splat(Some(stroke)), + })?; + } else { + continue; + } + } + } } Some(()) |
