mirror of
https://github.com/typst/typst
synced 2025-06-08 13:16:24 +08:00
part1
This commit is contained in:
parent
db412f4387
commit
4186ef2c77
@ -6,7 +6,7 @@ use crate::page::PageLabelExt;
|
|||||||
use crate::shape::handle_shape;
|
use crate::shape::handle_shape;
|
||||||
use crate::text::handle_text;
|
use crate::text::handle_text;
|
||||||
use crate::util::{convert_path, display_font, AbsExt, TransformExt};
|
use crate::util::{convert_path, display_font, AbsExt, TransformExt};
|
||||||
use crate::{paint, PdfOptions};
|
use crate::PdfOptions;
|
||||||
use krilla::destination::{NamedDestination, XyzDestination};
|
use krilla::destination::{NamedDestination, XyzDestination};
|
||||||
use krilla::error::KrillaError;
|
use krilla::error::KrillaError;
|
||||||
use krilla::page::PageLabel;
|
use krilla::page::PageLabel;
|
||||||
@ -24,19 +24,20 @@ use typst_library::layout::{
|
|||||||
};
|
};
|
||||||
use typst_library::model::HeadingElem;
|
use typst_library::model::HeadingElem;
|
||||||
use typst_library::text::{Font, Lang};
|
use typst_library::text::{Font, Lang};
|
||||||
use typst_library::visualize::{Geometry, Paint, Shape};
|
use typst_library::visualize::{Geometry, Paint};
|
||||||
use typst_syntax::Span;
|
use typst_syntax::Span;
|
||||||
|
|
||||||
|
/// A state allowing us to keep track of transforms and container sizes,
|
||||||
|
/// 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,
|
||||||
/// The full transform chain
|
/// The full transform chain
|
||||||
transform_chain: Transform,
|
transform_chain: Transform,
|
||||||
/// The transform of the current item.
|
|
||||||
pub(crate) transform: Transform,
|
|
||||||
/// The transform of first hard frame in the hierarchy.
|
/// The transform of first hard frame in the hierarchy.
|
||||||
container_transform_chain: Transform,
|
container_transform_chain: Transform,
|
||||||
/// The size of the first hard frame in the hierarchy.
|
/// The size of the first hard frame in the hierarchy.
|
||||||
size: Size,
|
container_size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
@ -50,29 +51,26 @@ impl State {
|
|||||||
transform_chain,
|
transform_chain,
|
||||||
transform: Transform::identity(),
|
transform: Transform::identity(),
|
||||||
container_transform_chain,
|
container_transform_chain,
|
||||||
size,
|
container_size: size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn size(&mut self, size: Size) {
|
pub(crate) fn register_container(&mut self, size: Size) {
|
||||||
self.size = size;
|
self.container_transform_chain = self.transform_chain;
|
||||||
|
self.container_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn transform(&mut self, transform: Transform) {
|
pub(crate) fn pre_concat(&mut self, transform: Transform) {
|
||||||
self.transform = self.transform.pre_concat(transform);
|
self.transform = self.transform.pre_concat(transform);
|
||||||
self.transform_chain = self.transform_chain.pre_concat(transform);
|
self.transform_chain = self.transform_chain.pre_concat(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_container_transform(&mut self) {
|
|
||||||
self.container_transform_chain = self.transform_chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates the [`Transforms`] structure for the current item.
|
/// Creates the [`Transforms`] structure for the current item.
|
||||||
pub(crate) fn transforms(&self, size: Size) -> Transforms {
|
pub(crate) fn transforms(&self, size: Size) -> Transforms {
|
||||||
Transforms {
|
Transforms {
|
||||||
transform_chain_: self.transform_chain,
|
transform_chain_: self.transform_chain,
|
||||||
container_transform_chain: self.container_transform_chain,
|
container_transform_chain: self.container_transform_chain,
|
||||||
container_size: self.size,
|
container_size: self.container_size,
|
||||||
size,
|
size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,8 +294,7 @@ pub(crate) fn handle_frame(
|
|||||||
fc.push();
|
fc.push();
|
||||||
|
|
||||||
if frame.kind().is_hard() {
|
if frame.kind().is_hard() {
|
||||||
fc.state_mut().set_container_transform();
|
fc.state_mut().register_container(frame.size());
|
||||||
fc.state_mut().size(frame.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fill) = fill {
|
if let Some(fill) = fill {
|
||||||
@ -307,7 +304,7 @@ pub(crate) fn handle_frame(
|
|||||||
|
|
||||||
for (point, item) in frame.items() {
|
for (point, item) in frame.items() {
|
||||||
fc.push();
|
fc.push();
|
||||||
fc.state_mut().transform(Transform::translate(point.x, point.y));
|
fc.state_mut().pre_concat(Transform::translate(point.x, point.y));
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
FrameItem::Group(g) => handle_group(fc, g, surface, gc)?,
|
FrameItem::Group(g) => handle_group(fc, g, surface, gc)?,
|
||||||
@ -335,7 +332,7 @@ pub(crate) fn handle_group(
|
|||||||
context: &mut GlobalContext,
|
context: &mut GlobalContext,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
fc.push();
|
fc.push();
|
||||||
fc.state_mut().transform(group.transform);
|
fc.state_mut().pre_concat(group.transform);
|
||||||
|
|
||||||
let clip_path = group
|
let clip_path = group
|
||||||
.clip_path
|
.clip_path
|
||||||
|
@ -13,7 +13,7 @@ use typst_library::visualize::{
|
|||||||
};
|
};
|
||||||
use typst_utils::Numeric;
|
use typst_utils::Numeric;
|
||||||
|
|
||||||
pub(crate) fn fill(
|
pub(crate) fn convert_fill(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
paint_: &Paint,
|
paint_: &Paint,
|
||||||
fill_rule_: FillRule,
|
fill_rule_: FillRule,
|
||||||
@ -21,7 +21,7 @@ pub(crate) fn fill(
|
|||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
transforms: Transforms,
|
transforms: Transforms,
|
||||||
) -> SourceResult<krilla::path::Fill> {
|
) -> SourceResult<krilla::path::Fill> {
|
||||||
let (paint, opacity) = paint(gc, paint_, on_text, surface, transforms)?;
|
let (paint, opacity) = convert_paint(gc, paint_, on_text, surface, transforms)?;
|
||||||
|
|
||||||
Ok(krilla::path::Fill {
|
Ok(krilla::path::Fill {
|
||||||
paint,
|
paint,
|
||||||
@ -30,14 +30,14 @@ pub(crate) fn fill(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn stroke(
|
pub(crate) fn convert_stroke(
|
||||||
fc: &mut GlobalContext,
|
fc: &mut GlobalContext,
|
||||||
stroke: &FixedStroke,
|
stroke: &FixedStroke,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
transforms: Transforms,
|
transforms: Transforms,
|
||||||
) -> SourceResult<krilla::path::Stroke> {
|
) -> SourceResult<krilla::path::Stroke> {
|
||||||
let (paint, opacity) = paint(fc, &stroke.paint, on_text, surface, transforms)?;
|
let (paint, opacity) = convert_paint(fc, &stroke.paint, on_text, surface, transforms)?;
|
||||||
|
|
||||||
Ok(krilla::path::Stroke {
|
Ok(krilla::path::Stroke {
|
||||||
paint,
|
paint,
|
||||||
@ -46,18 +46,18 @@ pub(crate) fn stroke(
|
|||||||
line_join: stroke.join.to_krilla(),
|
line_join: stroke.join.to_krilla(),
|
||||||
line_cap: stroke.cap.to_krilla(),
|
line_cap: stroke.cap.to_krilla(),
|
||||||
opacity: NormalizedF32::new(opacity as f32 / 255.0).unwrap(),
|
opacity: NormalizedF32::new(opacity as f32 / 255.0).unwrap(),
|
||||||
dash: stroke.dash.as_ref().map(|d| dash(d)),
|
dash: stroke.dash.as_ref().map(|d| convert_dash(d)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dash(dash: &DashPattern<Abs, Abs>) -> krilla::path::StrokeDash {
|
fn convert_dash(dash: &DashPattern<Abs, Abs>) -> krilla::path::StrokeDash {
|
||||||
krilla::path::StrokeDash {
|
krilla::path::StrokeDash {
|
||||||
array: dash.array.iter().map(|e| e.to_f32()).collect(),
|
array: dash.array.iter().map(|e| e.to_f32()).collect(),
|
||||||
offset: dash.phase.to_f32(),
|
offset: dash.phase.to_f32(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn convert_paint(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
paint: &Paint,
|
paint: &Paint,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
@ -65,40 +65,41 @@ fn paint(
|
|||||||
transforms: Transforms,
|
transforms: Transforms,
|
||||||
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
||||||
match paint {
|
match paint {
|
||||||
Paint::Solid(c) => {
|
Paint::Solid(c) => Ok(convert_solid(c)),
|
||||||
let (p, alpha) = match c.space() {
|
|
||||||
ColorSpace::D65Gray => {
|
|
||||||
let components = c.to_vec4_u8();
|
|
||||||
(krilla::color::luma::Color::new(components[0]).into(), components[3])
|
|
||||||
}
|
|
||||||
ColorSpace::Cmyk => {
|
|
||||||
let components = c.to_vec4_u8();
|
|
||||||
(
|
|
||||||
krilla::color::cmyk::Color::new(
|
|
||||||
components[0],
|
|
||||||
components[1],
|
|
||||||
components[2],
|
|
||||||
components[3],
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
// Typst doesn't support alpha on CMYK colors.
|
|
||||||
255,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let (c, a) = c.to_krilla_rgb();
|
|
||||||
(c.into(), a)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((p, alpha))
|
|
||||||
}
|
|
||||||
Paint::Gradient(g) => Ok(convert_gradient(g, on_text, transforms)),
|
Paint::Gradient(g) => Ok(convert_gradient(g, on_text, transforms)),
|
||||||
Paint::Tiling(p) => convert_pattern(gc, p, on_text, surface, transforms),
|
Paint::Tiling(p) => convert_pattern(gc, p, on_text, surface, transforms),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn convert_pattern(
|
fn convert_solid(color: &Color) -> (krilla::paint::Paint, u8) {
|
||||||
|
match color.space() {
|
||||||
|
ColorSpace::D65Gray => {
|
||||||
|
let components = color.to_vec4_u8();
|
||||||
|
(krilla::color::luma::Color::new(components[0]).into(), components[3])
|
||||||
|
}
|
||||||
|
ColorSpace::Cmyk => {
|
||||||
|
let components = color.to_vec4_u8();
|
||||||
|
(
|
||||||
|
krilla::color::cmyk::Color::new(
|
||||||
|
components[0],
|
||||||
|
components[1],
|
||||||
|
components[2],
|
||||||
|
components[3],
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
// Typst doesn't support alpha on CMYK colors.
|
||||||
|
255,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Convert all remaining colors into RGB
|
||||||
|
_ => {
|
||||||
|
let (c, a) = color.to_krilla_rgb();
|
||||||
|
(c.into(), a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_pattern(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
pattern: &Tiling,
|
pattern: &Tiling,
|
||||||
on_text: bool,
|
on_text: bool,
|
||||||
|
@ -17,7 +17,7 @@ pub(crate) fn handle_shape(
|
|||||||
|
|
||||||
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 {
|
||||||
let fill = paint::fill(
|
let fill = paint::convert_fill(
|
||||||
gc,
|
gc,
|
||||||
&paint,
|
&paint,
|
||||||
shape.fill_rule,
|
shape.fill_rule,
|
||||||
@ -38,7 +38,7 @@ pub(crate) fn handle_shape(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(stroke) = &stroke {
|
if let Some(stroke) = &stroke {
|
||||||
let stroke = paint::stroke(
|
let stroke = paint::convert_stroke(
|
||||||
gc,
|
gc,
|
||||||
stroke,
|
stroke,
|
||||||
false,
|
false,
|
||||||
|
@ -21,7 +21,7 @@ pub(crate) fn handle_text(
|
|||||||
*gc.languages.entry(t.lang).or_insert(0) += t.glyphs.len();
|
*gc.languages.entry(t.lang).or_insert(0) += t.glyphs.len();
|
||||||
|
|
||||||
let font = convert_font(gc, t.font.clone())?;
|
let font = convert_font(gc, t.font.clone())?;
|
||||||
let fill = paint::fill(
|
let fill = paint::convert_fill(
|
||||||
gc,
|
gc,
|
||||||
&t.fill,
|
&t.fill,
|
||||||
FillRule::NonZero,
|
FillRule::NonZero,
|
||||||
@ -48,7 +48,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::stroke(gc, s, true, surface, fc.state().transforms(Size::zero())))
|
.map(|s| paint::convert_stroke(gc, s, true, surface, fc.state().transforms(Size::zero())))
|
||||||
{
|
{
|
||||||
let stroke = stroke?;
|
let stroke = stroke?;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user