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);
|
||||
|
||||
for window in linear.stops.windows(2) {
|
||||
let (_, start_t) = window[0];
|
||||
let (_, end_t) = window[1];
|
||||
let (start_c, start_t) = window[0];
|
||||
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.
|
||||
// This is a workaround for a bug in many readers:
|
||||
// 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
|
||||
// too much if there are already a lot of stops as in most presets.
|
||||
let len = (256 / linear.stops.len() as u32).max(1);
|
||||
for i in 0..len {
|
||||
let len = if gradient.anti_alias() {
|
||||
(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 t = start_t + (end_t - start_t) * t0;
|
||||
let c = gradient.sample(RatioOrAngle::Ratio(t));
|
||||
@ -685,6 +696,11 @@ impl SVGRenderer {
|
||||
self.xml.write_attribute("stop-color", &c.to_hex());
|
||||
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();
|
||||
|
@ -445,7 +445,7 @@ impl Gradient {
|
||||
angle: grad.angle,
|
||||
space: grad.space,
|
||||
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_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 {
|
||||
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.
|
||||
|
||||
---
|
||||
#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