mirror of
https://github.com/typst/typst
synced 2025-06-08 05:06: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::text::handle_text;
|
||||
use crate::util::{convert_path, display_font, AbsExt, TransformExt};
|
||||
use crate::{paint, PdfOptions};
|
||||
use crate::PdfOptions;
|
||||
use krilla::destination::{NamedDestination, XyzDestination};
|
||||
use krilla::error::KrillaError;
|
||||
use krilla::page::PageLabel;
|
||||
@ -24,19 +24,20 @@ use typst_library::layout::{
|
||||
};
|
||||
use typst_library::model::HeadingElem;
|
||||
use typst_library::text::{Font, Lang};
|
||||
use typst_library::visualize::{Geometry, Paint, Shape};
|
||||
use typst_library::visualize::{Geometry, Paint};
|
||||
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)]
|
||||
pub(crate) struct State {
|
||||
pub(crate) transform: Transform,
|
||||
/// The full transform chain
|
||||
transform_chain: Transform,
|
||||
/// The transform of the current item.
|
||||
pub(crate) transform: Transform,
|
||||
/// The transform of first hard frame in the hierarchy.
|
||||
container_transform_chain: Transform,
|
||||
/// The size of the first hard frame in the hierarchy.
|
||||
size: Size,
|
||||
container_size: Size,
|
||||
}
|
||||
|
||||
impl State {
|
||||
@ -50,29 +51,26 @@ impl State {
|
||||
transform_chain,
|
||||
transform: Transform::identity(),
|
||||
container_transform_chain,
|
||||
size,
|
||||
container_size: size,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn size(&mut self, size: Size) {
|
||||
self.size = size;
|
||||
pub(crate) fn register_container(&mut 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_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.
|
||||
pub(crate) fn transforms(&self, size: Size) -> Transforms {
|
||||
Transforms {
|
||||
transform_chain_: self.transform_chain,
|
||||
container_transform_chain: self.container_transform_chain,
|
||||
container_size: self.size,
|
||||
container_size: self.container_size,
|
||||
size,
|
||||
}
|
||||
}
|
||||
@ -296,8 +294,7 @@ pub(crate) fn handle_frame(
|
||||
fc.push();
|
||||
|
||||
if frame.kind().is_hard() {
|
||||
fc.state_mut().set_container_transform();
|
||||
fc.state_mut().size(frame.size());
|
||||
fc.state_mut().register_container(frame.size());
|
||||
}
|
||||
|
||||
if let Some(fill) = fill {
|
||||
@ -307,7 +304,7 @@ pub(crate) fn handle_frame(
|
||||
|
||||
for (point, item) in frame.items() {
|
||||
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 {
|
||||
FrameItem::Group(g) => handle_group(fc, g, surface, gc)?,
|
||||
@ -335,7 +332,7 @@ pub(crate) fn handle_group(
|
||||
context: &mut GlobalContext,
|
||||
) -> SourceResult<()> {
|
||||
fc.push();
|
||||
fc.state_mut().transform(group.transform);
|
||||
fc.state_mut().pre_concat(group.transform);
|
||||
|
||||
let clip_path = group
|
||||
.clip_path
|
||||
|
@ -13,7 +13,7 @@ use typst_library::visualize::{
|
||||
};
|
||||
use typst_utils::Numeric;
|
||||
|
||||
pub(crate) fn fill(
|
||||
pub(crate) fn convert_fill(
|
||||
gc: &mut GlobalContext,
|
||||
paint_: &Paint,
|
||||
fill_rule_: FillRule,
|
||||
@ -21,7 +21,7 @@ pub(crate) fn fill(
|
||||
surface: &mut Surface,
|
||||
transforms: Transforms,
|
||||
) -> 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 {
|
||||
paint,
|
||||
@ -30,14 +30,14 @@ pub(crate) fn fill(
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn stroke(
|
||||
pub(crate) fn convert_stroke(
|
||||
fc: &mut GlobalContext,
|
||||
stroke: &FixedStroke,
|
||||
on_text: bool,
|
||||
surface: &mut Surface,
|
||||
transforms: Transforms,
|
||||
) -> 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 {
|
||||
paint,
|
||||
@ -46,18 +46,18 @@ pub(crate) fn stroke(
|
||||
line_join: stroke.join.to_krilla(),
|
||||
line_cap: stroke.cap.to_krilla(),
|
||||
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 {
|
||||
array: dash.array.iter().map(|e| e.to_f32()).collect(),
|
||||
offset: dash.phase.to_f32(),
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(
|
||||
fn convert_paint(
|
||||
gc: &mut GlobalContext,
|
||||
paint: &Paint,
|
||||
on_text: bool,
|
||||
@ -65,40 +65,41 @@ fn paint(
|
||||
transforms: Transforms,
|
||||
) -> SourceResult<(krilla::paint::Paint, u8)> {
|
||||
match paint {
|
||||
Paint::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::Solid(c) => Ok(convert_solid(c)),
|
||||
Paint::Gradient(g) => Ok(convert_gradient(g, on_text, 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,
|
||||
pattern: &Tiling,
|
||||
on_text: bool,
|
||||
|
@ -17,7 +17,7 @@ pub(crate) fn handle_shape(
|
||||
|
||||
if let Some(path) = convert_geometry(&shape.geometry) {
|
||||
if let Some(paint) = &shape.fill {
|
||||
let fill = paint::fill(
|
||||
let fill = paint::convert_fill(
|
||||
gc,
|
||||
&paint,
|
||||
shape.fill_rule,
|
||||
@ -38,7 +38,7 @@ pub(crate) fn handle_shape(
|
||||
});
|
||||
|
||||
if let Some(stroke) = &stroke {
|
||||
let stroke = paint::stroke(
|
||||
let stroke = paint::convert_stroke(
|
||||
gc,
|
||||
stroke,
|
||||
false,
|
||||
|
@ -21,7 +21,7 @@ pub(crate) fn handle_text(
|
||||
*gc.languages.entry(t.lang).or_insert(0) += t.glyphs.len();
|
||||
|
||||
let font = convert_font(gc, t.font.clone())?;
|
||||
let fill = paint::fill(
|
||||
let fill = paint::convert_fill(
|
||||
gc,
|
||||
&t.fill,
|
||||
FillRule::NonZero,
|
||||
@ -48,7 +48,7 @@ pub(crate) fn handle_text(
|
||||
if let Some(stroke) = t
|
||||
.stroke
|
||||
.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?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user