mirror of
https://github.com/typst/typst
synced 2025-05-18 02:55:28 +08:00
Gradient Part 2a - Fix sharp gradients in SVG (#2307)
This commit is contained in:
parent
55095246bf
commit
57bc614cf4
@ -666,16 +666,27 @@ impl SVGRenderer {
|
|||||||
self.xml.write_attribute("y2", &y2);
|
self.xml.write_attribute("y2", &y2);
|
||||||
|
|
||||||
for window in linear.stops.windows(2) {
|
for window in linear.stops.windows(2) {
|
||||||
let (_, start_t) = window[0];
|
let (start_c, start_t) = window[0];
|
||||||
let (_, end_t) = window[1];
|
let (end_c, end_t) = window[1];
|
||||||
|
|
||||||
|
self.xml.start_element("stop");
|
||||||
|
self.xml
|
||||||
|
.write_attribute_fmt("offset", format_args!("{start_t:?}"));
|
||||||
|
self.xml.write_attribute("stop-color", &start_c.to_hex());
|
||||||
|
self.xml.end_element();
|
||||||
|
|
||||||
// Generate (256 / len) stops between the two stops.
|
// Generate (256 / len) stops between the two stops.
|
||||||
// This is a workaround for a bug in many readers:
|
// This is a workaround for a bug in many readers:
|
||||||
// They tend to just ignore the color space of the gradient.
|
// They tend to just ignore the color space of the gradient.
|
||||||
// The goal is to have smooth gradients but not to balloon the file size
|
// The goal is to have smooth gradients but not to balloon the file size
|
||||||
// too much if there are already a lot of stops as in most presets.
|
// too much if there are already a lot of stops as in most presets.
|
||||||
let len = (256 / linear.stops.len() as u32).max(1);
|
let len = if gradient.anti_alias() {
|
||||||
for i in 0..len {
|
(256 / linear.stops.len() as u32).max(2)
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
};
|
||||||
|
|
||||||
|
for i in 1..(len - 1) {
|
||||||
let t0 = i as f64 / (len - 1) as f64;
|
let t0 = i as f64 / (len - 1) as f64;
|
||||||
let t = start_t + (end_t - start_t) * t0;
|
let t = start_t + (end_t - start_t) * t0;
|
||||||
let c = gradient.sample(RatioOrAngle::Ratio(t));
|
let c = gradient.sample(RatioOrAngle::Ratio(t));
|
||||||
@ -685,6 +696,11 @@ impl SVGRenderer {
|
|||||||
self.xml.write_attribute("stop-color", &c.to_hex());
|
self.xml.write_attribute("stop-color", &c.to_hex());
|
||||||
self.xml.end_element();
|
self.xml.end_element();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.xml.start_element("stop");
|
||||||
|
self.xml.write_attribute_fmt("offset", format_args!("{end_t:?}"));
|
||||||
|
self.xml.write_attribute("stop-color", &end_c.to_hex());
|
||||||
|
self.xml.end_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.xml.end_element();
|
self.xml.end_element();
|
||||||
|
@ -445,7 +445,7 @@ impl Gradient {
|
|||||||
angle: grad.angle,
|
angle: grad.angle,
|
||||||
space: grad.space,
|
space: grad.space,
|
||||||
relative: grad.relative,
|
relative: grad.relative,
|
||||||
anti_alias: true,
|
anti_alias: grad.anti_alias,
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -762,7 +762,7 @@ fn sample_stops(stops: &[(Color, Ratio)], mixing_space: ColorSpace, t: f64) -> C
|
|||||||
let hue_0 = if hue_0 < hue_1 { hue_0 + 360.0 } else { hue_0 };
|
let hue_0 = if hue_0 < hue_1 { hue_0 + 360.0 } else { hue_0 };
|
||||||
let hue_1 = if hue_1 < hue_0 { hue_1 + 360.0 } else { hue_1 };
|
let hue_1 = if hue_1 < hue_0 { hue_1 + 360.0 } else { hue_1 };
|
||||||
|
|
||||||
let hue = (hue_0 * (1.0 - t as f32) + hue_1 * t as f32).rem_euclid(360.0);
|
let hue = hue_0 * (1.0 - t as f32) + hue_1 * t as f32;
|
||||||
|
|
||||||
if mixing_space == ColorSpace::Hsl {
|
if mixing_space == ColorSpace::Hsl {
|
||||||
let [_, saturation, lightness, alpha] = out.to_hsl().to_vec4();
|
let [_, saturation, lightness, alpha] = out.to_hsl().to_vec4();
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 45 KiB |
@ -1,4 +1,13 @@
|
|||||||
// Test sharp gradients.
|
// Test sharp gradients.
|
||||||
|
|
||||||
---
|
---
|
||||||
#square(size: 100pt, fill: gradient.linear(..color.map.rainbow).sharp(10))
|
#square(
|
||||||
|
size: 100pt,
|
||||||
|
fill: gradient.linear(..color.map.rainbow, space: color.hsl).sharp(10),
|
||||||
|
)
|
||||||
|
|
||||||
|
---
|
||||||
|
#square(
|
||||||
|
size: 100pt,
|
||||||
|
fill: gradient.linear(..color.map.rainbow, space: color.hsl).sharp(10, smoothness: 40%),
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user