Merge pull request #3322 from dotCooCoo/fix/objects-on-path-refuses-live-containers

Objects on Path: clipping paths and parts of blends, envelopes and repeats stay in place
This commit is contained in:
BFlat
2026-10-21 17:27:14 +07:00
committed by GitHub
25 changed files with 251 additions and 6 deletions
+42 -1
View File
@@ -20,7 +20,7 @@ use vectorcraft_geom::{Affine, PathData, Point};
use crate::blend::Spine;
use crate::symbols::SymbolBoxes;
use crate::{Node, NodeId, NodeKind};
use crate::{Document, Node, NodeId, NodeKind};
/// The center of the nine reference points.
pub const CENTER: u8 = 4;
@@ -157,6 +157,47 @@ pub fn attachable_path(n: &Node) -> Option<&PathData> {
}
}
/// What keeps an object from going into an Objects on Path group, as its path or as one of its
/// objects ([`held`]).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Held {
/// It is inside a compound path, blend, envelope, repeat or Intertwine group, as part of its art.
Live,
/// It is the clipping path of a clip group or of a layer with a clipping mask, or inside one.
Clipping,
}
/// What keeps the object `id` of `d` where it is ([`Held`]), if anything: in an Objects on Path
/// group it would no longer be a part of the compound path, blend, envelope, repeat or Intertwine
/// group it is in, or of the clipping path it is or is in. The innermost reason counts. `None` for
/// an object that is neither a clipping path nor inside one and is in a layer directly or through
/// plain groups and clip groups, and for an id not in `d`.
pub fn held(d: &Document, id: NodeId) -> Option<Held> {
let path = d.index_path(id)?;
let mut chain: Vec<&Node> = Vec::with_capacity(path.len());
let mut nodes = &d.layers;
for &i in &path {
let n: &Node = nodes.get(i)?;
chain.push(n);
if let Some(children) = n.children() {
nodes = children;
}
}
for (depth, n) in chain.iter().enumerate().rev() {
let Some(parent) = depth.checked_sub(1).and_then(|up| chain.get(up)) else { break };
if matches!(n.kind, NodeKind::Path { clipping: true, .. }) || (parent.clips() && path.get(depth) == Some(&0)) {
return Some(Held::Clipping);
}
if matches!(
parent.kind,
NodeKind::Compound { .. } | NodeKind::Blend { .. } | NodeKind::Envelope { .. } | NodeKind::Repeat(_) | NodeKind::Intertwine { .. }
) {
return Some(Held::Live);
}
}
None
}
/// The frame `n` is drawn in when it is attached: the page's axes turned by its rotation
/// ([`Node::bbox_angle`]) less the nearest multiple of 90°, about the center of its bounds. Placed in
/// that frame, an object stands square to the path or across it.
+10 -2
View File
@@ -21,7 +21,7 @@ use std::collections::HashMap;
use std::sync::Arc;
use serde_json::{Value, json};
use vectorcraft_doc::objects_on_path::{CENTER, ObjectsOnPath, attachable_path, is_objects_on_path, place};
use vectorcraft_doc::objects_on_path::{CENTER, Held, ObjectsOnPath, attachable_path, held, is_objects_on_path, place};
use vectorcraft_doc::{Document, Node, NodeId, NodeKind};
use vectorcraft_geom::Rect;
@@ -168,7 +168,10 @@ fn path_refused(d: &Document, path: NodeId) -> Option<&'static str> {
if group_around(d, path).is_some() {
return Some("the path is already in an Objects on Path group");
}
None
match held(d, path)? {
Held::Live => Some("a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects"),
Held::Clipping => Some("a clipping path can't take objects"),
}
}
/// Why `n` can't be attached to a path, if it can't (the help page names graphs).
@@ -179,6 +182,11 @@ fn object_refused(d: &Document, n: &Node) -> Option<&'static str> {
if group_around(d, n.id).is_some() {
return Some("an object already on a path can't be attached again");
}
match held(d, n.id) {
Some(Held::Live) => return Some("objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path"),
Some(Held::Clipping) => return Some("a clipping path can't be attached to a path"),
None => {}
}
let mut graph = false;
n.walk(&mut |c| graph |= c.extras().graph.is_some());
graph.then_some("graphs can't be attached to a path")
@@ -373,6 +373,50 @@ fn what_cannot_be_attached_is_refused_with_a_reason() {
assert!(s.execute("object.objectsOnPath.options", &json!({"ids": [other.0]})).is_err());
}
#[test]
fn paths_and_objects_that_are_part_of_live_art_or_a_clipping_path_stay_where_they_are() {
let mut s = session();
let ([left, middle, _], path) = squares_and_line(&mut s);
let err = |s: &mut Session, p: Value| s.execute("object.objectsOnPath.attach", &p).unwrap_err().to_string();
let parent = |s: &Session, id: NodeId| s.doc().unwrap().doc.parent_of(id);
// A compound path's member as the path; as an object, the whole compound attaches.
let member = rect(&mut s, 20.0, 150.0, 40.0, 40.0);
let hole = rect(&mut s, 30.0, 160.0, 10.0, 10.0);
select(&mut s, &[member, hole]);
let compound = id_of(&s.execute("object.compoundPath.make", &json!({})).unwrap());
let why = err(&mut s, json!({"path": member.0, "ids": [left.0]}));
assert!(why.contains("a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects"), "{why}");
assert_eq!(parent(&s, member), Some(compound));
// A blend's key path, as the path and as an object.
let key = line(&mut s, (50.0, 200.0), (350.0, 200.0));
let other_key = line(&mut s, (50.0, 250.0), (350.0, 250.0));
select(&mut s, &[key, other_key]);
let blend = id_of(&s.execute("object.blend.make", &json!({"steps": 2})).unwrap());
assert!(err(&mut s, json!({"path": key.0, "ids": [left.0]})).contains("can't take objects"));
let why = err(&mut s, json!({"path": path.0, "ids": [key.0]}));
assert!(why.contains("objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path"), "{why}");
assert_eq!((parent(&s, key), parent(&s, other_key)), (Some(blend), Some(blend)));
// A repeat's source art as an object.
let source = rect(&mut s, 300.0, 340.0, 10.0, 10.0);
select(&mut s, &[source]);
let repeat = id_of(&s.execute("object.repeat.grid", &json!({})).unwrap());
assert!(err(&mut s, json!({"path": path.0, "ids": [source.0]})).contains("can't be attached to a path"));
assert_eq!(parent(&s, source), Some(repeat));
// A clipping path, as the path and as an object.
let art = rect(&mut s, 200.0, 100.0, 60.0, 60.0);
let mask = rect(&mut s, 210.0, 110.0, 40.0, 40.0);
select(&mut s, &[art, mask]);
let clip = id_of(&s.execute("object.clippingMask.make", &json!({})).unwrap());
assert!(err(&mut s, json!({"path": mask.0, "ids": [left.0]})).contains("a clipping path can't take objects"));
assert!(err(&mut s, json!({"path": path.0, "ids": [mask.0]})).contains("a clipping path can't be attached to a path"));
assert_eq!(s.doc().unwrap().doc.node(clip).unwrap().children().unwrap().first().map(|c| c.id), Some(mask));
// The art the clipping path clips, and a compound path's member as an object, still attach.
let g = attach(&mut s, path, &[left, middle, member, art], json!({}));
let rec = s.doc().unwrap().doc.node(g).unwrap().extras().objects_on_path.as_deref().cloned().unwrap();
assert!(rec.members.iter().any(|m| m.id == compound), "the compound attaches whole");
assert_eq!(parent(&s, member), Some(compound));
}
#[test]
fn options_and_expand_take_ids_without_a_selection() {
let mut s = session();
+40 -1
View File
@@ -15,7 +15,9 @@ use crate::{Action, Cursor, Mods, Overlay, PointerEvent, PointerKind, Tool, Tool
const HIGHLIGHT: [u8; 3] = [0x4f, 0x9d, 0xff];
/// The path a click at `p` attaches the selected objects to: the path object hit there, when it can
/// take objects, is in no Objects on Path group, and something else is selected.
/// take objects, is in no Objects on Path group, is not a clipping path or part of a compound path,
/// blend, envelope, repeat or Intertwine group ([`vectorcraft_doc::objects_on_path::held`]), and
/// something else is selected.
pub fn target(cx: &ToolContext, p: Point) -> Option<(NodeId, BezPath)> {
let h = vectorcraft_doc::hit::hit_test(cx.doc, p, cx.hit_options())?;
let n = cx.doc.node(h.leaf)?;
@@ -23,6 +25,9 @@ pub fn target(cx: &ToolContext, p: Point) -> Option<(NodeId, BezPath)> {
if h.ancestry.iter().filter(|a| **a != h.leaf).any(|a| cx.doc.node(*a).is_some_and(is_objects_on_path)) {
return None;
}
if vectorcraft_doc::objects_on_path::held(cx.doc, h.leaf).is_some() {
return None;
}
cx.selection.objects.iter().any(|id| *id != h.leaf).then(|| (h.leaf, path.to_bezpath()))
}
@@ -156,4 +161,38 @@ mod tests {
assert!(t.pointer(&cx, &ev(PointerKind::Up, 200.0, 300.0)).is_empty());
assert!(matches!(d.node(line).map(|n| &n.kind), Some(NodeKind::Path { .. })));
}
#[test]
fn a_clipping_path_or_a_blend_key_is_not_a_target() {
let (mut d, line, square) = doc();
let l = d.layers[0].id;
let key = d.alloc_id();
d.insert(Some(l), 2, Node::path(key, shapes::line(Point::new(0.0, 100.0), Point::new(400.0, 100.0)), Appearance::default_art())).unwrap();
let blend = d.alloc_id();
d.wrap(&[line, key], |children| Node::new(blend, NodeKind::Blend { children, spec: Default::default() })).unwrap();
let mask = d.alloc_id();
let art = d.alloc_id();
d.insert(Some(l), 2, Node::path(mask, shapes::rectangle(Rect::new(100.0, 380.0, 300.0, 430.0)), Appearance::default_art())).unwrap();
d.insert(Some(l), 3, Node::path(art, shapes::rectangle(Rect::new(250.0, 390.0, 290.0, 420.0)), Appearance::default_art())).unwrap();
let clip = d.alloc_id();
d.wrap(&[mask, art], |children| {
let mut g = Node::group(clip, children);
g.set_clips(true);
g
})
.unwrap();
assert_eq!(d.node(clip).and_then(|g| g.children()).and_then(|c| c.first()).map(|c| c.id), Some(mask));
let mut sel = Selection::default();
sel.set([square]);
let paint = paint();
let cx = cx(&d, &sel, &paint);
let mut t = ObjectsOnPathTool::default();
for (p, what) in [((150.0, 400.0), "a clipping path"), ((200.0, 300.0), "a blend's key path"), ((200.0, 100.0), "a blend's other key path")] {
assert_eq!(t.cursor(&cx, Point::new(p.0, p.1), Mods::default()), Cursor::Arrow, "{what}");
t.pointer(&cx, &ev(PointerKind::Move, p.0, p.1));
assert!(t.overlays(&cx).is_empty(), "{what} is not highlighted");
t.pointer(&cx, &ev(PointerKind::Down, p.0, p.1));
assert!(t.pointer(&cx, &ev(PointerKind::Up, p.0, p.1)).is_empty(), "a click on {what} attaches nothing");
}
}
}
+4
View File
@@ -4419,6 +4419,10 @@ imageTrace Outline Obrys
@msg select a repeat vyberte opakování
@msg select an Intertwine group vyberte skupinu propletení
@msg select an Objects on Path group vyberte skupinu objektů na cestě
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects cesta uvnitř složené cesty, prolnutí, obálky, opakování nebo skupiny propletení nemůže přijmout objekty
@msg a clipping path can't take objects ořezová cesta nemůže přijmout objekty
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objekty uvnitř prolnutí, obálky, opakování nebo skupiny propletení nelze připojit na cestu
@msg a clipping path can't be attached to a path ořezovou cestu nelze připojit na cestu
@msg select a stroke with a variable width vyberte tah s proměnnou šířkou
@msg select a symbol instance vyberte instanci symbolu
@msg select an Image Trace object vyberte objekt vektorizace obrazu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4056,6 +4056,10 @@ theme Appearance Erscheinungsbild
@msg select a repeat wählen Sie eine Wiederholung aus
@msg select an Intertwine group wählen Sie eine Verflechtungsgruppe aus
@msg select an Objects on Path group wählen Sie eine Gruppe „Objekte auf Pfad“ aus
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects ein Pfad in einem zusammengesetzten Pfad, einer Angleichung, einer Hülle, einer Wiederholung oder einer Verflechtungsgruppe kann keine Objekte aufnehmen
@msg a clipping path can't take objects ein Schnittpfad kann keine Objekte aufnehmen
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path die Objekte in einer Angleichung, einer Hülle, einer Wiederholung oder einer Verflechtungsgruppe können nicht an einen Pfad angehängt werden
@msg a clipping path can't be attached to a path ein Schnittpfad kann nicht an einen Pfad angehängt werden
@msg select a stroke with a variable width wählen Sie eine Kontur mit variabler Breite aus
@msg select a symbol instance wählen Sie eine Symbolinstanz aus
@msg select an Image Trace object wählen Sie ein Bildnachzeichner-Objekt aus
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -5116,6 +5116,10 @@ effect Points Σημεία
@msg nothing in data set {name} was applied: no object is bound to a variable it has a value for δεν εφαρμόστηκε τίποτα από το σύνολο δεδομένων {name}: κανένα αντικείμενο δεν είναι συνδεδεμένο με μεταβλητή για την οποία έχει τιμή
@msg select an Intertwine group επιλέξτε μια ομάδα διαπλοκής
@msg select an Objects on Path group επιλέξτε μια ομάδα αντικειμένων σε διαδρομή
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects μια διαδρομή μέσα σε σύνθετη διαδρομή, ανάμειξη, περίβλημα, επανάληψη ή ομάδα διαπλοκής δεν μπορεί να δεχτεί αντικείμενα
@msg a clipping path can't take objects μια διαδρομή αποκοπής δεν μπορεί να δεχτεί αντικείμενα
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path τα αντικείμενα μέσα σε ανάμειξη, περίβλημα, επανάληψη ή ομάδα διαπλοκής δεν μπορούν να προσαρτηθούν σε διαδρομή
@msg a clipping path can't be attached to a path μια διαδρομή αποκοπής δεν μπορεί να προσαρτηθεί σε διαδρομή
@msg span must be "object" or "selection", got {v} το span πρέπει να είναι "object" ή "selection", δόθηκε {v}
@msg span: "selection" places a `gradient`, not a swatch span: το "selection" τοποθετεί ένα `gradient`, όχι δείγμα χρώματος
@msg span: "selection" places a gradient: give `gradient` span: το "selection" τοποθετεί ντεγκραντέ: δώστε `gradient`
Can't render this file because it contains an unexpected character in line 2020 and column 19.
+4
View File
@@ -4118,6 +4118,10 @@ axis Both Ambos
@msg select a repeat selecciona una repetición
@msg select an Intertwine group selecciona un grupo entrelazado
@msg select an Objects on Path group selecciona un grupo de objetos en trazado
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects un trazado dentro de un trazado compuesto, una fusión, una envolvente, una repetición o un grupo entrelazado no puede recibir objetos
@msg a clipping path can't take objects un trazado de recorte no puede recibir objetos
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path los objetos dentro de una fusión, una envolvente, una repetición o un grupo entrelazado no se pueden adjuntar a un trazado
@msg a clipping path can't be attached to a path un trazado de recorte no se puede adjuntar a un trazado
@msg select a stroke with a variable width selecciona un trazo con anchura variable
@msg select a symbol instance selecciona una instancia de símbolo
@msg select an Image Trace object selecciona un objeto de calco de imagen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -5128,6 +5128,10 @@ mark-style Japanese Japanilainen
@msg nothing in data set {name} was applied: no object is bound to a variable it has a value for tietojoukosta {name} ei käytetty mitään: mitään objektia ei ole sidottu muuttujaan, jolle siinä on arvo
@msg select an Intertwine group valitse lomitusryhmä
@msg select an Objects on Path group valitse Objektit polulla -ryhmä
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects yhdistelmäpolun, sulautuksen, vääristyskuoren, toiston tai lomitusryhmän sisällä olevaan polkuun ei voi kiinnittää objekteja
@msg a clipping path can't take objects leikkauspolkuun ei voi kiinnittää objekteja
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path sulautuksen, vääristyskuoren, toiston tai lomitusryhmän sisällä olevia objekteja ei voi kiinnittää polulle
@msg a clipping path can't be attached to a path leikkauspolkua ei voi kiinnittää polulle
@msg span must be "object" or "selection", got {v} span-arvon on oltava "object" tai "selection", saatiin {v}
@msg span: "selection" places a `gradient`, not a swatch span: "selection" sijoittaa `gradient`-liukuvärin, ei värimallia
@msg span: "selection" places a gradient: give `gradient` span: "selection" sijoittaa liukuvärin: anna `gradient`
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4115,6 +4115,10 @@ axis Both Les deux
@msg select a repeat sélectionnez une répétition
@msg select an Intertwine group sélectionnez un groupe entrelacé
@msg select an Objects on Path group sélectionnez un groupe d’objets sur tracé
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects un tracé à l’intérieur d’un tracé transparent, d’un dégradé de formes, d’une enveloppe, d’une répétition ou d’un groupe entrelacé ne peut pas recevoir d’objets
@msg a clipping path can't take objects un tracé d’écrêtage ne peut pas recevoir d’objets
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path les objets à l’intérieur d’un dégradé de formes, d’une enveloppe, d’une répétition ou d’un groupe entrelacé ne peuvent pas être attachés à un tracé
@msg a clipping path can't be attached to a path un tracé d’écrêtage ne peut pas être attaché à un tracé
@msg select a stroke with a variable width sélectionnez un contour de largeur variable
@msg select a symbol instance sélectionnez une instance de symbole
@msg select an Image Trace object sélectionnez un objet de vectorisation de l’image
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4807,6 +4807,10 @@ imageTrace Outline Körvonal
@msg select a repeat jelölj ki egy ismétlést
@msg select an Intertwine group jelölj ki egy összefonási csoportot
@msg select an Objects on Path group jelölj ki egy Objektumok útvonalon csoportot
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects összetett útvonalban, összemosásban, burkolóban, ismétlésben vagy összefonási csoportban lévő útvonalhoz nem csatolhatók objektumok
@msg a clipping path can't take objects vágóútvonalhoz nem csatolhatók objektumok
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path összemosásban, burkolóban, ismétlésben vagy összefonási csoportban lévő objektumok nem csatolhatók útvonalhoz
@msg a clipping path can't be attached to a path vágóútvonal nem csatolható útvonalhoz
@msg select a stroke with a variable width jelölj ki egy változó szélességű körvonalat
@msg select a symbol instance jelölj ki egy szimbólumpéldányt
@msg select an envelope jelölj ki egy burkolót
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4157,6 +4157,10 @@ axis Both Entrambi
@msg select a repeat seleziona una ripetizione
@msg select an Intertwine group seleziona un gruppo intrecciato
@msg select an Objects on Path group seleziona un gruppo di oggetti su tracciato
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects un tracciato all'interno di un tracciato composto, una fusione, un involucro, una ripetizione o un gruppo intrecciato non può ricevere oggetti
@msg a clipping path can't take objects un tracciato di ritaglio non può ricevere oggetti
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path gli oggetti all'interno di una fusione, un involucro, una ripetizione o un gruppo intrecciato non possono essere agganciati a un tracciato
@msg a clipping path can't be attached to a path un tracciato di ritaglio non può essere agganciato a un tracciato
@msg select a stroke with a variable width seleziona una traccia con larghezza variabile
@msg select a symbol instance seleziona un'istanza di simbolo
@msg select an Image Trace object seleziona un oggetto di ricalco immagine
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4039,6 +4039,10 @@ swatch Bright Violet ビビッドバイオレット
@msg select a repeat リピートを選択してください
@msg select an Intertwine group 織り交ぜグループを選択してください
@msg select an Objects on Path group パス上のオブジェクトグループを選択してください
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 複合パス、ブレンド、エンベロープ、リピートまたは織り交ぜグループ内のパスにはオブジェクトをアタッチできません
@msg a clipping path can't take objects クリッピングパスにはオブジェクトをアタッチできません
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path ブレンド、エンベロープ、リピートまたは織り交ぜグループ内のオブジェクトはパスにアタッチできません
@msg a clipping path can't be attached to a path クリッピングパスはパスにアタッチできません
@msg select the art to repeat リピートするアートを選択してください
@msg the document has no patterns ドキュメントにパターンがありません
@msg no artboard アートボードがありません
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4837,6 +4837,10 @@ imageTrace Outline კონტური
Arrange Intertwine Area გადახლართვის არის დალაგება
@msg select an Intertwine group მონიშნეთ გადახლართვის ჯგუფი
@msg select an Objects on Path group მონიშნეთ ტრაექტორიაზე ობიექტების ჯგუფი
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects შედგენილ ტრაექტორიაში, გადასვლაში, გარსში, გამეორებაში ან გადახლართვის ჯგუფში მყოფ ტრაექტორიაზე ობიექტების მიმაგრება ვერ ხერხდება
@msg a clipping path can't take objects მომჭრელ ტრაექტორიაზე ობიექტების მიმაგრება ვერ ხერხდება
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path გადასვლაში, გარსში, გამეორებაში ან გადახლართვის ჯგუფში მყოფი ობიექტების ტრაექტორიაზე მიმაგრება ვერ ხერხდება
@msg a clipping path can't be attached to a path მომჭრელი ტრაექტორიის ტრაექტორიაზე მიმაგრება ვერ ხერხდება
Registration: საბაზისო წერტილი:
@msg span must be "object" or "selection", got {v} span უნდა იყოს "object" ან "selection", მიღებულია {v}
@msg span: "selection" places a `gradient`, not a swatch span: "selection" ათავსებს `gradient`-ს და არა ფერის ნიმუშს
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -3971,6 +3971,10 @@ theme Appearance 외관
@msg select a repeat 반복을 선택하세요
@msg select an Intertwine group 교차 그룹을 선택하세요
@msg select an Objects on Path group 패스 위 개체 그룹을 선택하세요
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 컴파운드 패스, 블렌드, 엔벨로프, 반복 또는 교차 그룹 안의 패스에는 개체를 부착할 수 없습니다
@msg a clipping path can't take objects 클리핑 패스에는 개체를 부착할 수 없습니다
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path 블렌드, 엔벨로프, 반복 또는 교차 그룹 안의 개체는 패스에 부착할 수 없습니다
@msg a clipping path can't be attached to a path 클리핑 패스는 패스에 부착할 수 없습니다
@msg select the art to repeat 반복할 아트웍을 선택하세요
@msg the document has no patterns 문서에 패턴이 없습니다
@msg no artboard 아트보드가 없습니다
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -4243,6 +4243,10 @@ imageTrace Outline Kontur
@msg select a repeat zaznacz powtórzenie
@msg select an Intertwine group zaznacz grupę przeplotu
@msg select an Objects on Path group zaznacz grupę obiektów na ścieżce
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects do ścieżki wewnątrz ścieżki złożonej, przejścia, koperty, powtórzenia lub grupy przeplotu nie można dołączyć obiektów
@msg a clipping path can't take objects do ścieżki przycinającej nie można dołączyć obiektów
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path obiektów wewnątrz przejścia, koperty, powtórzenia lub grupy przeplotu nie można dołączyć do ścieżki
@msg a clipping path can't be attached to a path ścieżki przycinającej nie można dołączyć do ścieżki
@msg select a stroke with a variable width zaznacz obrys o zmiennej szerokości
@msg select a symbol instance zaznacz wystąpienie symbolu
@msg select an Image Trace object zaznacz obiekt obrysu obrazu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -3698,6 +3698,10 @@ axis Both Ambos
@msg select a repeat selecione uma repetição
@msg select an Intertwine group selecione um grupo entrelaçado
@msg select an Objects on Path group selecione um grupo de objetos no caminho
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects um caminho dentro de um caminho composto, mesclagem, envelope, repetição ou grupo entrelaçado não pode receber objetos
@msg a clipping path can't take objects um caminho de recorte não pode receber objetos
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objetos dentro de uma mesclagem, envelope, repetição ou grupo entrelaçado não podem ser anexados a um caminho
@msg a clipping path can't be attached to a path um caminho de recorte não pode ser anexado a um caminho
@msg select a stroke with a variable width selecione um traço com largura variável
@msg select a symbol instance selecione uma instância de símbolo
@msg select an Image Trace object selecione um objeto de Vetorização de imagem
Can't render this file because it contains an unexpected character in line 6 and column 47.
+4
View File
@@ -4153,6 +4153,10 @@ axis Both Оба
@msg select a repeat выделите повтор
@msg select an Intertwine group выделите группу переплетения
@msg select an Objects on Path group выделите группу объектов на контуре
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects к контуру внутри составного контура, перехода, оболочки, повтора или группы переплетения нельзя прикрепить объекты
@msg a clipping path can't take objects к контуру обрезки нельзя прикрепить объекты
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path объекты внутри перехода, оболочки, повтора или группы переплетения нельзя прикрепить к контуру
@msg a clipping path can't be attached to a path контур обрезки нельзя прикрепить к контуру
@msg select a stroke with a variable width выделите обводку с переменной шириной
@msg select a symbol instance выделите экземпляр символа
@msg select an Image Trace object выделите объект трассировки изображения
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -5120,6 +5120,10 @@ theme Appearance Utseende
@msg nothing in data set {name} was applied: no object is bound to a variable it has a value for inget i datauppsättningen {name} användes: inget objekt är bundet till en variabel som den har ett värde för
@msg select an Intertwine group markera en sammanflätningsgrupp
@msg select an Objects on Path group markera en grupp med objekt på bana
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects en bana inuti en sammansatt bana, en blandning, ett kuvert, en upprepning eller en sammanflätningsgrupp kan inte ta emot objekt
@msg a clipping path can't take objects en klippbana kan inte ta emot objekt
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objekt inuti en blandning, ett kuvert, en upprepning eller en sammanflätningsgrupp kan inte fästas på en bana
@msg a clipping path can't be attached to a path en klippbana kan inte fästas på en bana
@msg span must be "object" or "selection", got {v} span måste vara "object" eller "selection", fick {v}
@msg span: "selection" places a `gradient`, not a swatch span: "selection" placerar en `gradient`, inte en färgruta
@msg span: "selection" places a gradient: give `gradient` span: "selection" placerar en övertoning: ange `gradient`
Can't render this file because it contains an unexpected character in line 5 and column 25.
+33
View File
@@ -1733,6 +1733,39 @@ fn blend_spine_param_errors_are_translated() {
assert!(untranslated.is_empty(), "untranslated spine errors:\n{}", untranslated.join("\n"));
}
/// Objects on Path's refusals of a path inside a compound path, blend, envelope, repeat or
/// Intertwine group, of an object inside a blend, envelope, repeat or Intertwine group, and of a
/// clipping path, whose text the scan above doesn't read, are translated whole in each language of
/// [`COMPLETE_MESSAGES`].
#[test]
fn objects_on_path_refusals_are_translated() {
use serde_json::json;
use vectorcraft_engine::Session;
let mut s = Session::new();
s.execute("file.new", &json!({})).unwrap();
let rectangle =
|s: &mut Session, x: u64| s.execute("shape.rectangle", &json!({"x": x, "y": 0, "width": 40, "height": 40})).unwrap()["id"].clone();
let path = s.execute("shape.line", &json!({"x1": 0, "y1": 300, "x2": 300, "y2": 300})).unwrap()["id"].clone();
let object = rectangle(&mut s, 0);
let (member, hole) = (rectangle(&mut s, 100), rectangle(&mut s, 110));
s.execute("select.set", &json!({"ids": [member, hole]})).unwrap();
s.execute("object.compoundPath.make", &json!({})).unwrap();
let (art, mask) = (rectangle(&mut s, 200), rectangle(&mut s, 210));
s.execute("select.set", &json!({"ids": [art, mask]})).unwrap();
s.execute("object.clippingMask.make", &json!({})).unwrap();
let source = rectangle(&mut s, 300);
s.execute("select.set", &json!({"ids": [source]})).unwrap();
s.execute("object.repeat.grid", &json!({})).unwrap();
for (p, ids) in [(&member, &object), (&mask, &object), (&path, &source), (&path, &mask)] {
let e = s.execute("object.objectsOnPath.attach", &json!({"path": p, "ids": [ids]})).unwrap_err();
let vectorcraft_engine::EngineError::BadParams { msg, .. } = &e else { panic!("{e}") };
for code in COMPLETE_MESSAGES {
let shown = message(Lang::from_code(code).unwrap(), &e.to_string());
assert!(!shown.contains(msg.as_str()), "{code}: {shown}");
}
}
}
/// The parameter error of Save as Template for a `.ait` with `aiVersion` 7 is translated whole in
/// each language of [`COMPLETE_MESSAGES`].
#[test]
+4
View File
@@ -4141,6 +4141,10 @@ axis Both Обидві
@msg select a repeat виділіть повтор
@msg select an Intertwine group виділіть групу переплетення
@msg select an Objects on Path group виділіть групу об’єктів на контурі
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects до контуру всередині складеного контуру, переходу, оболонки, повтору або групи переплетення не можна прикріпити об’єкти
@msg a clipping path can't take objects до відсічного контуру не можна прикріпити об’єкти
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path об’єкти всередині переходу, оболонки, повтору або групи переплетення не можна прикріпити до контуру
@msg a clipping path can't be attached to a path відсічний контур не можна прикріпити до контуру
@msg select a stroke with a variable width виділіть обведення зі змінною шириною
@msg select a symbol instance виділіть екземпляр символу
@msg select an Image Trace object виділіть об’єкт трасування зображення
Can't render this file because it contains an unexpected character in line 725 and column 40.
+4
View File
@@ -4457,6 +4457,10 @@ theme Appearance Giao diện
@msg select a repeat hãy chọn một đối tượng lặp
@msg select an Intertwine group hãy chọn một nhóm đan xen
@msg select an Objects on Path group hãy chọn một nhóm đối tượng trên đường dẫn
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects không thể gắn đối tượng lên một đường dẫn nằm trong đường dẫn phức, đối tượng hòa trộn, Envelope, đối tượng lặp hoặc nhóm đan xen
@msg a clipping path can't take objects không thể gắn đối tượng lên đường dẫn cắt
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path không thể gắn các đối tượng nằm trong đối tượng hòa trộn, Envelope, đối tượng lặp hoặc nhóm đan xen lên đường dẫn
@msg a clipping path can't be attached to a path không thể gắn đường dẫn cắt lên đường dẫn
@msg select a stroke with a variable width hãy chọn nét có chiều rộng biến đổi
@msg select a symbol instance hãy chọn đối tượng ký hiệu
@msg select an envelope hãy chọn một Envelope
Can't render this file because it contains an unexpected character in line 3967 and column 10.
+4
View File
@@ -3791,6 +3791,10 @@ imageTrace Outline 轮廓
@msg select a repeat 请选择一个重复对象
@msg select an Intertwine group 请选择一个交织组
@msg select an Objects on Path group 请选择一个路径上的对象组
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 复合路径、混合对象、封套、重复对象或交织组中的路径无法附加对象
@msg a clipping path can't take objects 剪切路径无法附加对象
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path 混合对象、封套、重复对象或交织组中的对象无法附加到路径
@msg a clipping path can't be attached to a path 剪切路径无法附加到路径
@msg select the art to repeat 请选择要重复的图稿
@msg the document has no patterns 文档中没有图案
@msg no artboard 没有画板
Can't render this file because it contains an unexpected character in line 2 and column 73.
+4
View File
@@ -1794,6 +1794,10 @@ file-filter Templates 範本
@msg select a repeat 請選取重複物件
@msg select an Intertwine group 請選取交織群組
@msg select an Objects on Path group 請選取路徑上的物件群組
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects 複合路徑、漸變物件、封套、重複物件或交織群組中的路徑無法附加物件
@msg a clipping path can't take objects 剪裁路徑無法附加物件
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path 漸變物件、封套、重複物件或交織群組中的物件無法附加到路徑
@msg a clipping path can't be attached to a path 剪裁路徑無法附加到路徑
@msg select the art to repeat 請選取要重複的圖稿
@msg the document has no patterns 文件中沒有圖樣
@msg no artboard 沒有工作區域
Can't render this file because it contains an unexpected character in line 6 and column 47.
+6 -2
View File
@@ -4409,8 +4409,12 @@ between them by length; on a closed path the gaps run all the way round. The att
object is turned to the path's direction there. An object rotated by other than a multiple of 90° is first turned to
the nearest multiple. `rotate` tilts every object by that many degrees counter-clockwise. Without `path`, the command
chooses the Objects on Path tool (`objectsOnPath`), whose click on a path sends `{path}`. As the path, the command
refuses a guide, a compound path, type, a path without length and a path already in an Objects on Path group. As
objects, it refuses graphs, layers and objects already in an Objects on Path group.
refuses a guide, a compound path, type, a path without length, a path already in an Objects on Path group, a
clipping path, and a path inside a compound path, blend, envelope, repeat or Intertwine group. As objects, it skips
layers and refuses graphs, objects already in an Objects on Path group, clipping paths, and objects inside a blend,
envelope, repeat or Intertwine group; a member of a compound path attaches as its whole compound path. The tool
does not highlight a clipping path or a path inside a blend, envelope, repeat or Intertwine group, and a click on one
attaches nothing.
The group stays live: after every edit its objects go back on its path. Editing the path moves them, an object moved
on its own goes back to its place, an object moved into the group (`layer.move` with `place: "inside"`) joins the end