mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 20:27:05 -06:00
M3.98: radial annotator extent ellipse, aspect handle and off-centre focal point
Radial gradients show a dashed extent ellipse: its handle across the bar sets the aspect ratio, the ellipse elsewhere rotates it, and the dot inside the centre ring drags the focal point (GradientGeom.focal) for an off-centre radial. paint.setGradientGeom takes aspect (%) and focal ([x,y] | null), and start/end may be left out; the focal point keeps its place in the ellipse as the vector, aspect and object transform. It renders as a two-point radial, exports and imports as SVG fx/fy and PDF two-point radial shadings, expands to off-centre rings, and travels in gradient params and the native format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b8793eeaef
commit
d8eff17b9f
+10
-11
@@ -1,7 +1,7 @@
|
||||
//! Paint conversion (solid, gradients, patterns) and image decoding.
|
||||
|
||||
use vectorcraft_color::{GradientKind, Paint};
|
||||
use vectorcraft_geom::{Affine, Rect, Vec2};
|
||||
use vectorcraft_geom::{Rect, Vec2};
|
||||
use vello_cpu::RenderContext;
|
||||
use vello_cpu::peniko::{self, ColorStop};
|
||||
|
||||
@@ -26,16 +26,15 @@ pub(crate) fn set_paint(ctx: &mut RenderContext, p: &Paint, bounds: Rect, f: &Fr
|
||||
let grad = match g.gradient.kind {
|
||||
GradientKind::Radial => {
|
||||
let r = geom.length().max(1e-6) as f32;
|
||||
let angle = (geom.end - geom.start).atan2();
|
||||
// Aspect ratio squashes the circle along the perpendicular of the gradient vector.
|
||||
ctx.set_paint_transform(
|
||||
Affine::translate(geom.start.to_vec2())
|
||||
* Affine::rotate(angle)
|
||||
* Affine::scale_non_uniform(1.0, geom.aspect.max(1e-3))
|
||||
* Affine::rotate(-angle)
|
||||
* Affine::translate(-geom.start.to_vec2()),
|
||||
);
|
||||
peniko::Gradient::new_radial(geom.start, r).with_stops(stops.as_slice())
|
||||
// The aspect ratio squashes the circle across the gradient vector.
|
||||
let squash = geom.radial_squash();
|
||||
ctx.set_paint_transform(squash);
|
||||
let g = match geom.focal {
|
||||
// An off-centre focal point: a two-point radial from it to the extent circle.
|
||||
Some(f) => peniko::Gradient::new_two_point_radial(squash.inverse() * f, 0.0, geom.start, r),
|
||||
None => peniko::Gradient::new_radial(geom.start, r),
|
||||
};
|
||||
g.with_stops(stops.as_slice())
|
||||
}
|
||||
_ => {
|
||||
ctx.reset_paint_transform();
|
||||
|
||||
Reference in New Issue
Block a user