mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 20:34:18 +00:00
Gradients: conic gradients sweep the stops once around the center
A fourth gradient kind, conic (also accepted as `angle` or `conical`), sweeps the stops once around the center (the gradient's start), clockwise on the page from the vector, with a seam where the last stop meets the first. A negative aspect mirrors the sweep, and reflecting an object turns its sweep the other way, also for a conic without a vector or with a flat extent. - Gradient panel: a Conic button in the Type row; the Aspect Ratio field works for conic gradients and keeps a mirrored sweep mirrored. - Gradient tool: the extent ellipse, aspect handle and center ring of a radial gradient, without a focal point. - Rendering, swatch chips, transforms, warps, plug-in round trips, and Object > Expand into wedges or a mesh of columns around the center. - Commands: a negative `aspect` is an error for linear and radial gradients, and so is a `focal` point for a conic gradient. - PDF export writes a function-based shading whose calculator function turns the angle into the ramp, and PDF import reads a function-based shading that turns around the origin of its space back as a conic gradient, also when that origin lies outside the painted area. A PDF/A file, or a conic with more than 97 stops, gets an image instead. - SVG export writes 360 solid wedges clipped to the shape for opaque stops and an image otherwise, and a linear gradient on characters. - CSS export writes `conic-gradient(from ...)`, with the stops mirrored for a mirrored sweep. - EPS and legacy .ai export write 360 solid wedges; the .ai editing data holds a linear gradient along the vector with the same stops. - .af files: conical gradients open as conic gradients. - An export that writes the gradient in another form gives a warning. Supersedes #2326 and includes switch87's code from it. Co-authored-by: Gert Pellin <gert@pellin.be>
This commit is contained in:
@@ -67,6 +67,28 @@ fn objects_round_trip_through_the_json_model() {
|
||||
assert_eq!(d, before);
|
||||
}
|
||||
|
||||
/// A mirrored conic gradient handed back keeps its negative aspect (its sweep stays mirrored),
|
||||
/// kept within the same range as other aspects; a radial's is kept positive.
|
||||
#[test]
|
||||
fn a_mirrored_conic_keeps_its_sign_through_a_plug_in() {
|
||||
let (d, ids, _) = doc();
|
||||
let a = ids[0].0;
|
||||
let fill = |kind: &str, aspect: f64| {
|
||||
let mut g = vectorcraft_color::GradientPaint::new(vectorcraft_color::Gradient::default());
|
||||
g.geom = Some(vectorcraft_color::GradientGeom { start: Point::new(0.0, 0.0), end: Point::new(10.0, 0.0), aspect, focal: None });
|
||||
let mut p = serde_json::to_value(Paint::Gradient(Box::new(g))).unwrap();
|
||||
p["gradient"]["kind"] = json!(kind);
|
||||
p
|
||||
};
|
||||
for (kind, aspect, want) in [("Conic", -0.5, -0.5), ("Conic", -500.0, -100.0), ("Conic", 0.5, 0.5), ("Radial", -0.5, 0.01)] {
|
||||
let mut d = d.clone();
|
||||
let out = decode_json(json!({"objects": [{"id": a, "fills": [fill(kind, aspect)]}]})).unwrap();
|
||||
apply_output(&mut d, &ids, out, None, &keep).unwrap();
|
||||
let Paint::Gradient(g) = d.node(ids[0]).unwrap().appearance.fill_paint() else { panic!("a gradient fill") };
|
||||
assert_eq!(g.geom.unwrap().aspect, want, "{kind} {aspect}");
|
||||
}
|
||||
}
|
||||
|
||||
/// A path handed back as it was stays the live shape it was (a rectangle keeps its corner
|
||||
/// widgets); a path that changed is a plain path.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user