mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Extract typst-render
crate
This commit is contained in:
parent
c12a19a075
commit
ec04c3de2f
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -2908,9 +2908,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"palette",
|
"palette",
|
||||||
"pdf-writer",
|
"pdf-writer",
|
||||||
"pixglyph",
|
|
||||||
"regex",
|
"regex",
|
||||||
"resvg",
|
|
||||||
"roxmltree",
|
"roxmltree",
|
||||||
"rustybuzz",
|
"rustybuzz",
|
||||||
"serde",
|
"serde",
|
||||||
@ -2920,7 +2918,6 @@ dependencies = [
|
|||||||
"subsetter",
|
"subsetter",
|
||||||
"svg2pdf",
|
"svg2pdf",
|
||||||
"time",
|
"time",
|
||||||
"tiny-skia",
|
|
||||||
"toml",
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
@ -2976,6 +2973,7 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"typst",
|
"typst",
|
||||||
"typst-library",
|
"typst-library",
|
||||||
|
"typst-render",
|
||||||
"ureq",
|
"ureq",
|
||||||
"xz2",
|
"xz2",
|
||||||
"zip",
|
"zip",
|
||||||
@ -3065,6 +3063,23 @@ dependencies = [
|
|||||||
"syn 2.0.38",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typst-render"
|
||||||
|
version = "0.9.0"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"comemo",
|
||||||
|
"flate2",
|
||||||
|
"image",
|
||||||
|
"pixglyph",
|
||||||
|
"resvg",
|
||||||
|
"roxmltree",
|
||||||
|
"tiny-skia",
|
||||||
|
"ttf-parser",
|
||||||
|
"typst",
|
||||||
|
"usvg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typst-syntax"
|
name = "typst-syntax"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -3095,6 +3110,7 @@ dependencies = [
|
|||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
"typst",
|
"typst",
|
||||||
"typst-library",
|
"typst-library",
|
||||||
|
"typst-render",
|
||||||
"unscanny",
|
"unscanny",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
@ -19,6 +19,7 @@ keywords = ["typst"]
|
|||||||
typst = { path = "crates/typst" }
|
typst = { path = "crates/typst" }
|
||||||
typst-library = { path = "crates/typst-library" }
|
typst-library = { path = "crates/typst-library" }
|
||||||
typst-macros = { path = "crates/typst-macros" }
|
typst-macros = { path = "crates/typst-macros" }
|
||||||
|
typst-render = { path = "crates/typst-render" }
|
||||||
typst-syntax = { path = "crates/typst-syntax" }
|
typst-syntax = { path = "crates/typst-syntax" }
|
||||||
az = "1.2"
|
az = "1.2"
|
||||||
base64 = "0.21.2"
|
base64 = "0.21.2"
|
||||||
|
@ -22,6 +22,7 @@ doc = false
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
typst = { workspace = true }
|
typst = { workspace = true }
|
||||||
typst-library = { workspace = true }
|
typst-library = { workspace = true }
|
||||||
|
typst-render = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
codespan-reporting = { workspace = true }
|
codespan-reporting = { workspace = true }
|
||||||
|
@ -220,7 +220,7 @@ fn export_image(
|
|||||||
match fmt {
|
match fmt {
|
||||||
ImageExportFormat::Png => {
|
ImageExportFormat::Png => {
|
||||||
let pixmap =
|
let pixmap =
|
||||||
typst::export::render(frame, command.ppi / 72.0, Color::WHITE);
|
typst_render::render(frame, command.ppi / 72.0, Color::WHITE);
|
||||||
pixmap
|
pixmap
|
||||||
.save_png(path)
|
.save_png(path)
|
||||||
.map_err(|err| eco_format!("failed to write PNG file ({err})"))?;
|
.map_err(|err| eco_format!("failed to write PNG file ({err})"))?;
|
||||||
|
29
crates/typst-render/Cargo.toml
Normal file
29
crates/typst-render/Cargo.toml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
[package]
|
||||||
|
name = "typst-render"
|
||||||
|
description = "Raster image exporter for Typst."
|
||||||
|
version.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
categories.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
typst = { workspace = true }
|
||||||
|
bytemuck = { workspace = true }
|
||||||
|
comemo = { workspace = true }
|
||||||
|
flate2 = { workspace = true }
|
||||||
|
image = { workspace = true }
|
||||||
|
pixglyph = { workspace = true }
|
||||||
|
resvg = { workspace = true }
|
||||||
|
roxmltree = { workspace = true }
|
||||||
|
tiny-skia = { workspace = true }
|
||||||
|
ttf-parser = { workspace = true }
|
||||||
|
usvg = { workspace = true }
|
@ -9,15 +9,14 @@ use pixglyph::Bitmap;
|
|||||||
use resvg::tiny_skia::IntRect;
|
use resvg::tiny_skia::IntRect;
|
||||||
use tiny_skia as sk;
|
use tiny_skia as sk;
|
||||||
use ttf_parser::{GlyphId, OutlineBuilder};
|
use ttf_parser::{GlyphId, OutlineBuilder};
|
||||||
use usvg::{NodeExt, TreeParsing};
|
use typst::doc::{Frame, FrameItem, FrameKind, GroupItem, Meta, TextItem};
|
||||||
|
use typst::font::Font;
|
||||||
use crate::doc::{Frame, FrameItem, FrameKind, GroupItem, Meta, TextItem};
|
use typst::geom::{
|
||||||
use crate::font::Font;
|
|
||||||
use crate::geom::{
|
|
||||||
self, Abs, Axes, Color, FixedStroke, Geometry, Gradient, LineCap, LineJoin, Paint,
|
self, Abs, Axes, Color, FixedStroke, Geometry, Gradient, LineCap, LineJoin, Paint,
|
||||||
PathItem, Point, Ratio, Relative, Shape, Size, Transform,
|
PathItem, Point, Ratio, Relative, Shape, Size, Transform,
|
||||||
};
|
};
|
||||||
use crate::image::{Image, ImageKind, RasterFormat};
|
use typst::image::{Image, ImageKind, RasterFormat};
|
||||||
|
use usvg::{NodeExt, TreeParsing};
|
||||||
|
|
||||||
/// Export a frame into a raster image.
|
/// Export a frame into a raster image.
|
||||||
///
|
///
|
||||||
@ -29,7 +28,7 @@ pub fn render(frame: &Frame, pixel_per_pt: f32, fill: Color) -> sk::Pixmap {
|
|||||||
let pxh = (pixel_per_pt * size.y.to_f32()).round().max(1.0) as u32;
|
let pxh = (pixel_per_pt * size.y.to_f32()).round().max(1.0) as u32;
|
||||||
|
|
||||||
let mut canvas = sk::Pixmap::new(pxw, pxh).unwrap();
|
let mut canvas = sk::Pixmap::new(pxw, pxh).unwrap();
|
||||||
canvas.fill(fill.into());
|
canvas.fill(to_sk_color(fill));
|
||||||
|
|
||||||
let ts = sk::Transform::from_scale(pixel_per_pt, pixel_per_pt);
|
let ts = sk::Transform::from_scale(pixel_per_pt, pixel_per_pt);
|
||||||
render_frame(&mut canvas, State::new(size, ts, pixel_per_pt), frame);
|
render_frame(&mut canvas, State::new(size, ts, pixel_per_pt), frame);
|
||||||
@ -49,7 +48,7 @@ pub fn render_merged(
|
|||||||
) -> sk::Pixmap {
|
) -> sk::Pixmap {
|
||||||
let pixmaps: Vec<_> = frames
|
let pixmaps: Vec<_> = frames
|
||||||
.iter()
|
.iter()
|
||||||
.map(|frame| typst::export::render(frame, pixel_per_pt, frame_fill))
|
.map(|frame| render(frame, pixel_per_pt, frame_fill))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let padding = (pixel_per_pt * padding.to_f32()).round() as u32;
|
let padding = (pixel_per_pt * padding.to_f32()).round() as u32;
|
||||||
@ -59,7 +58,7 @@ pub fn render_merged(
|
|||||||
padding + pixmaps.iter().map(|pixmap| pixmap.height() + padding).sum::<u32>();
|
padding + pixmaps.iter().map(|pixmap| pixmap.height() + padding).sum::<u32>();
|
||||||
|
|
||||||
let mut canvas = sk::Pixmap::new(pxw, pxh).unwrap();
|
let mut canvas = sk::Pixmap::new(pxw, pxh).unwrap();
|
||||||
canvas.fill(padding_fill.into());
|
canvas.fill(to_sk_color(padding_fill));
|
||||||
|
|
||||||
let [x, mut y] = [padding; 2];
|
let [x, mut y] = [padding; 2];
|
||||||
for pixmap in pixmaps {
|
for pixmap in pixmaps {
|
||||||
@ -173,18 +172,19 @@ fn render_frame(canvas: &mut sk::Pixmap, state: State, frame: &Frame) {
|
|||||||
|
|
||||||
/// Render a group frame with optional transform and clipping into the canvas.
|
/// Render a group frame with optional transform and clipping into the canvas.
|
||||||
fn render_group(canvas: &mut sk::Pixmap, state: State, pos: Point, group: &GroupItem) {
|
fn render_group(canvas: &mut sk::Pixmap, state: State, pos: Point, group: &GroupItem) {
|
||||||
|
let sk_transform = to_sk_transform(&group.transform);
|
||||||
let state = match group.frame.kind() {
|
let state = match group.frame.kind() {
|
||||||
FrameKind::Soft => state.pre_translate(pos).pre_concat(group.transform.into()),
|
FrameKind::Soft => state.pre_translate(pos).pre_concat(sk_transform),
|
||||||
FrameKind::Hard => state
|
FrameKind::Hard => state
|
||||||
.pre_translate(pos)
|
.pre_translate(pos)
|
||||||
.pre_concat(group.transform.into())
|
.pre_concat(sk_transform)
|
||||||
.pre_concat_container(
|
.pre_concat_container(
|
||||||
state
|
state
|
||||||
.transform
|
.transform
|
||||||
.post_concat(state.container_transform.invert().unwrap()),
|
.post_concat(state.container_transform.invert().unwrap()),
|
||||||
)
|
)
|
||||||
.pre_concat_container(Transform::translate(pos.x, pos.y).into())
|
.pre_concat_container(to_sk_transform(&Transform::translate(pos.x, pos.y)))
|
||||||
.pre_concat_container(group.transform.into())
|
.pre_concat_container(sk_transform)
|
||||||
.with_size(group.frame.size()),
|
.with_size(group.frame.size()),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -456,8 +456,7 @@ fn write_bitmap<S: PaintSampler>(
|
|||||||
for x in 0..mw {
|
for x in 0..mw {
|
||||||
for y in 0..mh {
|
for y in 0..mh {
|
||||||
let alpha = bitmap.coverage[(y * mw + x) as usize];
|
let alpha = bitmap.coverage[(y * mw + x) as usize];
|
||||||
let color: sk::ColorU8 = sampler.sample((x, y)).into();
|
let color = to_sk_color_u8_without_alpha(sampler.sample((x, y)));
|
||||||
|
|
||||||
pixmap.pixels_mut()[((y + 1) * (mw + 2) + (x + 1)) as usize] =
|
pixmap.pixels_mut()[((y + 1) * (mw + 2) + (x + 1)) as usize] =
|
||||||
sk::ColorU8::from_rgba(
|
sk::ColorU8::from_rgba(
|
||||||
color.red(),
|
color.red(),
|
||||||
@ -502,8 +501,9 @@ fn write_bitmap<S: PaintSampler>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let color: sk::ColorU8 = sampler.sample((x as _, y as _)).into();
|
let color = sampler.sample((x as _, y as _));
|
||||||
let color = bytemuck::cast(color.premultiply());
|
let color =
|
||||||
|
bytemuck::cast(to_sk_color_u8_without_alpha(color).premultiply());
|
||||||
let pi = (y * cw + x) as usize;
|
let pi = (y * cw + x) as usize;
|
||||||
if cov == 255 {
|
if cov == 255 {
|
||||||
pixels[pi] = color;
|
pixels[pi] = color;
|
||||||
@ -621,8 +621,8 @@ fn render_shape(canvas: &mut sk::Pixmap, state: State, shape: &Shape) -> Option<
|
|||||||
);
|
);
|
||||||
let stroke = sk::Stroke {
|
let stroke = sk::Stroke {
|
||||||
width,
|
width,
|
||||||
line_cap: line_cap.into(),
|
line_cap: to_sk_line_cap(*line_cap),
|
||||||
line_join: line_join.into(),
|
line_join: to_sk_line_join(*line_join),
|
||||||
dash,
|
dash,
|
||||||
miter_limit: miter_limit.get() as f32,
|
miter_limit: miter_limit.get() as f32,
|
||||||
};
|
};
|
||||||
@ -740,34 +740,6 @@ fn scaled_texture(image: &Image, w: u32, h: u32) -> Option<Arc<sk::Pixmap>> {
|
|||||||
Some(Arc::new(pixmap))
|
Some(Arc::new(pixmap))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Transform> for sk::Transform {
|
|
||||||
fn from(transform: Transform) -> Self {
|
|
||||||
let Transform { sx, ky, kx, sy, tx, ty } = transform;
|
|
||||||
sk::Transform::from_row(
|
|
||||||
sx.get() as _,
|
|
||||||
ky.get() as _,
|
|
||||||
kx.get() as _,
|
|
||||||
sy.get() as _,
|
|
||||||
tx.to_f32(),
|
|
||||||
ty.to_f32(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<sk::Transform> for Transform {
|
|
||||||
fn from(value: sk::Transform) -> Self {
|
|
||||||
let sk::Transform { sx, ky, kx, sy, tx, ty } = value;
|
|
||||||
Self {
|
|
||||||
sx: Ratio::new(sx as _),
|
|
||||||
ky: Ratio::new(ky as _),
|
|
||||||
kx: Ratio::new(kx as _),
|
|
||||||
sy: Ratio::new(sy as _),
|
|
||||||
tx: Abs::raw(tx as _),
|
|
||||||
ty: Abs::raw(ty as _),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for sampling of a paint, used as a generic
|
/// Trait for sampling of a paint, used as a generic
|
||||||
/// abstraction over solid colors and gradients.
|
/// abstraction over solid colors and gradients.
|
||||||
trait PaintSampler: Copy {
|
trait PaintSampler: Copy {
|
||||||
@ -860,18 +832,16 @@ fn to_sk_paint<'a>(
|
|||||||
let mut pixmap = sk::Pixmap::new(width.max(1), height.max(1)).unwrap();
|
let mut pixmap = sk::Pixmap::new(width.max(1), height.max(1)).unwrap();
|
||||||
for x in 0..width {
|
for x in 0..width {
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
let color: sk::Color = gradient
|
let color = gradient.sample_at(
|
||||||
.sample_at(
|
(
|
||||||
(
|
(x as f32 + offset.x.to_f32()) * scale.x.get() as f32,
|
||||||
(x as f32 + offset.x.to_f32()) * scale.x.get() as f32,
|
(y as f32 + offset.y.to_f32()) * scale.y.get() as f32,
|
||||||
(y as f32 + offset.y.to_f32()) * scale.y.get() as f32,
|
),
|
||||||
),
|
(width as f32, height as f32),
|
||||||
(width as f32, height as f32),
|
);
|
||||||
)
|
|
||||||
.into();
|
|
||||||
|
|
||||||
pixmap.pixels_mut()[(y * width + x) as usize] =
|
pixmap.pixels_mut()[(y * width + x) as usize] =
|
||||||
color.premultiply().to_color_u8();
|
to_sk_color(color).premultiply().to_color_u8();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,7 +851,7 @@ fn to_sk_paint<'a>(
|
|||||||
let mut sk_paint: sk::Paint<'_> = sk::Paint::default();
|
let mut sk_paint: sk::Paint<'_> = sk::Paint::default();
|
||||||
match paint {
|
match paint {
|
||||||
Paint::Solid(color) => {
|
Paint::Solid(color) => {
|
||||||
sk_paint.set_color((*color).into());
|
sk_paint.set_color(to_sk_color(*color));
|
||||||
sk_paint.anti_alias = true;
|
sk_paint.anti_alias = true;
|
||||||
}
|
}
|
||||||
Paint::Gradient(gradient) => {
|
Paint::Gradient(gradient) => {
|
||||||
@ -925,31 +895,42 @@ fn to_sk_paint<'a>(
|
|||||||
sk_paint
|
sk_paint
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Color> for sk::Color {
|
fn to_sk_color(color: Color) -> sk::Color {
|
||||||
fn from(color: Color) -> Self {
|
let [r, g, b, a] = color.to_rgba().to_vec4_u8();
|
||||||
let [r, g, b, a] = color.to_rgba().to_vec4_u8();
|
sk::Color::from_rgba8(r, g, b, a)
|
||||||
sk::Color::from_rgba8(r, g, b, a)
|
}
|
||||||
|
|
||||||
|
fn to_sk_color_u8_without_alpha(color: Color) -> sk::ColorU8 {
|
||||||
|
let [r, g, b, _] = color.to_rgba().to_vec4_u8();
|
||||||
|
sk::ColorU8::from_rgba(r, g, b, 255)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_sk_line_cap(cap: LineCap) -> sk::LineCap {
|
||||||
|
match cap {
|
||||||
|
LineCap::Butt => sk::LineCap::Butt,
|
||||||
|
LineCap::Round => sk::LineCap::Round,
|
||||||
|
LineCap::Square => sk::LineCap::Square,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&LineCap> for sk::LineCap {
|
fn to_sk_line_join(join: LineJoin) -> sk::LineJoin {
|
||||||
fn from(line_cap: &LineCap) -> Self {
|
match join {
|
||||||
match line_cap {
|
LineJoin::Miter => sk::LineJoin::Miter,
|
||||||
LineCap::Butt => sk::LineCap::Butt,
|
LineJoin::Round => sk::LineJoin::Round,
|
||||||
LineCap::Round => sk::LineCap::Round,
|
LineJoin::Bevel => sk::LineJoin::Bevel,
|
||||||
LineCap::Square => sk::LineCap::Square,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&LineJoin> for sk::LineJoin {
|
fn to_sk_transform(transform: &Transform) -> sk::Transform {
|
||||||
fn from(line_join: &LineJoin) -> Self {
|
let Transform { sx, ky, kx, sy, tx, ty } = *transform;
|
||||||
match line_join {
|
sk::Transform::from_row(
|
||||||
LineJoin::Miter => sk::LineJoin::Miter,
|
sx.get() as _,
|
||||||
LineJoin::Round => sk::LineJoin::Round,
|
ky.get() as _,
|
||||||
LineJoin::Bevel => sk::LineJoin::Bevel,
|
kx.get() as _,
|
||||||
}
|
sy.get() as _,
|
||||||
}
|
tx.to_f32(),
|
||||||
|
ty.to_f32(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows to build tiny-skia paths from glyph outlines.
|
/// Allows to build tiny-skia paths from glyph outlines.
|
||||||
@ -989,13 +970,6 @@ impl AbsExt for Abs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Color> for sk::ColorU8 {
|
|
||||||
fn from(value: Color) -> Self {
|
|
||||||
let [r, g, b, _] = value.to_rgba().to_vec4_u8();
|
|
||||||
sk::ColorU8::from_rgba(r, g, b, 255)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alpha multiplication and blending are ported from:
|
// Alpha multiplication and blending are ported from:
|
||||||
// https://skia.googlesource.com/skia/+/refs/heads/main/include/core/SkColorPriv.h
|
// https://skia.googlesource.com/skia/+/refs/heads/main/include/core/SkColorPriv.h
|
||||||
|
|
@ -34,9 +34,7 @@ miniz_oxide = { workspace = true }
|
|||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
palette = { workspace = true }
|
palette = { workspace = true }
|
||||||
pdf-writer = { workspace = true }
|
pdf-writer = { workspace = true }
|
||||||
pixglyph = { workspace = true }
|
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
resvg = { workspace = true }
|
|
||||||
roxmltree = { workspace = true }
|
roxmltree = { workspace = true }
|
||||||
rustybuzz = { workspace = true }
|
rustybuzz = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
@ -45,7 +43,6 @@ smallvec = { workspace = true }
|
|||||||
subsetter = { workspace = true }
|
subsetter = { workspace = true }
|
||||||
svg2pdf = { workspace = true }
|
svg2pdf = { workspace = true }
|
||||||
time = { workspace = true }
|
time = { workspace = true }
|
||||||
tiny-skia = { workspace = true }
|
|
||||||
toml = { workspace = true }
|
toml = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
ttf-parser = { workspace = true }
|
ttf-parser = { workspace = true }
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
//! Exporting into external formats.
|
//! Exporting into external formats.
|
||||||
|
|
||||||
mod pdf;
|
mod pdf;
|
||||||
mod render;
|
|
||||||
mod svg;
|
mod svg;
|
||||||
|
|
||||||
pub use self::pdf::{pdf, PdfPageLabel, PdfPageLabelStyle};
|
pub use self::pdf::{pdf, PdfPageLabel, PdfPageLabelStyle};
|
||||||
pub use self::render::{render, render_merged};
|
|
||||||
pub use self::svg::{svg, svg_merged};
|
pub use self::svg::{svg, svg_merged};
|
||||||
|
@ -9,6 +9,7 @@ publish = false
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
typst = { workspace = true }
|
typst = { workspace = true }
|
||||||
typst-library = { workspace = true }
|
typst-library = { workspace = true }
|
||||||
|
typst-render = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
comemo = { workspace = true }
|
comemo = { workspace = true }
|
||||||
ecow = { workspace = true }
|
ecow = { workspace = true }
|
||||||
|
@ -90,7 +90,7 @@ fn bench_render(iai: &mut Iai) {
|
|||||||
let world = BenchWorld::new();
|
let world = BenchWorld::new();
|
||||||
let mut tracer = Tracer::new();
|
let mut tracer = Tracer::new();
|
||||||
let document = typst::compile(&world, &mut tracer).unwrap();
|
let document = typst::compile(&world, &mut tracer).unwrap();
|
||||||
iai.run(|| typst::export::render(&document.pages[0], 1.0, Color::WHITE))
|
iai.run(|| typst_render::render(&document.pages[0], 1.0, Color::WHITE))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BenchWorld {
|
struct BenchWorld {
|
||||||
|
@ -26,7 +26,7 @@ use typst::eval::{
|
|||||||
eco_format, func, Bytes, Datetime, Library, NoneValue, Repr, Tracer, Value,
|
eco_format, func, Bytes, Datetime, Library, NoneValue, Repr, Tracer, Value,
|
||||||
};
|
};
|
||||||
use typst::font::{Font, FontBook};
|
use typst::font::{Font, FontBook};
|
||||||
use typst::geom::{Abs, Color, Smart};
|
use typst::geom::{Abs, Color, Smart, Transform};
|
||||||
use typst::syntax::{FileId, PackageVersion, Source, SyntaxNode, VirtualPath};
|
use typst::syntax::{FileId, PackageVersion, Source, SyntaxNode, VirtualPath};
|
||||||
use typst::{World, WorldExt};
|
use typst::{World, WorldExt};
|
||||||
use typst_library::layout::{Margin, PageElem};
|
use typst_library::layout::{Margin, PageElem};
|
||||||
@ -906,7 +906,7 @@ fn render(frames: &[Frame]) -> sk::Pixmap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pixmap = typst::export::render_merged(
|
let mut pixmap = typst_render::render_merged(
|
||||||
frames,
|
frames,
|
||||||
pixel_per_pt,
|
pixel_per_pt,
|
||||||
Color::WHITE,
|
Color::WHITE,
|
||||||
@ -932,7 +932,7 @@ fn render_links(canvas: &mut sk::Pixmap, ts: sk::Transform, frame: &Frame) {
|
|||||||
let ts = ts.pre_translate(pos.x.to_pt() as f32, pos.y.to_pt() as f32);
|
let ts = ts.pre_translate(pos.x.to_pt() as f32, pos.y.to_pt() as f32);
|
||||||
match *item {
|
match *item {
|
||||||
FrameItem::Group(ref group) => {
|
FrameItem::Group(ref group) => {
|
||||||
let ts = ts.pre_concat(group.transform.into());
|
let ts = ts.pre_concat(to_sk_transform(&group.transform));
|
||||||
render_links(canvas, ts, &group.frame);
|
render_links(canvas, ts, &group.frame);
|
||||||
}
|
}
|
||||||
FrameItem::Meta(Meta::Link(_), size) => {
|
FrameItem::Meta(Meta::Link(_), size) => {
|
||||||
@ -948,6 +948,18 @@ fn render_links(canvas: &mut sk::Pixmap, ts: sk::Transform, frame: &Frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_sk_transform(transform: &Transform) -> sk::Transform {
|
||||||
|
let Transform { sx, ky, kx, sy, tx, ty } = *transform;
|
||||||
|
sk::Transform::from_row(
|
||||||
|
sx.get() as _,
|
||||||
|
ky.get() as _,
|
||||||
|
kx.get() as _,
|
||||||
|
sy.get() as _,
|
||||||
|
tx.to_pt() as f32,
|
||||||
|
ty.to_pt() as f32,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// A Linear-feedback shift register using XOR as its shifting function.
|
/// A Linear-feedback shift register using XOR as its shifting function.
|
||||||
/// Can be used as PRNG.
|
/// Can be used as PRNG.
|
||||||
struct LinearShift(u64);
|
struct LinearShift(u64);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user