mirror of
https://github.com/typst/typst
synced 2025-06-08 13:16:24 +08:00
more
This commit is contained in:
parent
0c4cffb475
commit
59a1bbed55
@ -40,9 +40,7 @@ pub(crate) struct State {
|
|||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
/// Creates a new, clean state for a given `size`.
|
/// Creates a new, clean state for a given `size`.
|
||||||
fn new(
|
fn new(size: Size) -> Self {
|
||||||
size: Size,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
transform: Transform::identity(),
|
transform: Transform::identity(),
|
||||||
container_transform: Transform::identity(),
|
container_transform: Transform::identity(),
|
||||||
@ -59,14 +57,16 @@ impl State {
|
|||||||
self.transform = self.transform.pre_concat(transform);
|
self.transform = self.transform.pre_concat(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the [`Transforms`] structure for the current item.
|
pub(crate) fn transform(&self) -> Transform {
|
||||||
pub(crate) fn transforms(&self, size: Size) -> Transforms {
|
self.transform
|
||||||
Transforms {
|
|
||||||
transform_chain_: self.transform,
|
|
||||||
container_transform_chain: self.container_transform,
|
|
||||||
container_size: self.container_size,
|
|
||||||
size,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn container_transform(&self) -> Transform {
|
||||||
|
self.container_transform
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn container_size(&self) -> Size {
|
||||||
|
self.container_size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,19 +100,6 @@ 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(crate) transform_chain_: Transform,
|
|
||||||
/// The transform of first hard frame in the hierarchy.
|
|
||||||
pub(crate) container_transform_chain: Transform,
|
|
||||||
/// The size of the first hard frame in the hierarchy.
|
|
||||||
pub(crate) container_size: Size,
|
|
||||||
/// The size of the item.
|
|
||||||
pub(crate) size: Size,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct GlobalContext<'a> {
|
pub(crate) struct GlobalContext<'a> {
|
||||||
/// Cache the conversion between krilla and Typst fonts (forward and backward).
|
/// Cache the conversion between krilla and Typst fonts (forward and backward).
|
||||||
pub(crate) fonts_forward: HashMap<Font, krilla::font::Font>,
|
pub(crate) fonts_forward: HashMap<Font, krilla::font::Font>,
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
//! Convert paint types from typst to krilla.
|
//! Convert paint types from typst to krilla.
|
||||||
|
|
||||||
use crate::krilla::{handle_frame, FrameContext, GlobalContext, Transforms};
|
use crate::krilla::{handle_frame, FrameContext, GlobalContext, State};
|
||||||
use crate::util::{AbsExt, ColorExt, FillRuleExt, LineCapExt, LineJoinExt, TransformExt};
|
use crate::util::{AbsExt, ColorExt, FillRuleExt, LineCapExt, LineJoinExt, TransformExt};
|
||||||
use krilla::geom::NormalizedF32;
|
use krilla::geom::NormalizedF32;
|
||||||
use krilla::paint::SpreadMethod;
|
use krilla::paint::SpreadMethod;
|
||||||
use krilla::surface::Surface;
|
use krilla::surface::Surface;
|
||||||
use typst_library::diag::SourceResult;
|
use typst_library::diag::SourceResult;
|
||||||
use typst_library::layout::{Abs, Angle, Quadrant, Ratio, Transform};
|
use typst_library::layout::{Abs, Angle, Quadrant, Ratio, Size, Transform};
|
||||||
use typst_library::visualize::{
|
use typst_library::visualize::{
|
||||||
Color, ColorSpace, DashPattern, FillRule, FixedStroke, Gradient, Paint, RatioOrAngle,
|
Color, ColorSpace, DashPattern, FillRule, FixedStroke, Gradient, Paint, RatioOrAngle,
|
||||||
RelativeTo, Tiling, WeightedColor,
|
RelativeTo, Tiling, WeightedColor,
|
||||||
@ -19,9 +19,10 @@ pub(crate) fn convert_fill(
|
|||||||
fill_rule_: FillRule,
|
fill_rule_: FillRule,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
transforms: Transforms,
|
state: &State,
|
||||||
|
size: Size,
|
||||||
) -> SourceResult<krilla::path::Fill> {
|
) -> SourceResult<krilla::path::Fill> {
|
||||||
let (paint, opacity) = convert_paint(gc, paint_, on_text, surface, transforms)?;
|
let (paint, opacity) = convert_paint(gc, paint_, on_text, surface, state, size)?;
|
||||||
|
|
||||||
Ok(krilla::path::Fill {
|
Ok(krilla::path::Fill {
|
||||||
paint,
|
paint,
|
||||||
@ -35,9 +36,11 @@ pub(crate) fn convert_stroke(
|
|||||||
stroke: &FixedStroke,
|
stroke: &FixedStroke,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
transforms: Transforms,
|
state: &State,
|
||||||
|
size: Size,
|
||||||
) -> SourceResult<krilla::path::Stroke> {
|
) -> SourceResult<krilla::path::Stroke> {
|
||||||
let (paint, opacity) = convert_paint(fc, &stroke.paint, on_text, surface, transforms)?;
|
let (paint, opacity) =
|
||||||
|
convert_paint(fc, &stroke.paint, on_text, surface, state, size)?;
|
||||||
|
|
||||||
Ok(krilla::path::Stroke {
|
Ok(krilla::path::Stroke {
|
||||||
paint,
|
paint,
|
||||||
@ -62,12 +65,22 @@ fn convert_paint(
|
|||||||
paint: &Paint,
|
paint: &Paint,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
transforms: Transforms,
|
state: &State,
|
||||||
|
mut size: Size,
|
||||||
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
||||||
|
// Edge cases for strokes.
|
||||||
|
if size.x.is_zero() {
|
||||||
|
size.x = Abs::pt(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if size.y.is_zero() {
|
||||||
|
size.y = Abs::pt(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
match paint {
|
match paint {
|
||||||
Paint::Solid(c) => Ok(convert_solid(c)),
|
Paint::Solid(c) => Ok(convert_solid(c)),
|
||||||
Paint::Gradient(g) => Ok(convert_gradient(g, on_text, transforms)),
|
Paint::Gradient(g) => Ok(convert_gradient(g, on_text, state, size)),
|
||||||
Paint::Tiling(p) => convert_pattern(gc, p, on_text, surface, transforms),
|
Paint::Tiling(p) => convert_pattern(gc, p, on_text, surface, state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,24 +117,15 @@ fn convert_pattern(
|
|||||||
pattern: &Tiling,
|
pattern: &Tiling,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
mut transforms: Transforms,
|
state: &State,
|
||||||
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
||||||
// Edge cases for strokes.
|
|
||||||
if transforms.size.x.is_zero() {
|
|
||||||
transforms.size.x = Abs::pt(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if transforms.size.y.is_zero() {
|
|
||||||
transforms.size.y = Abs::pt(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let transform = match pattern.unwrap_relative(on_text) {
|
let transform = match pattern.unwrap_relative(on_text) {
|
||||||
RelativeTo::Self_ => Transform::identity(),
|
RelativeTo::Self_ => Transform::identity(),
|
||||||
RelativeTo::Parent => transforms
|
RelativeTo::Parent => state
|
||||||
.transform_chain_
|
.transform
|
||||||
.invert()
|
.invert()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pre_concat(transforms.container_transform_chain),
|
.pre_concat(state.container_transform()),
|
||||||
}
|
}
|
||||||
.to_krilla();
|
.to_krilla();
|
||||||
|
|
||||||
@ -144,25 +148,18 @@ fn convert_pattern(
|
|||||||
fn convert_gradient(
|
fn convert_gradient(
|
||||||
gradient: &Gradient,
|
gradient: &Gradient,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
mut transforms: Transforms,
|
state: &State,
|
||||||
|
size: Size,
|
||||||
) -> (krilla::paint::Paint, u8) {
|
) -> (krilla::paint::Paint, u8) {
|
||||||
// Edge cases for strokes.
|
|
||||||
if transforms.size.x.is_zero() {
|
|
||||||
transforms.size.x = Abs::pt(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if transforms.size.y.is_zero() {
|
|
||||||
transforms.size.y = Abs::pt(1.0);
|
|
||||||
}
|
|
||||||
let size = match gradient.unwrap_relative(on_text) {
|
let size = match gradient.unwrap_relative(on_text) {
|
||||||
RelativeTo::Self_ => transforms.size,
|
RelativeTo::Self_ => size,
|
||||||
RelativeTo::Parent => transforms.container_size,
|
RelativeTo::Parent => state.container_size(),
|
||||||
};
|
};
|
||||||
let rotation = gradient.angle().unwrap_or_else(Angle::zero);
|
let rotation = gradient.angle().unwrap_or_else(Angle::zero);
|
||||||
|
|
||||||
let transform = match gradient.unwrap_relative(on_text) {
|
let transform = match gradient.unwrap_relative(on_text) {
|
||||||
RelativeTo::Self_ => transforms.transform_chain_,
|
RelativeTo::Self_ => state.transform,
|
||||||
RelativeTo::Parent => transforms.container_transform_chain,
|
RelativeTo::Parent => state.container_transform(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let angle = rotation;
|
let angle = rotation;
|
||||||
@ -180,7 +177,7 @@ fn convert_gradient(
|
|||||||
match &gradient {
|
match &gradient {
|
||||||
Gradient::Linear(linear) => {
|
Gradient::Linear(linear) => {
|
||||||
let actual_transform =
|
let actual_transform =
|
||||||
transforms.transform_chain_.invert().unwrap().pre_concat(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);
|
||||||
@ -238,7 +235,7 @@ fn convert_gradient(
|
|||||||
}
|
}
|
||||||
Gradient::Radial(radial) => {
|
Gradient::Radial(radial) => {
|
||||||
let actual_transform =
|
let actual_transform =
|
||||||
transforms.transform_chain_.invert().unwrap().pre_concat(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);
|
||||||
@ -286,8 +283,8 @@ 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 = transforms
|
let actual_transform = state
|
||||||
.transform_chain_
|
.transform
|
||||||
.invert()
|
.invert()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pre_concat(transform)
|
.pre_concat(transform)
|
||||||
|
@ -23,7 +23,8 @@ pub(crate) fn handle_shape(
|
|||||||
shape.fill_rule,
|
shape.fill_rule,
|
||||||
false,
|
false,
|
||||||
surface,
|
surface,
|
||||||
fc.state().transforms(shape.geometry.bbox_size()),
|
fc.state(),
|
||||||
|
shape.geometry.bbox_size(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
surface.fill_path(&path, fill);
|
surface.fill_path(&path, fill);
|
||||||
@ -43,7 +44,8 @@ pub(crate) fn handle_shape(
|
|||||||
stroke,
|
stroke,
|
||||||
false,
|
false,
|
||||||
surface,
|
surface,
|
||||||
fc.state().transforms(shape.geometry.bbox_size()),
|
fc.state(),
|
||||||
|
shape.geometry.bbox_size(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
surface.stroke_path(&path, stroke);
|
surface.stroke_path(&path, stroke);
|
||||||
|
@ -27,7 +27,8 @@ pub(crate) fn handle_text(
|
|||||||
FillRule::NonZero,
|
FillRule::NonZero,
|
||||||
true,
|
true,
|
||||||
surface,
|
surface,
|
||||||
fc.state().transforms(Size::zero()),
|
fc.state(),
|
||||||
|
Size::zero(),
|
||||||
)?;
|
)?;
|
||||||
let text = t.text.as_str();
|
let text = t.text.as_str();
|
||||||
let size = t.size;
|
let size = t.size;
|
||||||
@ -48,7 +49,7 @@ pub(crate) fn handle_text(
|
|||||||
if let Some(stroke) = t
|
if let Some(stroke) = t
|
||||||
.stroke
|
.stroke
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| paint::convert_stroke(gc, s, true, surface, fc.state().transforms(Size::zero())))
|
.map(|s| paint::convert_stroke(gc, s, true, surface, fc.state(), Size::zero()))
|
||||||
{
|
{
|
||||||
let stroke = stroke?;
|
let stroke = stroke?;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user