diff --git a/crates/typst-library/src/layout/transform.rs b/crates/typst-library/src/layout/transform.rs index 183df6098..d153d97db 100644 --- a/crates/typst-library/src/layout/transform.rs +++ b/crates/typst-library/src/layout/transform.rs @@ -307,6 +307,20 @@ impl Transform { Self { sx, sy, ..Self::identity() } } + /// A scale transform at a specific position. + pub fn scale_at(sx: Ratio, sy: Ratio, px: Abs, py: Abs) -> Self { + Self::translate(px, py) + .pre_concat(Self::scale(sx, sy)) + .pre_concat(Self::translate(-px, -py)) + } + + /// A rotate transform at a specific position. + pub fn rotate_at(angle: Angle, px: Abs, py: Abs) -> Self { + Self::translate(px, py) + .pre_concat(Self::rotate(angle)) + .pre_concat(Self::translate(-px, -py)) + } + /// A rotate transform. pub fn rotate(angle: Angle) -> Self { let cos = Ratio::new(angle.cos()); diff --git a/crates/typst-pdf/src/paint.rs b/crates/typst-pdf/src/paint.rs index 4a60a720b..1310e285a 100644 --- a/crates/typst-pdf/src/paint.rs +++ b/crates/typst-pdf/src/paint.rs @@ -211,15 +211,11 @@ fn convert_gradient( let pdf_gradient = PdfGradient { aspect_ratio: size.aspect_ratio(), - transform, + transform: Transform::identity(), gradient: gradient.clone(), angle: Gradient::correct_aspect_ratio(rotation, size.aspect_ratio()), }; - let actual_transform = transforms.transform.invert().unwrap().pre_concat(transform) - .pre_concat(Transform::scale(-Ratio::one(), Ratio::one())) - .pre_concat(Transform::rotate(-pdf_gradient.angle)); - match &gradient { Gradient::Linear(_) => { (krilla::color::rgb::Color::black().into(), 255) @@ -229,7 +225,11 @@ fn convert_gradient( } Gradient::Conic(conic) => { // Correct the gradient's angle - let angle = Gradient::correct_aspect_ratio(conic.angle, pdf_gradient.aspect_ratio); + 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.invert().unwrap().pre_concat(transform) + .pre_concat(Transform::scale_at(-Ratio::one(), Ratio::one(), Abs::pt(cx as f64), Abs::pt(cy as f64))) + .pre_concat(Transform::rotate_at(-pdf_gradient.angle, Abs::pt(cx as f64), Abs::pt(cy as f64))); let mut stops: Vec> = vec![]; let mut add_single = |color: &Color, offset: Ratio| { @@ -296,8 +296,8 @@ fn convert_gradient( } let sweep = krilla::paint::SweepGradient { - cx: size.x.to_f32() * conic.center.x.get() as f32, - cy: size.y.to_f32() * conic.center.y.get() as f32, + cx, + cy, start_angle: 0.0, end_angle: 360.0, transform: actual_transform.as_krilla(),