mirror of
https://github.com/typst/typst
synced 2025-06-08 13:16:24 +08:00
conic WIP
This commit is contained in:
parent
de889d9c13
commit
79173b1c55
@ -8,12 +8,11 @@ use krilla::geom::NormalizedF32;
|
|||||||
use krilla::page::{NumberingStyle, PageLabel};
|
use krilla::page::{NumberingStyle, PageLabel};
|
||||||
use krilla::surface::Surface;
|
use krilla::surface::Surface;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use typst_library::layout::Abs;
|
use typst_library::layout::{Abs, Angle, Ratio, Transform};
|
||||||
use typst_library::model::Numbering;
|
use typst_library::model::Numbering;
|
||||||
use typst_library::visualize::{
|
use typst_library::visualize::{ColorSpace, DashPattern, FillRule, FixedStroke, Gradient, Paint, Pattern, RelativeTo};
|
||||||
ColorSpace, DashPattern, FillRule, FixedStroke, Paint, Pattern, RelativeTo,
|
|
||||||
};
|
|
||||||
use typst_utils::Numeric;
|
use typst_utils::Numeric;
|
||||||
|
use crate::gradient_old::PdfGradient;
|
||||||
|
|
||||||
pub(crate) fn fill(
|
pub(crate) fn fill(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
@ -180,55 +179,137 @@ pub(crate) fn convert_pattern(
|
|||||||
|
|
||||||
// TODO: Anti-aliasing
|
// TODO: Anti-aliasing
|
||||||
|
|
||||||
// fn convert_gradient(
|
fn convert_gradient(
|
||||||
// gradient: &Gradient,
|
gradient: &Gradient,
|
||||||
// on_text: bool,
|
on_text: bool,
|
||||||
// mut transforms: Transforms,
|
mut transforms: Transforms,
|
||||||
// ) -> usize {
|
) -> (krilla::paint::Paint, u8) {
|
||||||
// // Edge cases for strokes.
|
// Edge cases for strokes.
|
||||||
// if transforms.size.x.is_zero() {
|
if transforms.size.x.is_zero() {
|
||||||
// transforms.size.x = Abs::pt(1.0);
|
transforms.size.x = Abs::pt(1.0);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if transforms.size.y.is_zero() {
|
if transforms.size.y.is_zero() {
|
||||||
// transforms.size.y = Abs::pt(1.0);
|
transforms.size.y = Abs::pt(1.0);
|
||||||
// }
|
}
|
||||||
// let size = match gradient.unwrap_relative(on_text) {
|
let size = match gradient.unwrap_relative(on_text) {
|
||||||
// RelativeTo::Self_ => transforms.size,
|
RelativeTo::Self_ => transforms.size,
|
||||||
// RelativeTo::Parent => transforms.container_size,
|
RelativeTo::Parent => transforms.container_size,
|
||||||
// };
|
};
|
||||||
//
|
|
||||||
// let rotation = gradient.angle().unwrap_or_else(Angle::zero);
|
let (offset_x, offset_y) = match gradient {
|
||||||
//
|
Gradient::Conic(conic) => (
|
||||||
// let transform = match gradient.unwrap_relative(on_text) {
|
-size.x * (1.0 - conic.center.x.get() / 2.0) / 2.0,
|
||||||
// RelativeTo::Self_ => transforms.transform,
|
-size.y * (1.0 - conic.center.y.get() / 2.0) / 2.0,
|
||||||
// RelativeTo::Parent => transforms.container_transform,
|
),
|
||||||
// };
|
_ => (Abs::zero(), Abs::zero()),
|
||||||
//
|
};
|
||||||
// let scale_offset = match gradient {
|
|
||||||
// Gradient::Conic(_) => 4.0_f64,
|
let rotation = gradient.angle().unwrap_or_else(Angle::zero);
|
||||||
// _ => 1.0,
|
|
||||||
// };
|
let transform = match gradient.unwrap_relative(on_text) {
|
||||||
//
|
RelativeTo::Self_ => transforms.transform,
|
||||||
// let angle = Gradient::correct_aspect_ratio(rotation, size.aspect_ratio());
|
RelativeTo::Parent => transforms.container_transform,
|
||||||
//
|
};
|
||||||
// match &gradient {
|
|
||||||
// Gradient::Linear(_) => {
|
let scale_offset = match gradient {
|
||||||
// let (mut sin, mut cos) = (angle.sin(), angle.cos());
|
Gradient::Conic(_) => 4.0_f64,
|
||||||
//
|
_ => 1.0,
|
||||||
// // Scale to edges of unit square.
|
};
|
||||||
// let factor = cos.abs() + sin.abs();
|
|
||||||
// sin *= factor;
|
let pdf_gradient = PdfGradient {
|
||||||
// cos *= factor;
|
aspect_ratio: size.aspect_ratio(),
|
||||||
//
|
transform: transform
|
||||||
// let (x1, y1, x2, y2): (f64, f64, f64, f64) = match angle.quadrant() {
|
.pre_concat(Transform::translate(
|
||||||
// Quadrant::First => (0.0, 0.0, cos, sin),
|
offset_x * scale_offset,
|
||||||
// Quadrant::Second => (1.0, 0.0, cos + 1.0, sin),
|
offset_y * scale_offset,
|
||||||
// Quadrant::Third => (1.0, 1.0, cos + 1.0, sin + 1.0),
|
))
|
||||||
// Quadrant::Fourth => (0.0, 1.0, cos, sin + 1.0),
|
.pre_concat(Transform::scale(
|
||||||
// };
|
Ratio::new(size.x.to_pt() * scale_offset),
|
||||||
// }
|
Ratio::new(size.y.to_pt() * scale_offset),
|
||||||
// Gradient::Radial(_) => {}
|
)),
|
||||||
// Gradient::Conic(_) => {}
|
gradient: gradient.clone(),
|
||||||
// }
|
angle: Gradient::correct_aspect_ratio(rotation, size.aspect_ratio()),
|
||||||
// }
|
};
|
||||||
|
|
||||||
|
match &gradient {
|
||||||
|
Gradient::Linear(_) => {
|
||||||
|
(krilla::color::rgb::Color::black().into(), 255)
|
||||||
|
}
|
||||||
|
Gradient::Radial(_) => {
|
||||||
|
(krilla::color::rgb::Color::black().into(), 255)
|
||||||
|
}
|
||||||
|
Gradient::Conic(conic) => {
|
||||||
|
// Correct the gradient's angle
|
||||||
|
let angle = Gradient::correct_aspect_ratio(conic.angle, pdf_gradient.aspect_ratio);
|
||||||
|
|
||||||
|
for window in conic.stops.windows(2) {
|
||||||
|
let ((c0, t0), (c1, t1)) = (window[0], window[1]);
|
||||||
|
|
||||||
|
// Precision:
|
||||||
|
// - On an even color, insert a stop every 90deg
|
||||||
|
// - For a hue-based color space, insert 200 stops minimum
|
||||||
|
// - On any other, insert 20 stops minimum
|
||||||
|
let max_dt = if c0 == c1 {
|
||||||
|
0.25
|
||||||
|
} else if conic.space.hue_index().is_some() {
|
||||||
|
0.005
|
||||||
|
} else {
|
||||||
|
0.05
|
||||||
|
};
|
||||||
|
let encode_space = conic
|
||||||
|
.space
|
||||||
|
.hue_index()
|
||||||
|
.map(|_| ColorSpace::Oklab)
|
||||||
|
.unwrap_or(conic.space);
|
||||||
|
let mut t_x = t0.get();
|
||||||
|
let dt = (t1.get() - t0.get()).min(max_dt);
|
||||||
|
|
||||||
|
// Special casing for sharp gradients.
|
||||||
|
if t0 == t1 {
|
||||||
|
write_patch(
|
||||||
|
&mut vertices,
|
||||||
|
t0.get() as f32,
|
||||||
|
t1.get() as f32,
|
||||||
|
&encode_space.convert(c0),
|
||||||
|
&encode_space.convert(c1),
|
||||||
|
angle,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while t_x < t1.get() {
|
||||||
|
let t_next = (t_x + dt).min(t1.get());
|
||||||
|
|
||||||
|
// The current progress in the current window.
|
||||||
|
let t = |t| (t - t0.get()) / (t1.get() - t0.get());
|
||||||
|
let c = Color::mix_iter(
|
||||||
|
[WeightedColor::new(c0, 1.0 - t(t_x)), WeightedColor::new(c1, t(t_x))],
|
||||||
|
conic.space,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let c_next = Color::mix_iter(
|
||||||
|
[
|
||||||
|
WeightedColor::new(c0, 1.0 - t(t_next)),
|
||||||
|
WeightedColor::new(c1, t(t_next)),
|
||||||
|
],
|
||||||
|
conic.space,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
write_patch(
|
||||||
|
&mut vertices,
|
||||||
|
t_x as f32,
|
||||||
|
t_next as f32,
|
||||||
|
&encode_space.convert(c),
|
||||||
|
&encode_space.convert(c_next),
|
||||||
|
angle,
|
||||||
|
);
|
||||||
|
|
||||||
|
t_x = t_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user