mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 09:20:56 -06:00
Revolve: the fills and strokes of one object share the paint-copy budget
Each fill or stroke with its own Revolve counted the copies of its paint from zero, so an object with several of them could draw past the 256 MiB budget. They now share one count, and past it the source path draws, as for the members of a group. effect.apply and effect.setParams on a fill or stroke now check the Revolve in that item's paint, after the item's geometry effects before it, together with the object's other items that carry a Revolve. Before, they checked the object's top fill. docs/revolve.md marks the axis position, type handling and member paint as VectorCraft's own rules, and docs/mcp.md says how the budget is counted.
This commit is contained in:
@@ -280,9 +280,13 @@ pub(crate) fn apply(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
let item = item_target(s, p, C)?;
|
||||
if effects::is_three_d(id) {
|
||||
for target in appearance_targets(s, p)? {
|
||||
let targets = appearance_targets(s, p)?;
|
||||
for (target, at) in targets.iter().copied().zip(item.per_target(s, &targets)) {
|
||||
let n = s.doc()?.doc.node(target).ok_or(EngineError::NoNode(target))?;
|
||||
effects::validate_three_d(n, id, &effect.params).map_err(|e| bad(C, e))?;
|
||||
// A new effect goes after the item's others.
|
||||
let on = at.and_then(|at| at.effects_item(&n.appearance, C).ok()).flatten();
|
||||
let on = on.and_then(|i| Some((i, n.appearance.items.get(i)?.effects().len())));
|
||||
effects::validate_three_d_at(n, id, &effect.params, on).map_err(|e| bad(C, e))?;
|
||||
if id == effects::REVOLVE && effects::has_revolve(n) {
|
||||
return Err(bad(C, "A profile supports one Revolve effect. Edit the existing effect's options instead."));
|
||||
}
|
||||
@@ -589,7 +593,7 @@ fn set_params(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
cur.extend(new);
|
||||
}
|
||||
if visible != Some(false) {
|
||||
effects::validate_three_d(n, to, &prospective).map_err(|e| bad(C, e))?;
|
||||
effects::validate_three_d_at(n, to, &prospective, target.map(|item| (item, index))).map_err(|e| bad(C, e))?;
|
||||
} else {
|
||||
// Hidden, the effect draws nothing, so its object need not fit. The values given are
|
||||
// checked, and after a change of 3D type so is every value it keeps.
|
||||
|
||||
@@ -260,6 +260,31 @@ fn revolve_refuses_type_and_groups_without_a_shape() {
|
||||
assert!(node(&s, g).appearance.effects.is_empty());
|
||||
}
|
||||
|
||||
/// A Revolve on one fill is checked in that fill's paint, and `effect.setParams` on it as well.
|
||||
#[test]
|
||||
fn revolve_on_a_fill_is_checked_in_that_fills_paint() {
|
||||
use vectorcraft_color::{Color, Gradient, GradientKind, GradientPaint, GradientStop, Paint};
|
||||
use vectorcraft_doc::{AppearanceItem, FillLayer};
|
||||
let (mut s, id) = session_with_rect();
|
||||
// The paint copies of 100 faces reach the 256 MiB budget: 8 segments stay under, 64 pass it.
|
||||
let count = (256 << 20) / (4 * 100 * std::mem::size_of::<GradientStop>());
|
||||
let stops = (0..count).map(|i| GradientStop::new(i as f32 / count as f32, Color::rgb(1.0, 0.0, 0.0))).collect();
|
||||
let ramp = Paint::Gradient(Box::new(GradientPaint::new(Gradient::new(GradientKind::Linear, stops))));
|
||||
s.edit("fills", |d, _| {
|
||||
let n = d.node_mut(id).unwrap();
|
||||
n.appearance.items =
|
||||
vec![AppearanceItem::Fill(FillLayer::new(ramp)), AppearanceItem::Fill(FillLayer::new(Paint::solid(Color::rgb(0.0, 0.0, 1.0))))];
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
let err = s.execute("effect.apply", &json!({"effect": "threeD.revolve", "ids": [id.0], "item": 0})).unwrap_err().to_string();
|
||||
assert!(err.contains("simplify the gradient"), "{err}");
|
||||
assert!(node(&s, id).appearance.items[0].effects().is_empty());
|
||||
s.execute("effect.apply", &json!({"effect": "threeD.revolve", "ids": [id.0], "item": 0, "params": {"segments": 8}})).unwrap();
|
||||
let err = s.execute("effect.setParams", &json!({"index": 0, "ids": [id.0], "item": 0, "params": {"segments": 128}})).unwrap_err().to_string();
|
||||
assert!(err.contains("simplify the gradient"), "{err}");
|
||||
}
|
||||
|
||||
/// Revolve on a group sweeps every member about one axis on the left edge of their bounds, keeps
|
||||
/// each member's paint, follows an edited member, expands and undoes as one step.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user