From 1d135ddd901d9b5a53bcc16b270c8f2a6f96dc26 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl <47084093+LaurenzV@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:29:58 +0100 Subject: [PATCH] fix missmatched pattern text issue --- crates/typst-pdf/src/krilla.rs | 39 +++++++++++++++++++++++++++------- crates/typst-pdf/src/paint.rs | 24 +++++++++------------ 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/crates/typst-pdf/src/krilla.rs b/crates/typst-pdf/src/krilla.rs index 9a740a4c0..d0ebf863a 100644 --- a/crates/typst-pdf/src/krilla.rs +++ b/crates/typst-pdf/src/krilla.rs @@ -1,4 +1,3 @@ -use crate::content_old::Transforms; use crate::primitive::{PointExt, SizeExt, TransformExt}; use crate::{paint, AbsExt}; use bytemuck::TransparentWrapper; @@ -26,20 +25,23 @@ use typst_library::visualize::{ #[derive(Debug, Clone)] struct State { + /// The full transform chain + transform_chain: Transform, /// The transform of the current item. transform: Transform, /// The transform of first hard frame in the hierarchy. - container_transform: Transform, + container_transform_chain: Transform, /// The size of the first hard frame in the hierarchy. size: Size, } impl State { /// Creates a new, clean state for a given `size`. - fn new(size: Size) -> Self { + fn new(size: Size, transform_chain: Transform, container_transform_chain: Transform) -> Self { Self { + transform_chain, transform: Transform::identity(), - container_transform: Transform::identity(), + container_transform_chain, size, } } @@ -50,17 +52,19 @@ impl State { pub fn transform(&mut self, transform: Transform) { self.transform = self.transform.pre_concat(transform); + self.transform_chain = self.transform_chain.pre_concat(transform); } fn set_container_transform(&mut self) { - self.container_transform = self.transform; + self.container_transform_chain = self.transform_chain; } /// Creates the [`Transforms`] structure for the current item. pub fn transforms(&self, size: Size) -> Transforms { Transforms { - transform: self.transform, - container_transform: self.container_transform, + transform_chain_: self.transform_chain, + transform_: self.transform, + container_transform_chain: self.container_transform_chain, container_size: self.size, size, } @@ -73,7 +77,11 @@ pub(crate) struct FrameContext { impl FrameContext { pub fn new(size: Size) -> Self { - Self { states: vec![State::new(size)] } + Self { states: vec![State::new(size, Transform::identity(), Transform::identity())] } + } + + pub fn derive_new(&self, size: Size) -> Self { + Self { states: vec![State::new(size, self.state().transform_chain, self.state().container_transform_chain)] } } pub fn push(&mut self) { @@ -93,6 +101,21 @@ impl FrameContext { } } +/// Subset of the state used to calculate the transform of gradients and patterns. +#[derive(Debug, Clone, Copy)] +pub(super) struct Transforms { + /// The full transform chain. + pub transform_chain_: Transform, + /// The transform of the current item. + pub transform_: Transform, + /// The transform of first hard frame in the hierarchy. + pub container_transform_chain: Transform, + /// The size of the first hard frame in the hierarchy. + pub container_size: Size, + /// The size of the item. + pub size: Size, +} + #[derive(TransparentWrapper)] #[repr(transparent)] struct PdfGlyph(Glyph); diff --git a/crates/typst-pdf/src/paint.rs b/crates/typst-pdf/src/paint.rs index fd5e56a4a..9d30d3551 100644 --- a/crates/typst-pdf/src/paint.rs +++ b/crates/typst-pdf/src/paint.rs @@ -1,7 +1,6 @@ //! Convert paint types from typst to krilla. -use crate::content_old::Transforms; -use crate::krilla::{process_frame, FrameContext, GlobalContext}; +use crate::krilla::{process_frame, FrameContext, GlobalContext, Transforms}; use crate::primitive::{FillRuleExt, LineCapExt, LineJoinExt, TransformExt}; use crate::AbsExt; use krilla::geom::NormalizedF32; @@ -157,13 +156,10 @@ pub(crate) fn convert_pattern( transforms.size.y = Abs::pt(1.0); } - let transform = surface.ctm().invert().unwrap().pre_concat( - match pattern.unwrap_relative(on_text) { - RelativeTo::Self_ => transforms.transform, - RelativeTo::Parent => transforms.container_transform, - } - .as_krilla(), - ); + let transform = match pattern.unwrap_relative(on_text) { + RelativeTo::Self_ => Transform::identity(), + RelativeTo::Parent => transforms.transform_chain_.invert().unwrap().pre_concat(transforms.container_transform_chain) + }.as_krilla(); let mut stream_builder = surface.stream_builder(); let mut surface = stream_builder.surface(); @@ -201,8 +197,8 @@ fn convert_gradient( let rotation = gradient.angle().unwrap_or_else(Angle::zero); let transform = match gradient.unwrap_relative(on_text) { - RelativeTo::Self_ => transforms.transform, - RelativeTo::Parent => transforms.container_transform, + RelativeTo::Self_ => transforms.transform_chain_, + RelativeTo::Parent => transforms.container_transform_chain, }; let angle = rotation; @@ -220,7 +216,7 @@ fn convert_gradient( match &gradient { Gradient::Linear(linear) => { let actual_transform = - transforms.transform.invert().unwrap().pre_concat(transform); + transforms.transform_chain_.invert().unwrap().pre_concat(transform); if let Some((c, t)) = linear.stops.first() { add_single(c, *t); @@ -280,7 +276,7 @@ fn convert_gradient( } Gradient::Radial(radial) => { let actual_transform = - transforms.transform.invert().unwrap().pre_concat(transform); + transforms.transform_chain_.invert().unwrap().pre_concat(transform); if let Some((c, t)) = radial.stops.first() { add_single(c, *t); @@ -331,7 +327,7 @@ fn convert_gradient( let cx = size.x.to_f32() * conic.center.x.get() as f32; let cy = size.y.to_f32() * conic.center.y.get() as f32; let actual_transform = transforms - .transform + .transform_chain_ .invert() .unwrap() .pre_concat(transform)