mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-24 02:06:54 -06:00
56 lines
2.7 KiB
Rust
56 lines
2.7 KiB
Rust
//! Gradient fills: InDesign stretches a radial gradient with the object's box.
|
||
|
||
use designcraft_color::swatch::{Swatch, SwatchValue};
|
||
use designcraft_color::{Color, Gradient, GradientKind, GradientStop};
|
||
use designcraft_compose::Cache;
|
||
use designcraft_doc::build::NewDocument;
|
||
use designcraft_doc::{Document, Fill, Item, ItemId, Shape, SpreadRef};
|
||
use designcraft_geom::{Affine, Rect, Vec2, shapes};
|
||
use designcraft_render::{Placed, RenderOptions, Rendered, Renderer};
|
||
|
||
/// A 100×200 rectangle at (50, 20) filled with a black-to-white radial gradient.
|
||
fn portrait(vector: Option<[f64; 4]>) -> Document {
|
||
let mut d = Document::new(&NewDocument { width: 200.0, height: 240.0, facing_pages: false, ..Default::default() });
|
||
let stop = |offset: f32, color: Color| GradientStop { offset, color, opacity: 1.0, midpoint: 0.5 };
|
||
d.swatches.push(Swatch {
|
||
name: "Radial".into(),
|
||
value: SwatchValue::Gradient {
|
||
gradient: Gradient { kind: GradientKind::Radial, stops: vec![stop(0.0, Color::BLACK), stop(1.0, Color::WHITE)] },
|
||
},
|
||
locked: false,
|
||
named: true,
|
||
hidden: false,
|
||
});
|
||
let id = ItemId(d.alloc());
|
||
let mut it = Item::new(id, d.default_layer(), Shape::Rectangle, shapes::rectangle(Rect::new(50.0, 20.0, 150.0, 220.0)));
|
||
it.fill = Fill { swatch: "Radial".into(), gradient_vector: vector, ..Fill::none() };
|
||
d.insert_item(SpreadRef::Doc(0), it, None).unwrap();
|
||
d
|
||
}
|
||
|
||
fn render(d: &Document) -> Rendered {
|
||
let mut r = Renderer::new();
|
||
r.threads = 0;
|
||
let opts = RenderOptions { background: Some([255, 255, 255, 255]), ..Default::default() };
|
||
r.render(d, &Cache::new(), &[Placed { spread: SpreadRef::Doc(0), xf: Affine::translate(Vec2::ZERO) }], 200, 240, Affine::IDENTITY, &opts)
|
||
}
|
||
|
||
fn grey(img: &Rendered, x: u32, y: u32) -> u8 {
|
||
img.pixel(x, y)[0]
|
||
}
|
||
|
||
#[test]
|
||
fn a_radial_gradient_stretches_with_its_object() {
|
||
// Centred, it reaches white at the sides and at the top and bottom alike (an ellipse).
|
||
let img = render(&portrait(None));
|
||
assert!(grey(&img, 100, 120) < 20, "black at the centre: {}", grey(&img, 100, 120));
|
||
let (side, top) = (grey(&img, 52, 120), grey(&img, 100, 22));
|
||
assert!(side > 225 && top > 225, "white at the side ({side}) and the top ({top})");
|
||
// Half-way to the side and half-way to the top: the same grey.
|
||
let (hs, ht) = (grey(&img, 75, 120), grey(&img, 100, 70));
|
||
assert!(hs.abs_diff(ht) < 12, "half-way: side {hs}, top {ht}");
|
||
// A Gradient Swatch tool vector to the right side: the same ellipse.
|
||
let dragged = render(&portrait(Some([100.0, 120.0, 150.0, 120.0])));
|
||
assert!(grey(&dragged, 100, 70).abs_diff(ht) < 12 && grey(&dragged, 75, 120).abs_diff(hs) < 12);
|
||
}
|