mirror of
https://github.com/typst/typst
synced 2025-05-20 03:55:29 +08:00
Fix CMYK on gradients (#3142)
This commit is contained in:
parent
67a0afe9bd
commit
712eaaa5f4
@ -39,15 +39,20 @@ pub(crate) fn write_gradients(ctx: &mut PdfContext) {
|
|||||||
let shading = ctx.alloc.bump();
|
let shading = ctx.alloc.bump();
|
||||||
ctx.gradient_refs.push(shading);
|
ctx.gradient_refs.push(shading);
|
||||||
|
|
||||||
|
let color_space = if gradient.space().hue_index().is_some() {
|
||||||
|
ColorSpace::Oklab
|
||||||
|
} else {
|
||||||
|
gradient.space()
|
||||||
|
};
|
||||||
|
|
||||||
let mut shading_pattern = match &gradient {
|
let mut shading_pattern = match &gradient {
|
||||||
Gradient::Linear(_) => {
|
Gradient::Linear(_) => {
|
||||||
let shading_function = shading_function(ctx, &gradient);
|
let shading_function = shading_function(ctx, &gradient, color_space);
|
||||||
let mut shading_pattern = ctx.pdf.shading_pattern(shading);
|
let mut shading_pattern = ctx.pdf.shading_pattern(shading);
|
||||||
let mut shading = shading_pattern.function_shading();
|
let mut shading = shading_pattern.function_shading();
|
||||||
shading.shading_type(FunctionShadingType::Axial);
|
shading.shading_type(FunctionShadingType::Axial);
|
||||||
|
|
||||||
ctx.colors
|
ctx.colors.write(color_space, shading.color_space(), &mut ctx.alloc);
|
||||||
.write(gradient.space(), shading.color_space(), &mut ctx.alloc);
|
|
||||||
|
|
||||||
let (mut sin, mut cos) = (angle.sin(), angle.cos());
|
let (mut sin, mut cos) = (angle.sin(), angle.cos());
|
||||||
|
|
||||||
@ -74,13 +79,12 @@ pub(crate) fn write_gradients(ctx: &mut PdfContext) {
|
|||||||
shading_pattern
|
shading_pattern
|
||||||
}
|
}
|
||||||
Gradient::Radial(radial) => {
|
Gradient::Radial(radial) => {
|
||||||
let shading_function = shading_function(ctx, &gradient);
|
let shading_function = shading_function(ctx, &gradient, color_space);
|
||||||
let mut shading_pattern = ctx.pdf.shading_pattern(shading);
|
let mut shading_pattern = ctx.pdf.shading_pattern(shading);
|
||||||
let mut shading = shading_pattern.function_shading();
|
let mut shading = shading_pattern.function_shading();
|
||||||
shading.shading_type(FunctionShadingType::Radial);
|
shading.shading_type(FunctionShadingType::Radial);
|
||||||
|
|
||||||
ctx.colors
|
ctx.colors.write(color_space, shading.color_space(), &mut ctx.alloc);
|
||||||
.write(gradient.space(), shading.color_space(), &mut ctx.alloc);
|
|
||||||
|
|
||||||
shading
|
shading
|
||||||
.anti_alias(gradient.anti_alias())
|
.anti_alias(gradient.anti_alias())
|
||||||
@ -99,7 +103,7 @@ pub(crate) fn write_gradients(ctx: &mut PdfContext) {
|
|||||||
|
|
||||||
shading_pattern
|
shading_pattern
|
||||||
}
|
}
|
||||||
Gradient::Conic(conic) => {
|
Gradient::Conic(_) => {
|
||||||
let vertices = compute_vertex_stream(&gradient, aspect_ratio);
|
let vertices = compute_vertex_stream(&gradient, aspect_ratio);
|
||||||
|
|
||||||
let stream_shading_id = ctx.alloc.bump();
|
let stream_shading_id = ctx.alloc.bump();
|
||||||
@ -107,12 +111,12 @@ pub(crate) fn write_gradients(ctx: &mut PdfContext) {
|
|||||||
ctx.pdf.stream_shading(stream_shading_id, &vertices);
|
ctx.pdf.stream_shading(stream_shading_id, &vertices);
|
||||||
|
|
||||||
ctx.colors.write(
|
ctx.colors.write(
|
||||||
conic.space,
|
color_space,
|
||||||
stream_shading.color_space(),
|
stream_shading.color_space(),
|
||||||
&mut ctx.alloc,
|
&mut ctx.alloc,
|
||||||
);
|
);
|
||||||
|
|
||||||
let range = conic.space.range();
|
let range = color_space.range();
|
||||||
stream_shading
|
stream_shading
|
||||||
.bits_per_coordinate(16)
|
.bits_per_coordinate(16)
|
||||||
.bits_per_component(16)
|
.bits_per_component(16)
|
||||||
@ -138,7 +142,11 @@ pub(crate) fn write_gradients(ctx: &mut PdfContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an expotential or stitched function that expresses the gradient.
|
/// Writes an expotential or stitched function that expresses the gradient.
|
||||||
fn shading_function(ctx: &mut PdfContext, gradient: &Gradient) -> Ref {
|
fn shading_function(
|
||||||
|
ctx: &mut PdfContext,
|
||||||
|
gradient: &Gradient,
|
||||||
|
color_space: ColorSpace,
|
||||||
|
) -> Ref {
|
||||||
let function = ctx.alloc.bump();
|
let function = ctx.alloc.bump();
|
||||||
let mut functions = vec![];
|
let mut functions = vec![];
|
||||||
let mut bounds = vec![];
|
let mut bounds = vec![];
|
||||||
@ -158,7 +166,7 @@ fn shading_function(ctx: &mut PdfContext, gradient: &Gradient) -> Ref {
|
|||||||
let real_t = first.1.get() * (1.0 - t) + second.1.get() * t;
|
let real_t = first.1.get() * (1.0 - t) + second.1.get() * t;
|
||||||
|
|
||||||
let c = gradient.sample(RatioOrAngle::Ratio(Ratio::new(real_t)));
|
let c = gradient.sample(RatioOrAngle::Ratio(Ratio::new(real_t)));
|
||||||
functions.push(single_gradient(ctx, last_c, c, ColorSpace::Oklab));
|
functions.push(single_gradient(ctx, last_c, c, color_space));
|
||||||
bounds.push(real_t as f32);
|
bounds.push(real_t as f32);
|
||||||
encode.extend([0.0, 1.0]);
|
encode.extend([0.0, 1.0]);
|
||||||
last_c = c;
|
last_c = c;
|
||||||
@ -166,7 +174,7 @@ fn shading_function(ctx: &mut PdfContext, gradient: &Gradient) -> Ref {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bounds.push(second.1.get() as f32);
|
bounds.push(second.1.get() as f32);
|
||||||
functions.push(single_gradient(ctx, first.0, second.0, gradient.space()));
|
functions.push(single_gradient(ctx, first.0, second.0, color_space));
|
||||||
encode.extend([0.0, 1.0]);
|
encode.extend([0.0, 1.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +190,7 @@ fn shading_function(ctx: &mut PdfContext, gradient: &Gradient) -> Ref {
|
|||||||
ctx.pdf
|
ctx.pdf
|
||||||
.stitching_function(function)
|
.stitching_function(function)
|
||||||
.domain([0.0, 1.0])
|
.domain([0.0, 1.0])
|
||||||
.range(gradient.space().range())
|
.range(color_space.range())
|
||||||
.functions(functions)
|
.functions(functions)
|
||||||
.bounds(bounds)
|
.bounds(bounds)
|
||||||
.encode(encode);
|
.encode(encode);
|
||||||
|
BIN
tests/ref/bugs/gradient-cmyk-encode.png
Normal file
BIN
tests/ref/bugs/gradient-cmyk-encode.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 875 B |
27
tests/typ/bugs/gradient-cmyk-encode.typ
Normal file
27
tests/typ/bugs/gradient-cmyk-encode.typ
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Test that CMYK works on gradients
|
||||||
|
|
||||||
|
---
|
||||||
|
#set page(margin: 0pt, width: 200pt, height: auto)
|
||||||
|
|
||||||
|
#let violet = cmyk(75%, 80%, 0%, 0%)
|
||||||
|
#let blue = cmyk(75%, 30%, 0%, 0%)
|
||||||
|
|
||||||
|
#rect(
|
||||||
|
width: 100%,
|
||||||
|
height: 30pt,
|
||||||
|
fill: gradient.linear(violet, blue)
|
||||||
|
)
|
||||||
|
|
||||||
|
#rect(
|
||||||
|
width: 100%,
|
||||||
|
height: 30pt,
|
||||||
|
fill: gradient.linear(rgb(violet), rgb(blue))
|
||||||
|
)
|
||||||
|
|
||||||
|
// In PDF format, this gradient can look different from the others.
|
||||||
|
// This is because PDF readers do weird things with CMYK.
|
||||||
|
#rect(
|
||||||
|
width: 100%,
|
||||||
|
height: 30pt,
|
||||||
|
fill: gradient.linear(violet, blue, space: cmyk)
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user