This commit is contained in:
Laurenz Stampfl 2024-12-17 19:21:59 +01:00
parent 59a1bbed55
commit 1085dd00de
6 changed files with 29 additions and 33 deletions

View File

@ -21,7 +21,7 @@ pub(crate) fn handle_image(
surface: &mut Surface, surface: &mut Surface,
span: Span, span: Span,
) -> SourceResult<()> { ) -> SourceResult<()> {
surface.push_transform(&fc.state().transform.to_krilla()); surface.push_transform(&fc.state().transform().to_krilla());
match image.kind() { match image.kind() {
ImageKind::Raster(raster) => { ImageKind::Raster(raster) => {

View File

@ -31,7 +31,7 @@ use typst_syntax::Span;
/// which is mainly needed to resolve gradients and patterns correctly. /// which is mainly needed to resolve gradients and patterns correctly.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct State { pub(crate) struct State {
pub(crate) transform: Transform, transform: Transform,
/// The transform of first hard frame in the hierarchy. /// The transform of first hard frame in the hierarchy.
container_transform: Transform, container_transform: Transform,
/// The size of the first hard frame in the hierarchy. /// The size of the first hard frame in the hierarchy.

View File

@ -28,7 +28,7 @@ pub(crate) fn handle_link(
pos + Point::with_y(size.y), pos + Point::with_y(size.y),
pos + size.to_point(), pos + size.to_point(),
] { ] {
let t = point.transform(fc.state().transform); let t = point.transform(fc.state().transform());
min_x.set_min(t.x); min_x.set_min(t.x);
min_y.set_min(t.y); min_y.set_min(t.y);
max_x.set_max(t.x); max_x.set_max(t.x);

View File

@ -119,15 +119,7 @@ fn convert_pattern(
surface: &mut Surface, surface: &mut Surface,
state: &State, state: &State,
) -> SourceResult<(krilla::paint::Paint, u8)> { ) -> SourceResult<(krilla::paint::Paint, u8)> {
let transform = match pattern.unwrap_relative(on_text) { let transform = correct_transform(state, pattern.unwrap_relative(on_text));
RelativeTo::Self_ => Transform::identity(),
RelativeTo::Parent => state
.transform
.invert()
.unwrap()
.pre_concat(state.container_transform()),
}
.to_krilla();
let mut stream_builder = surface.stream_builder(); let mut stream_builder = surface.stream_builder();
let mut surface = stream_builder.surface(); let mut surface = stream_builder.surface();
@ -137,7 +129,7 @@ fn convert_pattern(
let stream = stream_builder.finish(); let stream = stream_builder.finish();
let pattern = krilla::paint::Pattern { let pattern = krilla::paint::Pattern {
stream, stream,
transform, transform: transform.to_krilla(),
width: (pattern.size().x + pattern.spacing().x).to_pt() as _, width: (pattern.size().x + pattern.spacing().x).to_pt() as _,
height: (pattern.size().y + pattern.spacing().y).to_pt() as _, height: (pattern.size().y + pattern.spacing().y).to_pt() as _,
}; };
@ -155,12 +147,9 @@ fn convert_gradient(
RelativeTo::Self_ => size, RelativeTo::Self_ => size,
RelativeTo::Parent => state.container_size(), RelativeTo::Parent => state.container_size(),
}; };
let rotation = gradient.angle().unwrap_or_else(Angle::zero);
let transform = match gradient.unwrap_relative(on_text) { let rotation = gradient.angle().unwrap_or_else(Angle::zero);
RelativeTo::Self_ => state.transform, let base_transform = correct_transform(state, gradient.unwrap_relative(on_text));
RelativeTo::Parent => state.container_transform(),
};
let angle = rotation; let angle = rotation;
@ -176,9 +165,6 @@ fn convert_gradient(
match &gradient { match &gradient {
Gradient::Linear(linear) => { Gradient::Linear(linear) => {
let actual_transform =
state.transform().invert().unwrap().pre_concat(transform);
if let Some((c, t)) = linear.stops.first() { if let Some((c, t)) = linear.stops.first() {
add_single(c, *t); add_single(c, *t);
} }
@ -223,7 +209,7 @@ fn convert_gradient(
y1, y1,
x2, x2,
y2, y2,
transform: actual_transform.to_krilla().pre_concat( transform: base_transform.to_krilla().pre_concat(
krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32()), krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32()),
), ),
spread_method: SpreadMethod::Pad, spread_method: SpreadMethod::Pad,
@ -234,9 +220,6 @@ fn convert_gradient(
(linear.into(), 255) (linear.into(), 255)
} }
Gradient::Radial(radial) => { Gradient::Radial(radial) => {
let actual_transform =
state.transform.invert().unwrap().pre_concat(transform);
if let Some((c, t)) = radial.stops.first() { if let Some((c, t)) = radial.stops.first() {
add_single(c, *t); add_single(c, *t);
} }
@ -269,7 +252,7 @@ fn convert_gradient(
cx: radial.center.x.get() as f32, cx: radial.center.x.get() as f32,
cy: radial.center.y.get() as f32, cy: radial.center.y.get() as f32,
cr: radial.radius.get() as f32, cr: radial.radius.get() as f32,
transform: actual_transform.to_krilla().pre_concat( transform: base_transform.to_krilla().pre_concat(
krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32()), krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32()),
), ),
spread_method: SpreadMethod::Pad, spread_method: SpreadMethod::Pad,
@ -283,11 +266,7 @@ fn convert_gradient(
// Correct the gradient's angle // Correct the gradient's angle
let cx = size.x.to_f32() * conic.center.x.get() as f32; 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 cy = size.y.to_f32() * conic.center.y.get() as f32;
let actual_transform = state let actual_transform = base_transform
.transform
.invert()
.unwrap()
.pre_concat(transform)
.pre_concat(Transform::rotate_at( .pre_concat(Transform::rotate_at(
angle, angle,
Abs::pt(cx as f64), Abs::pt(cx as f64),
@ -365,3 +344,20 @@ fn convert_gradient(
} }
} }
} }
fn correct_transform(state: &State, relative: RelativeTo) -> Transform {
// In krilla, if we have a shape with a transform and a complex paint,
// then the paint will inherit the transform of the shape.
match relative {
// Because of the above, we don't need to apply an additional transform here.
RelativeTo::Self_ => Transform::identity(),
// Because of the above, we need to first reverse the transform that will be
// applied from the shape, and then re-apply the transform that is used for
// the next parent container.
RelativeTo::Parent => state
.transform()
.invert()
.unwrap()
.pre_concat(state.container_transform()),
}
}

View File

@ -13,7 +13,7 @@ pub(crate) fn handle_shape(
surface: &mut Surface, surface: &mut Surface,
gc: &mut GlobalContext, gc: &mut GlobalContext,
) -> SourceResult<()> { ) -> SourceResult<()> {
surface.push_transform(&fc.state().transform.to_krilla()); surface.push_transform(&fc.state().transform().to_krilla());
if let Some(path) = convert_geometry(&shape.geometry) { if let Some(path) = convert_geometry(&shape.geometry) {
if let Some(paint) = &shape.fill { if let Some(paint) = &shape.fill {

View File

@ -34,7 +34,7 @@ pub(crate) fn handle_text(
let size = t.size; let size = t.size;
let glyphs: &[PdfGlyph] = TransparentWrapper::wrap_slice(t.glyphs.as_slice()); let glyphs: &[PdfGlyph] = TransparentWrapper::wrap_slice(t.glyphs.as_slice());
surface.push_transform(&fc.state().transform.to_krilla()); surface.push_transform(&fc.state().transform().to_krilla());
surface.fill_glyphs( surface.fill_glyphs(
krilla::geom::Point::from_xy(0.0, 0.0), krilla::geom::Point::from_xy(0.0, 0.0),
fill, fill,