summaryrefslogtreecommitdiff
path: root/src/export/pdf
diff options
context:
space:
mode:
authorBirk Tjelmeland <git@birktj.no>2023-04-13 16:05:56 +0200
committerGitHub <noreply@github.com>2023-04-13 16:05:56 +0200
commitd1cd814ef8149cbac6e59c81e074aa59c930eed3 (patch)
tree02b9a8afed4d121b34d89669452f91cda19df8e2 /src/export/pdf
parent46ce9c94e3f615751989d3cba5aa1599e0ba5913 (diff)
Add support for more complex strokes (#505)
Diffstat (limited to 'src/export/pdf')
-rw-r--r--src/export/pdf/page.rs60
1 files changed, 55 insertions, 5 deletions
diff --git a/src/export/pdf/page.rs b/src/export/pdf/page.rs
index 636d42c7..d6ead124 100644
--- a/src/export/pdf/page.rs
+++ b/src/export/pdf/page.rs
@@ -1,5 +1,7 @@
use ecow::eco_format;
-use pdf_writer::types::{ActionType, AnnotationType, ColorSpaceOperand};
+use pdf_writer::types::{
+ ActionType, AnnotationType, ColorSpaceOperand, LineCapStyle, LineJoinStyle,
+};
use pdf_writer::writers::ColorSpace;
use pdf_writer::{Content, Filter, Finish, Name, Rect, Ref, Str};
@@ -7,8 +9,8 @@ use super::{deflate, AbsExt, EmExt, PdfContext, RefExt, D65_GRAY, SRGB};
use crate::doc::{Destination, Frame, FrameItem, GroupItem, Meta, TextItem};
use crate::font::Font;
use crate::geom::{
- self, Abs, Color, Em, Geometry, Numeric, Paint, Point, Ratio, Shape, Size, Stroke,
- Transform,
+ self, Abs, Color, Em, Geometry, LineCap, LineJoin, Numeric, Paint, Point, Ratio,
+ Shape, Size, Stroke, Transform,
};
use crate::image::Image;
@@ -250,8 +252,17 @@ impl PageContext<'_, '_> {
fn set_stroke(&mut self, stroke: &Stroke) {
if self.state.stroke.as_ref() != Some(stroke) {
+ let Stroke {
+ paint,
+ thickness,
+ line_cap,
+ line_join,
+ dash_pattern,
+ miter_limit,
+ } = stroke;
+
let f = |c| c as f32 / 255.0;
- let Paint::Solid(color) = stroke.paint;
+ let Paint::Solid(color) = paint;
match color {
Color::Luma(c) => {
self.set_stroke_color_space(D65_GRAY);
@@ -267,7 +278,26 @@ impl PageContext<'_, '_> {
}
}
- self.content.set_line_width(stroke.thickness.to_f32());
+ self.content.set_line_width(thickness.to_f32());
+ if self.state.stroke.as_ref().map(|s| &s.line_cap) != Some(line_cap) {
+ self.content.set_line_cap(line_cap.into());
+ }
+ if self.state.stroke.as_ref().map(|s| &s.line_join) != Some(line_join) {
+ self.content.set_line_join(line_join.into());
+ }
+ if self.state.stroke.as_ref().map(|s| &s.dash_pattern) != Some(dash_pattern) {
+ if let Some(pattern) = dash_pattern {
+ self.content.set_dash_pattern(
+ pattern.array.iter().map(|l| l.to_f32()),
+ pattern.phase.to_f32(),
+ );
+ } else {
+ self.content.set_dash_pattern([], 0.0);
+ }
+ }
+ if self.state.stroke.as_ref().map(|s| &s.miter_limit) != Some(miter_limit) {
+ self.content.set_miter_limit(miter_limit.0 as f32);
+ }
self.state.stroke = Some(stroke.clone());
}
}
@@ -486,3 +516,23 @@ fn write_link(ctx: &mut PageContext, pos: Point, dest: &Destination, size: Size)
ctx.links.push((dest.clone(), rect));
}
+
+impl From<&LineCap> for LineCapStyle {
+ fn from(line_cap: &LineCap) -> Self {
+ match line_cap {
+ LineCap::Butt => LineCapStyle::ButtCap,
+ LineCap::Round => LineCapStyle::RoundCap,
+ LineCap::Square => LineCapStyle::ProjectingSquareCap,
+ }
+ }
+}
+
+impl From<&LineJoin> for LineJoinStyle {
+ fn from(line_join: &LineJoin) -> Self {
+ match line_join {
+ LineJoin::Miter => LineJoinStyle::MiterJoin,
+ LineJoin::Round => LineJoinStyle::RoundJoin,
+ LineJoin::Bevel => LineJoinStyle::BevelJoin,
+ }
+ }
+}