mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 10:01:58 +00:00
Document Info: strokes and fills at opacity 0 list no brush or paint
A stroke at an opacity of 0 draws nothing, so its brush is no longer listed in the Brushes category, brushNames or brushes. Pattern Objects, Gradient Objects and Spot Color Objects likewise leave out fills and strokes at an opacity of 0, and Objects no longer counts objects whose only such paint is at opacity 0.
This commit is contained in:
@@ -18,7 +18,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Document Info",
|
||||
["Window", "Document Info"],
|
||||
None,
|
||||
"{selectionOnly?, category?: document|objects|graphicStyles|brushes|spotColors|patterns|gradients|symbols|fonts|fontDetails|linkedImages|embeddedImages|repeats (only that one in sections and the text), format?: \"text\" (→ {text}: the report Document Info › Save… and Package write)} → {document, objects: {paths, compoundPaths, groups, …}, pathLength: pt (the paths' total length, compound paths' included, guides left out), fonts, images, swatches, graphicStyleNames (with selectionOnly: the styles the selected objects are linked to), brushNames (the brushes the art's drawn strokes use, each once; with selectionOnly: those the selected objects' strokes use), brushes: [{name, type: calligraphic|scatter|art|pattern|bristle|null}] (those brushes with their types; null: not in the Brushes panel), panelBrushNames (the Brushes panel's brushes), repeatObjects: [{id, name, type: radial|grid|mirror, instances, rows?, cols?}] (the Repeat objects, those in groups and other repeats included; with selectionOnly: those in the selection), spotObjects: [{id, name, spotColors}] (the objects filled or stroked with a spot color swatch, as a solid color or in the stops of a gradient with a stop above opacity 0, at a tint above 0, and grayscale images colorized with one, each once, by the rules patternObjects follows, with the spot colors they use; Registration and process colors are not spot colors; objects.spots counts them), spotColorNames and spotColors (the spot colors those objects use), patternObjects: [{id, name, patterns}] (the objects filled or stroked with a pattern, each once, those in groups and type whose drawn characters use one included, hidden fills and strokes, strokes with no width, guides, compound path members' own fills and strokes, images' fills and strokes without a shape and characters that draw nothing left out, with the patterns they use, which objects.patterns counts; with selectionOnly: those in the selection), patternNames (the patterns those objects use), gradientObjects: [{id, name, gradients}] (the objects filled or stroked with a gradient, by the same rules, with the gradients they use: a linked gradient swatch's name, else Linear gradient, Radial gradient or Freeform gradient; objects.gradients counts them), gradientNames (the gradients those objects use), …, sections: [{id, title, rows: [[label, value]]}] (the panel's categories; fontDetails: each font's file and whether its license lets it be embedded)}. An image linked to a file outside the automation read roots has link null, and its Linked Images row names the file alone",
|
||||
"{selectionOnly?, category?: document|objects|graphicStyles|brushes|spotColors|patterns|gradients|symbols|fonts|fontDetails|linkedImages|embeddedImages|repeats (only that one in sections and the text), format?: \"text\" (→ {text}: the report Document Info › Save… and Package write)} → {document, objects: {paths, compoundPaths, groups, …}, pathLength: pt (the paths' total length, compound paths' included, guides left out), fonts, images, swatches, graphicStyleNames (with selectionOnly: the styles the selected objects are linked to), brushNames (the brushes the art's drawn strokes use, each once; with selectionOnly: those the selected objects' strokes use), brushes: [{name, type: calligraphic|scatter|art|pattern|bristle|null}] (those brushes with their types; null: not in the Brushes panel), panelBrushNames (the Brushes panel's brushes), repeatObjects: [{id, name, type: radial|grid|mirror, instances, rows?, cols?}] (the Repeat objects, those in groups and other repeats included; with selectionOnly: those in the selection), spotObjects: [{id, name, spotColors}] (the objects filled or stroked with a spot color swatch, as a solid color or in the stops of a gradient with a stop above opacity 0, at a tint above 0, and grayscale images colorized with one, each once, by the rules patternObjects follows, with the spot colors they use; Registration and process colors are not spot colors; objects.spots counts them), spotColorNames and spotColors (the spot colors those objects use), patternObjects: [{id, name, patterns}] (the objects filled or stroked with a pattern, each once, those in groups and type whose drawn characters use one included, hidden fills and strokes, fills and strokes at an opacity of 0, strokes with no width, guides, compound path members' own fills and strokes, images' fills and strokes without a shape and characters that draw nothing left out, with the patterns they use, which objects.patterns counts; with selectionOnly: those in the selection), patternNames (the patterns those objects use), gradientObjects: [{id, name, gradients}] (the objects filled or stroked with a gradient, by the same rules, with the gradients they use: a linked gradient swatch's name, else Linear gradient, Radial gradient or Freeform gradient; objects.gradients counts them), gradientNames (the gradients those objects use), …, sections: [{id, title, rows: [[label, value]]}] (the panel's categories; fontDetails: each font's file and whether its license lets it be embedded)}. An image linked to a file outside the automation read roots has link null, and its Linked Images row names the file alone",
|
||||
has_doc,
|
||||
info
|
||||
),
|
||||
@@ -348,7 +348,8 @@ type PaintNames<'a> = dyn Fn(&Paint) -> Vec<String> + 'a;
|
||||
|
||||
/// The spot colors, patterns or gradients (`label`: [`spot_labels`], [`pattern_label`] or
|
||||
/// [`gradient_label`], each paint's names) that `n`'s own fills and strokes paint, each once. A
|
||||
/// hidden fill or stroke and a stroke with no width paint nothing, and neither does any fill or
|
||||
/// hidden fill or stroke, a fill or stroke at an opacity of 0 and a stroke with no width paint
|
||||
/// nothing, and neither does any fill or
|
||||
/// stroke of a guide (drawn in the guide color), of a compound path's member (`members`: the
|
||||
/// compound path's own fills and strokes paint it) or of type whose layout draws nothing
|
||||
/// (`painted_runs`). An image's fills and strokes paint only where an effect gives them a shape.
|
||||
@@ -372,7 +373,7 @@ fn own_paints(
|
||||
.then(|| vectorcraft_render::effects::image_paint(Some(d), n).into_iter().flat_map(|(_, _, item)| label(item.paint())).collect());
|
||||
let mut out: Vec<String> = vec![];
|
||||
for item in &n.appearance.items {
|
||||
if !item.visible() || matches!(item, vectorcraft_doc::AppearanceItem::Stroke(s) if s.width <= 0.0) {
|
||||
if !item.visible() || item.opacity() <= 0.0 || matches!(item, vectorcraft_doc::AppearanceItem::Stroke(s) if s.width <= 0.0) {
|
||||
continue;
|
||||
}
|
||||
for name in label(item.paint()) {
|
||||
@@ -390,7 +391,7 @@ fn one_label(label: fn(&Paint) -> Option<String>) -> impl Fn(&Paint) -> Vec<Stri
|
||||
}
|
||||
|
||||
/// The brushes `n`'s own strokes draw with, in the order of its appearance. A hidden stroke, a
|
||||
/// stroke with no paint and a stroke with no width draw nothing, and neither does any stroke of a
|
||||
/// stroke at an opacity of 0, a stroke with no paint and a stroke with no width draw nothing, and neither does any stroke of a
|
||||
/// guide (drawn in the guide color) or of a compound path's member (`members`: the compound path's
|
||||
/// own strokes draw it). An image's strokes draw only where an effect gives them a shape, and only
|
||||
/// paths, compound paths, type and images draw strokes of their own.
|
||||
@@ -399,7 +400,7 @@ fn applied_brushes(d: &Document, n: &Node, members: &HashSet<*const Node>) -> Ve
|
||||
return vec![];
|
||||
}
|
||||
let brush = |item: &vectorcraft_doc::AppearanceItem| match item {
|
||||
vectorcraft_doc::AppearanceItem::Stroke(st) if item.visible() && !st.paint.is_none() && st.width > 0.0 => {
|
||||
vectorcraft_doc::AppearanceItem::Stroke(st) if item.visible() && st.opacity > 0.0 && !st.paint.is_none() && st.width > 0.0 => {
|
||||
st.brush.clone().filter(|b| !b.is_empty())
|
||||
}
|
||||
_ => None,
|
||||
@@ -827,8 +828,8 @@ mod tests {
|
||||
assert_eq!(selected(&mut s)["brushNames"], json!([]));
|
||||
}
|
||||
|
||||
/// Document Info › Brushes leaves out brushes on strokes that draw nothing (hidden, with no
|
||||
/// width or paint, a guide's, a compound path member's, a path's with no segment, type's that
|
||||
/// Document Info › Brushes leaves out brushes on strokes that draw nothing (hidden, at an
|
||||
/// opacity of 0, with no width or paint, a guide's, a compound path member's, a path's with no segment, type's that
|
||||
/// draws no characters, a group's own), lists a brush the Brushes panel does
|
||||
/// not hold with no type, and gives a name two panel brushes share the type the renderer uses.
|
||||
#[test]
|
||||
@@ -839,8 +840,8 @@ mod tests {
|
||||
s.execute("shape.rectangle", &json!({"x": x, "y": 0, "width": 10, "height": 10})).unwrap()["id"].as_u64().unwrap()
|
||||
};
|
||||
let (hidden, thin, guide, missing) = (square(&mut s, 0.0), square(&mut s, 20.0), square(&mut s, 40.0), square(&mut s, 60.0));
|
||||
let empty = square(&mut s, 80.0);
|
||||
s.execute("brush.apply", &json!({"ids": [hidden, thin, guide, missing, empty], "name": "Charcoal"})).unwrap();
|
||||
let (empty, faint) = (square(&mut s, 80.0), square(&mut s, 200.0));
|
||||
s.execute("brush.apply", &json!({"ids": [hidden, thin, guide, missing, empty, faint], "name": "Charcoal"})).unwrap();
|
||||
let (p, q) = (square(&mut s, 100.0), square(&mut s, 120.0));
|
||||
s.execute("select.set", &json!({"ids": [p, q]})).unwrap();
|
||||
let compound = s.execute("object.compoundPath.make", &json!({})).unwrap()["id"].as_u64().unwrap();
|
||||
@@ -852,6 +853,8 @@ mod tests {
|
||||
member.stroke_mut().unwrap().brush = Some("Dots".into());
|
||||
d.node_mut(NodeId(hidden)).unwrap().appearance.stroke_mut().unwrap().visible = false;
|
||||
d.node_mut(NodeId(thin)).unwrap().appearance.stroke_mut().unwrap().width = 0.0;
|
||||
// A stroke at an opacity of 0 draws nothing.
|
||||
d.node_mut(NodeId(faint)).unwrap().appearance.stroke_mut().unwrap().opacity = 0.0;
|
||||
if let NodeKind::Path { guide: g, .. } = &mut d.node_mut(NodeId(guide)).unwrap().kind {
|
||||
*g = true;
|
||||
}
|
||||
@@ -1009,6 +1012,11 @@ mod tests {
|
||||
s.execute("paint.setFill", &json!({"ids": [e], "none": true})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [e], "swatch": "Dots"})).unwrap();
|
||||
s.execute("appearance.setItem", &json!({"ids": [e], "index": 1, "weight": 0})).unwrap();
|
||||
// Nor does a pattern fill at an opacity of 0.
|
||||
let clear = square(&mut s, 220.0);
|
||||
s.execute("paint.setStroke", &json!({"ids": [clear], "none": true})).unwrap();
|
||||
s.execute("paint.setFill", &json!({"ids": [clear], "swatch": "Dots"})).unwrap();
|
||||
s.execute("appearance.setItem", &json!({"ids": [clear], "index": 0, "opacity": 0})).unwrap();
|
||||
// A type object with no characters paints nothing either.
|
||||
let empty = s.execute("text.create", &json!({"x": 0, "y": 300, "text": ""})).unwrap()["id"].clone();
|
||||
s.execute("paint.setFill", &json!({"ids": [empty], "swatch": "Dots"})).unwrap();
|
||||
@@ -1069,7 +1077,7 @@ mod tests {
|
||||
assert_eq!(i["patternNames"], json!(["Dots"]));
|
||||
// Objects counts the objects that Pattern Objects lists.
|
||||
assert_eq!(i["objects"]["patterns"].as_u64(), Some(5), "{}", i["objects"]);
|
||||
s.execute("select.set", &json!({"ids": [d, e, empty, blank, guide, compound, image.0]})).unwrap();
|
||||
s.execute("select.set", &json!({"ids": [d, e, clear, empty, blank, guide, compound, image.0]})).unwrap();
|
||||
let i = s.execute("document.info", &json!({"selectionOnly": true})).unwrap();
|
||||
assert!(i["objects"]["patterns"].is_null() && i["patternObjects"] == json!([]), "{}", i["objects"]);
|
||||
let i = s.execute("document.info", &json!({"category": "patterns"})).unwrap();
|
||||
|
||||
+2
-2
@@ -6374,7 +6374,7 @@ result carries the same files as a zip (`{name: "<name>.zip", dataBase64}`, entr
|
||||
|
||||
`document.info {selectionOnly?, category?, format?: "text"}` adds `sections` (`[{id, title, rows: [[label, value]]}]`:
|
||||
document, objects, graphicStyles, brushes, spotColors, patterns, gradients, symbols, fonts, fontDetails, linkedImages,
|
||||
embeddedImages, repeats), `brushNames` (the brushes the art's strokes use, each once, hidden strokes, strokes with no
|
||||
embeddedImages, repeats), `brushNames` (the brushes the art's strokes use, each once, hidden strokes, strokes at an opacity of 0, strokes with no
|
||||
paint or width, guides, paths with no segment, type that draws no characters, a group's or layer's own strokes, a compound path member's own strokes and an image's strokes without a
|
||||
shape left out; with `selectionOnly`, the brushes the selected
|
||||
objects' strokes use), `brushes` (`[{name, type}]`: those brushes with their types, `calligraphic`, `scatter`, `art`,
|
||||
@@ -6383,7 +6383,7 @@ name with its type, such as `Art brush`, or `missing from the Brushes panel`), `
|
||||
groups and in other repeats included, with its type `radial`, `grid` or `mirror` and the number of instances it makes,
|
||||
and a grid's `rows` and `cols`; with `selectionOnly`, the Repeat objects in the selection), `patternObjects`
|
||||
(`[{id, name, patterns}]`: every object filled or stroked with a pattern, once each, those in groups and type objects
|
||||
whose drawn characters use a pattern included, hidden fills and strokes, strokes with no width, guides, a compound path
|
||||
whose drawn characters use a pattern included, hidden fills and strokes, fills and strokes at an opacity of 0, strokes with no width, guides, a compound path
|
||||
member's own fills and strokes, an image's fills and strokes that no Convert to Shape or Outline Object effect gives a
|
||||
shape, and characters that draw nothing (spaces and line breaks without an underline or strikethrough) left out, with
|
||||
the patterns it uses, which the patterns category lists as Pattern Objects and `objects.patterns` counts; with `selectionOnly`, those in the selection),
|
||||
|
||||
@@ -1379,9 +1379,9 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
Bristle Brush Options and `brush.new` take a bristle brush name of at most 31 characters, as the Brushes page states for the Bristle Brush Options. The Name field stops taking characters at 31, and `brush.new` and `brush.options` refuse a longer new name with an error that names the limit. The page does not say how the limit counts characters or what happens to longer names already saved; counting characters and the number added to a taken name, keeping longer saved names, and leaving `brush.duplicate` unlimited are VectorCraft's own rules. A bristle brush that a document or a saved file already holds under a longer name keeps it, and the other brush types take a name of any length. Test: `bristle_brush_names_have_at_most_31_characters` in `tests/brushsym.rs`. Public reference: [Brushes](https://web.archive.org/web/20241230205225/https://helpx.adobe.com/illustrator/using/brushes.html) (archived copy).
|
||||
In the Brushes panel, Shift-click selects a range of brushes and Ctrl/Cmd-click adds or removes one. Delete Brush and Duplicate Brush then act on all of them (`brush.delete {names}`, `brush.duplicate {names}`).
|
||||
The Brushes panel's Delete Brush button and panel menu item ask "Delete the selected brushes?" with Yes and No when none of the brushes is in use. Alt-click (Option-click on macOS) on the button deletes them without asking, as the [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for panel deletion outside the Layers panel (archived copy). When a stroke uses one of the brushes, the button, Alt-click and the menu item all ask with Remove Strokes and Cancel; Remove Strokes deletes the brushes and the strokes that used them become plain strokes. Tests: `panels::brushes::tests`, `dialogs::brush_delete::tests`.
|
||||
Document Info has a Brushes category after Graphic Styles. It lists the names and types of the brushes applied to the artwork, as the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes, or with Selection Only the brushes that the selected objects' strokes use. The Document Info report and Package's report list them too (`document.info {category: "brushes"}`, `brushNames`, `brushes`). Listing each brush once, leaving out the Brushes panel's brushes no art uses (`panelBrushNames` lists the panel's brushes), hidden strokes, strokes with no paint or width, guides, paths with no segment, type that draws no characters, a group's or layer's own strokes, a compound path member's own strokes and an image's strokes without a shape, and listing a brush the panel does not hold as missing, are VectorCraft's own rules. Tests: `cmd::docinfo::tests::info_lists_the_brushes` and `info_brushes_skip_undrawn_strokes_and_name_missing_brushes` (vectorcraft-engine).
|
||||
Document Info has a Brushes category after Graphic Styles. It lists the names and types of the brushes applied to the artwork, as the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes, or with Selection Only the brushes that the selected objects' strokes use. The Document Info report and Package's report list them too (`document.info {category: "brushes"}`, `brushNames`, `brushes`). Listing each brush once, leaving out the Brushes panel's brushes no art uses (`panelBrushNames` lists the panel's brushes), hidden strokes, strokes at an opacity of 0, strokes with no paint or width, guides, paths with no segment, type that draws no characters, a group's or layer's own strokes, a compound path member's own strokes and an image's strokes without a shape, and listing a brush the panel does not hold as missing, are VectorCraft's own rules. Tests: `cmd::docinfo::tests::info_lists_the_brushes` and `info_brushes_skip_undrawn_strokes_and_name_missing_brushes` (vectorcraft-engine).
|
||||
Document Info has a Repeat Objects category after Embedded Images. It lists each radial, grid and mirror Repeat object by name with its kind and the number of instances it makes. For a grid it gives the rows and columns instead, followed by the number of instances it draws when that is fewer. With Selection Only it lists the Repeat objects in the selection. The Document Info report and Package's report list them too (`document.info {category: "repeats"}`, `repeatObjects`).
|
||||
Document Info's Pattern Objects category lists the objects whose fill or stroke is a pattern, the category the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes, each by name with the patterns it uses. With Selection Only it lists those in the selection, and the Document Info report and Package's report list them too (`document.info {category: "patterns"}`, `patternObjects`). Listing an object with a pattern fill and a pattern stroke once, listing objects inside groups and type objects whose characters use a pattern, and leaving out hidden fills and strokes, strokes with no width, guides, a compound path member's own fills and strokes, an image's fills and strokes without a shape, characters the type does not draw and patterns no art uses, and counting the listed objects in Objects, are VectorCraft's own rules. Test: `cmd::docinfo::tests::info_lists_the_pattern_objects` (vectorcraft-engine).
|
||||
Document Info's Pattern Objects category lists the objects whose fill or stroke is a pattern, the category the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes, each by name with the patterns it uses. With Selection Only it lists those in the selection, and the Document Info report and Package's report list them too (`document.info {category: "patterns"}`, `patternObjects`). Listing an object with a pattern fill and a pattern stroke once, listing objects inside groups and type objects whose characters use a pattern, and leaving out hidden fills and strokes, fills and strokes at an opacity of 0, strokes with no width, guides, a compound path member's own fills and strokes, an image's fills and strokes without a shape, characters the type does not draw and patterns no art uses, and counting the listed objects in Objects, are VectorCraft's own rules. Test: `cmd::docinfo::tests::info_lists_the_pattern_objects` (vectorcraft-engine).
|
||||
Document Info's Gradient Objects category lists the objects whose fill or stroke is a gradient, the category the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes as the count of objects with gradient fills or strokes. Each object is listed by name with the gradients it uses. With Selection Only it lists those in the selection, and the Document Info report and Package's report list them too (`document.info {category: "gradients"}`, `gradientObjects`). Naming a linked gradient by its swatch and any other gradient by its kind, and leaving out paint that draws nothing by the rules Pattern Objects follows, gradient swatches no art uses, gradient meshes and gradients drawn by effects, are VectorCraft's own rules. Objects counts the listed objects as Gradient Objects. Test: `cmd::docinfo::tests::info_lists_the_gradient_objects` (vectorcraft-engine).
|
||||
Document Info's Spot Color Objects category lists the objects that use spot colors, the category the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes as objects using spot color separations. Each object is listed by name with the spot colors it uses. With Selection Only it lists those in the selection, and the Document Info report and Package's report list them too (`document.info {category: "spotColors"}`, `spotObjects`). Taking a solid color or a gradient stop linked to a spot swatch at a tint above 0 and a grayscale image colorized with one, leaving out process colors that look the same, Registration, gradients whose stops are all at an opacity of 0, paint that draws nothing by the rules Pattern Objects follows, spot swatches no art uses and spot colors inside patterns, symbols, opacity masks, effects and placed files, are VectorCraft's own rules. Objects counts the listed objects as Spot Color Objects. Tests: `cmd::docinfo::tests::info_lists_the_spot_color_objects` and `spot_color_objects_take_colorized_images_and_skip_clear_gradients` (vectorcraft-engine).
|
||||
Document Info's Save… writes the category the panel shows, with Selection Only applied, as the [Document Info panel](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/document-info-panel.html) page describes ("Exports the selected category's visible information to a text file"). With All Categories shown it writes every category, which is VectorCraft's own rule (`docInfo.save {category}`). Test: `panels::doc_info::tests::save_writes_the_category_the_panel_shows`.
|
||||
|
||||
Reference in New Issue
Block a user