mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Adjust the number of color components written to the pdf according to the color space (#4568)
This commit is contained in:
parent
1d74c8e8bf
commit
c4dd6fa062
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2774,6 +2774,7 @@ dependencies = [
|
||||
name = "typst-pdf"
|
||||
version = "0.11.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"base64",
|
||||
"bytemuck",
|
||||
"comemo",
|
||||
|
@ -28,6 +28,7 @@ typst-timing = { path = "crates/typst-timing", version = "0.11.0" }
|
||||
typst-utils = { path = "crates/typst-utils", version = "0.11.0" }
|
||||
typst-assets = { git = "https://github.com/typst/typst-assets", rev = "4ee794c" }
|
||||
typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", rev = "48a924d" }
|
||||
arrayvec = "0.7.4"
|
||||
az = "1.2"
|
||||
base64 = "0.22"
|
||||
bitflags = { version = "2", features = ["serde"] }
|
||||
|
@ -26,6 +26,7 @@ indexmap = { workspace = true }
|
||||
miniz_oxide = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
pdf-writer = { workspace = true }
|
||||
arrayvec = { workspace = true }
|
||||
subsetter = { workspace = true }
|
||||
svg2pdf = { workspace = true }
|
||||
ttf-parser = { workspace = true }
|
||||
|
@ -1,3 +1,4 @@
|
||||
use arrayvec::ArrayVec;
|
||||
use once_cell::sync::Lazy;
|
||||
use pdf_writer::{types::DeviceNSubtype, writers, Chunk, Dict, Filter, Name, Ref};
|
||||
use typst::visualize::{Color, ColorSpace, Paint};
|
||||
@ -377,26 +378,34 @@ impl PaintEncode for Color {
|
||||
/// Extra color space functions.
|
||||
pub(super) trait ColorSpaceExt {
|
||||
/// Returns the range of the color space.
|
||||
fn range(self) -> [f32; 6];
|
||||
fn range(self) -> &'static [f32];
|
||||
|
||||
/// Converts a color to the color space.
|
||||
fn convert<U: QuantizedColor>(self, color: Color) -> [U; 3];
|
||||
fn convert<U: QuantizedColor>(self, color: Color) -> ArrayVec<U, 4>;
|
||||
}
|
||||
|
||||
impl ColorSpaceExt for ColorSpace {
|
||||
fn range(self) -> [f32; 6] {
|
||||
[0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
|
||||
fn range(self) -> &'static [f32] {
|
||||
match self {
|
||||
ColorSpace::D65Gray => &[0.0, 1.0],
|
||||
ColorSpace::Oklab => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
ColorSpace::Oklch => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
ColorSpace::LinearRgb => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
ColorSpace::Srgb => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
ColorSpace::Cmyk => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
ColorSpace::Hsl => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
ColorSpace::Hsv => &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
|
||||
}
|
||||
}
|
||||
|
||||
fn convert<U: QuantizedColor>(self, color: Color) -> [U; 3] {
|
||||
let range = self.range();
|
||||
let [x, y, z, _] = self.encode(color);
|
||||
fn convert<U: QuantizedColor>(self, color: Color) -> ArrayVec<U, 4> {
|
||||
let components = self.encode(color);
|
||||
|
||||
[
|
||||
U::quantize(x, [range[0], range[1]]),
|
||||
U::quantize(y, [range[2], range[3]]),
|
||||
U::quantize(z, [range[4], range[5]]),
|
||||
]
|
||||
self.range()
|
||||
.chunks(2)
|
||||
.zip(components)
|
||||
.map(|(range, component)| U::quantize(component, [range[0], range[1]]))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,10 +145,9 @@ pub fn write_gradients(
|
||||
.bits_per_component(16)
|
||||
.bits_per_flag(8)
|
||||
.shading_type(StreamShadingType::CoonsPatch)
|
||||
.decode([
|
||||
0.0, 1.0, 0.0, 1.0, range[0], range[1], range[2], range[3],
|
||||
range[4], range[5],
|
||||
])
|
||||
.decode(
|
||||
[0.0, 1.0, 0.0, 1.0].into_iter().chain(range.iter().copied()),
|
||||
)
|
||||
.anti_alias(gradient.anti_alias())
|
||||
.filter(Filter::FlateDecode);
|
||||
|
||||
@ -216,7 +215,7 @@ fn shading_function(
|
||||
chunk
|
||||
.stitching_function(function)
|
||||
.domain([0.0, 1.0])
|
||||
.range(color_space.range())
|
||||
.range(color_space.range().iter().copied())
|
||||
.functions(functions)
|
||||
.bounds(bounds)
|
||||
.encode(encode);
|
||||
@ -235,7 +234,7 @@ fn single_gradient(
|
||||
let reference = chunk.alloc();
|
||||
chunk
|
||||
.exponential_function(reference)
|
||||
.range(color_space.range())
|
||||
.range(color_space.range().iter().copied())
|
||||
.c0(color_space.convert(first_color))
|
||||
.c1(color_space.convert(second_color))
|
||||
.domain([0.0, 1.0])
|
||||
@ -344,13 +343,13 @@ fn register_gradient(
|
||||
/// Structure:
|
||||
/// - flag: `u8`
|
||||
/// - points: `[u16; 24]`
|
||||
/// - colors: `[u16; 12]`
|
||||
/// - colors: `[u16; 4*N]` (N = number of components)
|
||||
fn write_patch(
|
||||
target: &mut Vec<u8>,
|
||||
t: f32,
|
||||
t1: f32,
|
||||
c0: [u16; 3],
|
||||
c1: [u16; 3],
|
||||
c0: &[u16],
|
||||
c1: &[u16],
|
||||
angle: Angle,
|
||||
) {
|
||||
let theta = -TAU * t + angle.to_rad() as f32 + PI;
|
||||
@ -390,11 +389,13 @@ fn write_patch(
|
||||
p1, p1, p2, p2, cp1, cp2, p3, p3, p1, p1, p1, p1,
|
||||
]));
|
||||
|
||||
let colors =
|
||||
[c0.map(u16::to_be), c0.map(u16::to_be), c1.map(u16::to_be), c1.map(u16::to_be)];
|
||||
|
||||
// Push the colors.
|
||||
target.extend_from_slice(bytemuck::cast_slice(&colors));
|
||||
let colors = [c0, c0, c1, c1]
|
||||
.into_iter()
|
||||
.flat_map(|c| c.iter().copied().map(u16::to_be_bytes))
|
||||
.flatten();
|
||||
|
||||
target.extend(colors);
|
||||
}
|
||||
|
||||
fn control_point(c: Point, r: f32, angle_start: f32, angle_end: f32) -> (Point, Point) {
|
||||
@ -452,8 +453,8 @@ fn compute_vertex_stream(gradient: &Gradient, aspect_ratio: Ratio) -> Arc<Vec<u8
|
||||
&mut vertices,
|
||||
t0.get() as f32,
|
||||
t1.get() as f32,
|
||||
encode_space.convert(c0),
|
||||
encode_space.convert(c1),
|
||||
&encode_space.convert(c0),
|
||||
&encode_space.convert(c1),
|
||||
angle,
|
||||
);
|
||||
continue;
|
||||
@ -483,8 +484,8 @@ fn compute_vertex_stream(gradient: &Gradient, aspect_ratio: Ratio) -> Arc<Vec<u8
|
||||
&mut vertices,
|
||||
t_x as f32,
|
||||
t_next as f32,
|
||||
encode_space.convert(c),
|
||||
encode_space.convert(c_next),
|
||||
&encode_space.convert(c),
|
||||
&encode_space.convert(c_next),
|
||||
angle,
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user