mirror of
https://github.com/typst/typst
synced 2025-06-08 13:16:24 +08:00
add radial gradients
This commit is contained in:
parent
67bc4bbf71
commit
9b8c30a5f0
@ -362,6 +362,7 @@ pub fn handle_shape(
|
||||
path_builder.line_to(l.x.to_f32(), l.y.to_f32());
|
||||
}
|
||||
Geometry::Rect(r) => {
|
||||
println!("{:?}", r);
|
||||
if let Some(r) = Rect::from_xywh(0.0, 0.0, r.x.to_f32(), r.y.to_f32()) {
|
||||
path_builder.push_rect(r);
|
||||
}
|
||||
|
@ -6,12 +6,15 @@ use crate::primitive::{FillRuleExt, LineCapExt, LineJoinExt, TransformExt};
|
||||
use crate::AbsExt;
|
||||
use krilla::geom::NormalizedF32;
|
||||
use krilla::page::{NumberingStyle, PageLabel};
|
||||
use krilla::paint::SpreadMethod;
|
||||
use krilla::surface::Surface;
|
||||
use std::num::NonZeroUsize;
|
||||
use krilla::paint::SpreadMethod;
|
||||
use typst_library::layout::{Abs, Angle, AngleUnit, Quadrant, Ratio, Size, Transform};
|
||||
use typst_library::model::Numbering;
|
||||
use typst_library::visualize::{Color, ColorSpace, DashPattern, FillRule, FixedStroke, Gradient, Paint, Pattern, RatioOrAngle, RelativeTo, WeightedColor};
|
||||
use typst_library::visualize::{
|
||||
Color, ColorSpace, DashPattern, FillRule, FixedStroke, Gradient, Paint, Pattern,
|
||||
RatioOrAngle, RelativeTo, WeightedColor,
|
||||
};
|
||||
use typst_utils::Numeric;
|
||||
|
||||
pub(crate) fn fill(
|
||||
@ -60,11 +63,7 @@ fn dash(dash: &DashPattern<Abs, Abs>) -> krilla::path::StrokeDash {
|
||||
fn convert_color(color: &Color) -> (krilla::color::rgb::Color, u8) {
|
||||
let components = color.to_space(ColorSpace::Srgb).to_vec4_u8();
|
||||
(
|
||||
krilla::color::rgb::Color::new(
|
||||
components[0],
|
||||
components[1],
|
||||
components[2],
|
||||
)
|
||||
krilla::color::rgb::Color::new(components[0], components[1], components[2])
|
||||
.into(),
|
||||
components[3],
|
||||
)
|
||||
@ -81,7 +80,7 @@ fn paint(
|
||||
Paint::Solid(c) => {
|
||||
let (c, alpha) = convert_color(c);
|
||||
(c.into(), alpha)
|
||||
},
|
||||
}
|
||||
Paint::Gradient(g) => convert_gradient(g, on_text, transforms),
|
||||
Paint::Pattern(p) => convert_pattern(gc, p, on_text, surface, transforms),
|
||||
}
|
||||
@ -208,7 +207,8 @@ fn convert_gradient(
|
||||
RelativeTo::Parent => transforms.container_transform,
|
||||
};
|
||||
|
||||
let angle = Gradient::correct_aspect_ratio(rotation, size.aspect_ratio());
|
||||
let angle = rotation;
|
||||
println!("angle: {:?}", angle);
|
||||
|
||||
let mut stops: Vec<krilla::paint::Stop<krilla::color::rgb::Color>> = vec![];
|
||||
|
||||
@ -216,18 +216,14 @@ fn convert_gradient(
|
||||
let (color, opacity) = convert_color(color);
|
||||
let opacity = NormalizedF32::new((opacity as f32) / 255.0).unwrap();
|
||||
let offset = NormalizedF32::new(offset.get() as f32).unwrap();
|
||||
let stop = krilla::paint::Stop {
|
||||
offset,
|
||||
color,
|
||||
opacity,
|
||||
};
|
||||
let stop = krilla::paint::Stop { offset, color, opacity };
|
||||
stops.push(stop);
|
||||
};
|
||||
|
||||
match &gradient {
|
||||
Gradient::Linear(linear) => {
|
||||
let actual_transform = transforms.transform.invert().unwrap()
|
||||
.pre_concat(transform);
|
||||
let actual_transform =
|
||||
transforms.transform.invert().unwrap().pre_concat(transform);
|
||||
|
||||
if let Some((c, t)) = linear.stops.first() {
|
||||
add_single(c, *t);
|
||||
@ -244,7 +240,8 @@ fn convert_gradient(
|
||||
if gradient.space().hue_index().is_some() {
|
||||
for i in 0..=32 {
|
||||
let t = i as f64 / 32.0;
|
||||
let real_t = Ratio::new(first.1.get() * (1.0 - t) + second.1.get() * t);
|
||||
let real_t =
|
||||
Ratio::new(first.1.get() * (1.0 - t) + second.1.get() * t);
|
||||
|
||||
let c = gradient.sample(RatioOrAngle::Ratio(real_t));
|
||||
add_single(&c, real_t);
|
||||
@ -274,7 +271,9 @@ fn convert_gradient(
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
transform: actual_transform.as_krilla().pre_concat(krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32())),
|
||||
transform: actual_transform.as_krilla().pre_concat(
|
||||
krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32()),
|
||||
),
|
||||
spread_method: SpreadMethod::Pad,
|
||||
stops: stops.into(),
|
||||
anti_alias: gradient.anti_alias(),
|
||||
@ -282,16 +281,74 @@ fn convert_gradient(
|
||||
|
||||
(linear.into(), 255)
|
||||
}
|
||||
Gradient::Radial(_) => {
|
||||
(krilla::color::rgb::Color::black().into(), 255)
|
||||
Gradient::Radial(radial) => {
|
||||
let actual_transform =
|
||||
transforms.transform.invert().unwrap().pre_concat(transform);
|
||||
|
||||
if let Some((c, t)) = radial.stops.first() {
|
||||
add_single(c, *t);
|
||||
}
|
||||
|
||||
// Create the individual gradient functions for each pair of stops.
|
||||
for window in radial.stops.windows(2) {
|
||||
let (first, second) = (window[0], window[1]);
|
||||
|
||||
// If we have a hue index or are using Oklab, we will create several
|
||||
// stops in-between to make the gradient smoother without interpolation
|
||||
// issues with native color spaces.
|
||||
let mut last_c = first.0;
|
||||
if gradient.space().hue_index().is_some() {
|
||||
for i in 0..=32 {
|
||||
let t = i as f64 / 32.0;
|
||||
let real_t =
|
||||
Ratio::new(first.1.get() * (1.0 - t) + second.1.get() * t);
|
||||
|
||||
let c = gradient.sample(RatioOrAngle::Ratio(real_t));
|
||||
add_single(&c, real_t);
|
||||
last_c = c;
|
||||
}
|
||||
}
|
||||
|
||||
add_single(&second.0, second.1);
|
||||
}
|
||||
|
||||
let radial = krilla::paint::RadialGradient {
|
||||
fx: radial.focal_center.x.get() as f32,
|
||||
fy: radial.focal_center.y.get() as f32,
|
||||
fr: radial.focal_radius.get() as f32,
|
||||
cx: radial.center.x.get() as f32,
|
||||
cy: radial.center.y.get() as f32,
|
||||
cr: radial.radius.get() as f32,
|
||||
transform: actual_transform.as_krilla().pre_concat(
|
||||
krilla::geom::Transform::from_scale(size.x.to_f32(), size.y.to_f32()),
|
||||
),
|
||||
spread_method: SpreadMethod::Pad,
|
||||
stops: stops.into(),
|
||||
anti_alias: gradient.anti_alias(),
|
||||
};
|
||||
|
||||
(radial.into(), 255)
|
||||
}
|
||||
Gradient::Conic(conic) => {
|
||||
// Correct the gradient's angle
|
||||
let cx = size.x.to_f32() * conic.center.x.get() as f32;
|
||||
let cy = size.y.to_f32() * conic.center.y.get() as f32;
|
||||
let actual_transform = transforms.transform.invert().unwrap().pre_concat(transform)
|
||||
.pre_concat(Transform::scale_at(-Ratio::one(), Ratio::one(), Abs::pt(cx as f64), Abs::pt(cy as f64)))
|
||||
.pre_concat(Transform::rotate_at(-angle, Abs::pt(cx as f64), Abs::pt(cy as f64)));
|
||||
let actual_transform = transforms
|
||||
.transform
|
||||
.invert()
|
||||
.unwrap()
|
||||
.pre_concat(transform)
|
||||
.pre_concat(Transform::rotate_at(
|
||||
angle,
|
||||
Abs::pt(cx as f64),
|
||||
Abs::pt(cy as f64),
|
||||
))
|
||||
.pre_concat(Transform::scale_at(
|
||||
-Ratio::one(),
|
||||
Ratio::one(),
|
||||
Abs::pt(cx as f64),
|
||||
Abs::pt(cy as f64),
|
||||
));
|
||||
|
||||
if let Some((c, t)) = conic.stops.first() {
|
||||
add_single(c, *t);
|
||||
@ -334,7 +391,7 @@ fn convert_gradient(
|
||||
],
|
||||
conic.space,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
add_single(&c_next, Ratio::new(t_next));
|
||||
t_x = t_next;
|
||||
|
Loading…
x
Reference in New Issue
Block a user