mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 06:31:19 +00:00
Plug-ins: kept rasters over painted pieces follow the swatches and patterns they name
A blur or shadow over a painted piece is drawn again when a swatch or pattern the piece names is deleted, or when the tiles of a named pattern change. The raster's inputs now include the swatch and pattern names and the pattern definitions for content with a plug-in effect.
This commit is contained in:
@@ -522,6 +522,64 @@ fn kept_art_follows_the_swatches_once_a_replaced_plugin_paints() {
|
||||
assert_eq!(draw(&s), (WHITE, RED), "without the swatch, the object as it is");
|
||||
}
|
||||
|
||||
/// Whether `px` is within 40 levels of `want` on every channel. A blur leaves the middle of a
|
||||
/// shape close to its color.
|
||||
fn near(px: [u8; 4], want: [u8; 4]) -> bool {
|
||||
px.iter().zip(want).all(|(a, b)| a.abs_diff(b) <= 40)
|
||||
}
|
||||
|
||||
/// A kept raster of a blur over a painted effect is made again when a swatch its piece names
|
||||
/// leaves the document (the object is then drawn as if the effect weren't there) and when Undo
|
||||
/// brings the swatch back.
|
||||
#[test]
|
||||
fn a_kept_raster_follows_the_swatches_painted_pieces_name() {
|
||||
let mut s = session();
|
||||
let id = rect(&mut s, 10.0, "#ff0000");
|
||||
run(&mut s, "swatch.new", json!({"name": "Leaf", "color": "#00ff00"}));
|
||||
install_wat(&mut s, &tpl::returning(&painting("test.engine.blurpaint", true), &leaf_square()));
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "effect": "plugin.test.engine.blurpaint"}));
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "effect": "blur.gaussian", "params": {"radius": 1}}));
|
||||
let mut r = vectorcraft_render::Renderer::new();
|
||||
let opts = vectorcraft_render::RenderOptions { background: Some([255, 255, 255, 255]), ..Default::default() };
|
||||
let mut draw = |s: &Session| r.render(&s.doc().unwrap().doc, 200, 200, vectorcraft_geom::Affine::IDENTITY, &opts);
|
||||
let img = draw(&s);
|
||||
assert!(near(img.pixel(50, 50), GREEN) && near(img.pixel(15, 15), WHITE), "the piece, green and blurred");
|
||||
run(&mut s, "swatch.delete", json!({"name": "Leaf"}));
|
||||
let img = draw(&s);
|
||||
assert!(near(img.pixel(50, 50), WHITE) && near(img.pixel(15, 15), RED), "without the swatch, the object as it is: {:?}", img.pixel(50, 50));
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
let img = draw(&s);
|
||||
assert!(near(img.pixel(50, 50), GREEN) && near(img.pixel(15, 15), WHITE), "the swatch back, the piece again");
|
||||
}
|
||||
|
||||
/// A kept raster of a blur over a painted effect is made again when the tile of a pattern its
|
||||
/// piece names changes and the pattern keeps its name.
|
||||
#[test]
|
||||
fn a_kept_raster_follows_the_tiles_of_patterns_painted_pieces_name() {
|
||||
let mut s = session();
|
||||
let id = rect(&mut s, 10.0, "#ff0000");
|
||||
let green = rect(&mut s, 300.0, "#00ff00");
|
||||
let blue = rect(&mut s, 320.0, "#0000ff");
|
||||
let tile = |r: f64, art: vectorcraft_doc::Node| vectorcraft_doc::pattern::PatternDef {
|
||||
tile: vectorcraft_geom::Rect::new(r, 10.0, r + 10.0, 20.0),
|
||||
..vectorcraft_doc::pattern::PatternDef::new("Tiles", vec![std::sync::Arc::new(art)])
|
||||
};
|
||||
let (first, second) = (tile(300.0, node(&s, green)), tile(320.0, node(&s, blue)));
|
||||
std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc).patterns.push(first);
|
||||
let paint = serde_json::to_value(Paint::Pattern { pattern: "Tiles".into(), xf: vectorcraft_geom::Affine::IDENTITY }).unwrap();
|
||||
let out = json!({"objects": [{"path": square_at(40.0), "fills": [paint]}]}).to_string();
|
||||
install_wat(&mut s, &tpl::returning(&painting("test.engine.tilepaint", true), &out));
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "effect": "plugin.test.engine.tilepaint"}));
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "effect": "blur.gaussian", "params": {"radius": 1}}));
|
||||
let mut r = vectorcraft_render::Renderer::new();
|
||||
let opts = vectorcraft_render::RenderOptions { background: Some([255, 255, 255, 255]), ..Default::default() };
|
||||
let mut draw = |s: &Session| r.render(&s.doc().unwrap().doc, 200, 200, vectorcraft_geom::Affine::IDENTITY, &opts).pixel(50, 50);
|
||||
assert!(near(draw(&s), GREEN), "the piece in the green tile");
|
||||
std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc).patterns[0] = second;
|
||||
let px = draw(&s);
|
||||
assert!(near(px, BLUE), "the piece in the new tile: {px:?}");
|
||||
}
|
||||
|
||||
/// Every painted piece counts against the effects' budget, however small its path: two painted
|
||||
/// effects in a stack that each return 350 tiny triangles make no more than 100,000 objects, not
|
||||
/// 350 × 350 of them.
|
||||
|
||||
@@ -398,8 +398,10 @@ impl Renderer {
|
||||
/// [`crate::RenderOptions::kept_images_only`], also which pixels and undecodable notes the
|
||||
/// image store holds); for type the fonts, whether overprinting shows
|
||||
/// ([`crate::proof::overprints`]) and Document Setup's substitution highlights; and the
|
||||
/// plug-ins installed, when an object in it has a plug-in effect, and when it shows symbol or
|
||||
/// pattern art and an object in the document's symbol or pattern art has one.
|
||||
/// plug-ins installed, with the names of the document's swatches and patterns and its pattern
|
||||
/// definitions (a plug-in's painted pieces can name them), when an object in it has a plug-in
|
||||
/// effect, and when it shows symbol or pattern art and an object in the document's symbol or
|
||||
/// pattern art has one.
|
||||
pub(crate) fn raster_inputs(&mut self, f: &Frame, n: &Node, reads: Reads) -> Inputs {
|
||||
let doc = self.doc_inputs(f.doc);
|
||||
let mut h = DefaultHasher::new();
|
||||
@@ -442,7 +444,7 @@ impl Renderer {
|
||||
(vectorcraft_text::FontDb::global().generation(), crate::proof::overprints(f.opts), highlights).hash(&mut h);
|
||||
}
|
||||
if reads.plugins || (doc.plugins && (reads.symbols || reads.patterns)) {
|
||||
effects::plugin_revision().hash(&mut h);
|
||||
(effects::plugin_revision(), doc.names, doc.patterns).hash(&mut h);
|
||||
}
|
||||
Inputs { reads, key: h.finish(), _doc: doc }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user