mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 02:19:56 -06:00
Merge pull request #5776 from Hamza0101/feat/paint-fill-to-stroke
Color Effects: Apply Fill to Stroke and Apply Stroke to Fill (#5530)
This commit is contained in:
@@ -3,9 +3,10 @@
|
||||
//! Filter writes any colour adjustment into the colours themselves, Select by Color Kind selects the
|
||||
//! objects that use spot colours, carry a live colour adjustment, or are images of a colour model,
|
||||
//! Print Ink Fixes ([`print_fixes`]) prepares a CMYK document's inks for print, Find Nearest
|
||||
//! Swatch ([`nearest`]) matches colours to a swatch library's, and Create Swatch Legend
|
||||
//! ([`legend`]) draws labelled chips of the document's swatches. Its panel and its submenu, Object ›
|
||||
//! Plug-ins › Color Effects, are the UI's.
|
||||
//! Swatch ([`nearest`]) matches colours to a swatch library's, Create Swatch Legend
|
||||
//! ([`legend`]) draws labelled chips of the document's swatches, and Apply Fill to Stroke and Apply
|
||||
//! Stroke to Fill ([`copy_paint`]) copy each object's own paint across. Its panel and its submenu,
|
||||
//! Object › Plug-ins › Color Effects, are the UI's.
|
||||
|
||||
pub mod legend;
|
||||
mod nearest;
|
||||
@@ -14,13 +15,14 @@ mod print_fixes;
|
||||
mod tests;
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::{Document, Node, NodeId, NodeKind};
|
||||
use vectorcraft_doc::{CharStyle, Document, Node, NodeId, NodeKind};
|
||||
use vectorcraft_render::effects;
|
||||
|
||||
use super::super::colorcmds::recolor_links;
|
||||
use super::super::paint::{restore_unpainted_stroke, set_run_stroke};
|
||||
use super::super::select::walk_selectable;
|
||||
use super::super::{CommandSpec, bad, checked_ids_or_selection, cmd, has_doc, has_selection, text_param};
|
||||
use crate::{Result, Session};
|
||||
use super::super::{CommandSpec, bad, checked_ids_or_selection, cmd, has_doc, has_selection, paint_targets, switch_or, text_param};
|
||||
use crate::{EngineError, Result, Session};
|
||||
|
||||
/// The kinds Select by Color Kind selects (`addon.color.select`).
|
||||
pub const SELECT_KINDS: [&str; 5] = ["spotColors", "colorEffects", "rgbImages", "cmykImages", "grayImages"];
|
||||
@@ -72,6 +74,24 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_selection,
|
||||
nearest::apply
|
||||
),
|
||||
cmd!(
|
||||
"addon.color.fillToStroke",
|
||||
"Apply Fill to Stroke",
|
||||
["Object", "Plug-ins", "Color Effects"],
|
||||
None,
|
||||
"{ids?|id?, skipNone?: bool} each target's top stroke takes its own top fill, as it is (a colour in its model, a global or spot colour linked at its tint, a gradient or pattern with its placement, None); a stroke given paint at width 0 gets 1 pt, as Swap Fill and Stroke does. Type: each run's stroke takes its own fill, and while the Type tool has characters selected (no ids), only those. A graph's series marks and labels keep the paint when the graph is drawn again. skipNone: leave alone a target whose fill is None. A target whose stroke already has that paint is left as it is, and when nothing changes no undo step is recorded. The default stroke takes the default fill the same way → {objects}",
|
||||
has_doc,
|
||||
|s, p| copy_paint(s, p, true)
|
||||
),
|
||||
cmd!(
|
||||
"addon.color.strokeToFill",
|
||||
"Apply Stroke to Fill",
|
||||
["Object", "Plug-ins", "Color Effects"],
|
||||
None,
|
||||
"{ids?|id?, skipNone?: bool} each target's top fill takes its own top stroke's paint, as addon.color.fillToStroke does the other way; the stroke itself is unchanged. The default fill takes the default stroke → {objects}",
|
||||
has_doc,
|
||||
|s, p| copy_paint(s, p, false)
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(legend::specs())
|
||||
@@ -156,3 +176,97 @@ fn filter(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let swatches = |name: &str| kinds.get(name).copied();
|
||||
recolor_links(s, &given, label, &|c| map.apply(c), &|c, link, tint| map.apply_link(c, link, tint, &swatches))
|
||||
}
|
||||
|
||||
/// Apply Fill to Stroke (`to_stroke`) or Apply Stroke to Fill: each target copies one of its own
|
||||
/// paints onto the other, so a mixed selection keeps each object's colour (#5530). Aimed and
|
||||
/// undone like Swap Fill and Stroke; characters selected with the Type tool are the only ones that
|
||||
/// change, as for `paint.setFill`. A graph's series marks and labels give the graph the paint in
|
||||
/// the same undo step, as `paint.setFill` does, so drawing the graph again keeps it. When nothing
|
||||
/// changes, the document and its undo history stay as they are.
|
||||
fn copy_paint(s: &mut Session, p: &Value, to_stroke: bool) -> Result<Value> {
|
||||
let (cmd, label) =
|
||||
if to_stroke { ("addon.color.fillToStroke", "Apply Fill to Stroke") } else { ("addon.color.strokeToFill", "Apply Stroke to Fill") };
|
||||
let skip_none = switch_or(p, "skipNone", false, cmd)?;
|
||||
// One text style: its stroke takes its fill, or the other way.
|
||||
let copy_run = |st: &mut CharStyle| {
|
||||
let from = if to_stroke { st.fill.clone() } else { st.stroke.clone() };
|
||||
if (skip_none && from.is_none()) || from == if to_stroke { st.stroke.clone() } else { st.fill.clone() } {
|
||||
return;
|
||||
}
|
||||
if to_stroke {
|
||||
set_run_stroke(st, from);
|
||||
} else {
|
||||
st.fill = from;
|
||||
}
|
||||
};
|
||||
if p.get("ids").is_none()
|
||||
&& p.get("id").is_none()
|
||||
&& let Some((id, a, b)) = super::super::textedit::editing_range(s)?
|
||||
&& a != b
|
||||
{
|
||||
// After Select All in threaded text, every frame's text takes it.
|
||||
let story = super::super::textedit::editing_story(s);
|
||||
let ranges: Vec<(NodeId, usize, usize)> =
|
||||
if story.is_empty() { vec![(id, a, b)] } else { story.iter().map(|f| (*f, 0, usize::MAX)).collect() };
|
||||
let ids: Vec<NodeId> = ranges.iter().map(|(f, _, _)| *f).collect();
|
||||
let before = s.doc()?.doc.clone();
|
||||
let n = super::super::overprint::edit_counted(s, label, |d| {
|
||||
for &(id, a, b) in &ranges {
|
||||
let Some(NodeKind::Text(t)) = d.node_mut(id).map(|n| &mut n.kind) else { return Err(EngineError::NoNode(id)) };
|
||||
vectorcraft_text::edit::style_range(&mut t.runs, a, b, copy_run);
|
||||
super::super::typecmd::refresh_bounds(t);
|
||||
}
|
||||
Ok(super::super::appearance::count_changed(d, &before, &ids))
|
||||
})?;
|
||||
return Ok(json!({"objects": n}));
|
||||
}
|
||||
// A graph's series group stands for its marks, as for `paint.setFill`.
|
||||
let ids = super::super::graph::paint_targets(&s.doc()?.doc, &paint_targets(s, p)?);
|
||||
let mut objects = 0;
|
||||
if !ids.is_empty() {
|
||||
let before = s.doc()?.doc.clone();
|
||||
super::super::overprint::edit_counted(s, label, |d| {
|
||||
for id in &ids {
|
||||
let Some(node) = d.node_mut(*id) else { continue };
|
||||
if let NodeKind::Text(t) = &mut node.kind {
|
||||
for r in &mut t.runs {
|
||||
copy_run(&mut r.style);
|
||||
}
|
||||
super::super::typecmd::refresh_bounds(t);
|
||||
continue;
|
||||
}
|
||||
let ap = &mut node.appearance;
|
||||
let (from, to) = if to_stroke { (ap.fill_paint(), ap.stroke_paint()) } else { (ap.stroke_paint(), ap.fill_paint()) };
|
||||
// A missing item reads as None: copying None onto it would add an item that
|
||||
// changes nothing.
|
||||
if (skip_none && from.is_none()) || from == to {
|
||||
continue;
|
||||
}
|
||||
if to_stroke {
|
||||
restore_unpainted_stroke(ap, None, &from);
|
||||
ap.set_stroke(from);
|
||||
} else {
|
||||
ap.set_fill(from);
|
||||
}
|
||||
}
|
||||
objects = super::super::appearance::count_changed(d, &before, &ids);
|
||||
// The graph keeps the paint its series marks and labels now have.
|
||||
let series = super::super::graph::capture_series_paints(d, &ids, !to_stroke);
|
||||
let labels = super::super::graph::capture_label_styles(d, &ids, ©_run);
|
||||
Ok(objects + usize::from(series || labels))
|
||||
})?;
|
||||
}
|
||||
// The defaults for new art change the same way, as Swap Fill and Stroke changes them.
|
||||
let from = if to_stroke { s.paint.fill.clone() } else { s.paint.stroke.clone() };
|
||||
if !(skip_none && from.is_none()) {
|
||||
if to_stroke {
|
||||
if s.paint.stroke.is_none() && !from.is_none() && s.paint.stroke_width == 0.0 {
|
||||
s.paint.stroke_width = 1.0;
|
||||
}
|
||||
s.paint.stroke = from;
|
||||
} else {
|
||||
s.paint.fill = from;
|
||||
}
|
||||
}
|
||||
Ok(json!({"objects": objects}))
|
||||
}
|
||||
|
||||
@@ -732,7 +732,7 @@ pub(crate) fn picked_mesh_points_of(s: &Session, ids: &[NodeId]) -> Option<Vec<(
|
||||
}
|
||||
|
||||
/// A type run's stroke; a painted stroke on a run without one gets 1 pt.
|
||||
fn set_run_stroke(style: &mut CharStyle, paint: Paint) {
|
||||
pub(super) fn set_run_stroke(style: &mut CharStyle, paint: Paint) {
|
||||
if !paint.is_none() {
|
||||
run_stroke_weight(style);
|
||||
}
|
||||
|
||||
@@ -414,3 +414,258 @@ fn a_group_shows_its_contents_in_the_proxies() {
|
||||
s.execute("select.none", &json!({})).unwrap();
|
||||
assert_eq!(s.proxy_paints().0, s.paint.fill);
|
||||
}
|
||||
|
||||
/// The top fill and top stroke of object `id`.
|
||||
fn paints(s: &Session, id: NodeId) -> (Paint, Paint, f64) {
|
||||
let n = node(s, id);
|
||||
(n.appearance.fill_paint(), n.appearance.stroke_paint(), n.appearance.stroke().map_or(0.0, |st| st.width))
|
||||
}
|
||||
|
||||
/// Apply Fill to Stroke gives each selected object a stroke of its own fill, not the first
|
||||
/// object's; Apply Stroke to Fill does the other way (#5530). A stroke that had no paint and no
|
||||
/// width gets the 1 pt Swap Fill and Stroke gives it, and the paint copied from stays.
|
||||
#[test]
|
||||
fn each_object_copies_its_own_paint_onto_the_other() {
|
||||
let mut s = session();
|
||||
let (a, b) = (rect(&mut s), rect(&mut s));
|
||||
for (id, hex) in [(a, "#ff0000"), (b, "#0080ff")] {
|
||||
s.execute("paint.setFill", &json!({"ids": [id.0], "color": hex})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [id.0], "none": true})).unwrap();
|
||||
s.execute("object.setStrokeWidth", &json!({"ids": [id.0], "width": 0})).ok();
|
||||
}
|
||||
s.execute("select.set", &json!({"ids": [a.0, b.0]})).unwrap();
|
||||
let r = s.execute("addon.color.fillToStroke", &json!({})).unwrap();
|
||||
assert_eq!(r["objects"], 2);
|
||||
for (id, hex) in [(a, "#ff0000"), (b, "#0080ff")] {
|
||||
let (fill, stroke, width) = paints(&s, id);
|
||||
assert_eq!(fill.color().unwrap().to_hex(), hex, "the fill stays");
|
||||
assert_eq!(stroke, fill, "the stroke is the object's own fill");
|
||||
assert!(width > 0.0, "and shows: {width}");
|
||||
}
|
||||
s.execute("paint.setStroke", &json!({"ids": [a.0], "color": "#00ff00"})).unwrap();
|
||||
s.execute("addon.color.strokeToFill", &json!({"ids": [a.0]})).unwrap();
|
||||
let (fill, stroke, _) = paints(&s, a);
|
||||
assert_eq!((fill.color().unwrap().to_hex(), stroke.color().unwrap().to_hex()), ("#00ff00".into(), "#00ff00".into()));
|
||||
assert_eq!(paints(&s, b).0.color().unwrap().to_hex(), "#0080ff", "an object not aimed at is left alone");
|
||||
}
|
||||
|
||||
/// A global swatch at a tint stays linked at that tint, and a gradient keeps its stops and
|
||||
/// placement: the paint is copied as it is.
|
||||
#[test]
|
||||
fn a_linked_swatch_and_a_gradient_copy_as_they_are() {
|
||||
let mut s = session();
|
||||
let a = rect(&mut s);
|
||||
s.execute("swatch.new", &json!({"name": "Ink", "color": "#c82828", "global": true})).unwrap();
|
||||
s.execute("paint.setFill", &json!({"ids": [a.0], "swatch": "Ink", "tint": 40})).unwrap();
|
||||
s.execute("addon.color.fillToStroke", &json!({"ids": [a.0]})).unwrap();
|
||||
let (fill, stroke, _) = paints(&s, a);
|
||||
assert!(matches!(&stroke, Paint::Solid { swatch: Some(name), .. } if name == "Ink"), "{stroke:?}");
|
||||
assert_eq!(stroke, fill);
|
||||
let g = json!({"gradient": {"kind": "linear", "stops": [{"offset": 0, "color": "#ff0000"}, {"offset": 1, "color": "#0000ff"}], "angle": 30}});
|
||||
let mut q = g.clone();
|
||||
q["ids"] = json!([a.0]);
|
||||
s.execute("paint.setFill", &q).unwrap();
|
||||
s.execute("addon.color.fillToStroke", &json!({"ids": [a.0]})).unwrap();
|
||||
let (fill, stroke, _) = paints(&s, a);
|
||||
assert!(matches!(stroke, Paint::Gradient { .. }), "{stroke:?}");
|
||||
assert_eq!(stroke, fill, "the same stops and placement");
|
||||
}
|
||||
|
||||
/// None copies as None, as Swap moves it; `skipNone` leaves an object whose source is None alone.
|
||||
#[test]
|
||||
fn none_copies_unless_skipped() {
|
||||
let mut s = session();
|
||||
let (a, b) = (rect(&mut s), rect(&mut s));
|
||||
s.execute("paint.setFill", &json!({"ids": [a.0], "none": true})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [a.0, b.0], "color": "#123456"})).unwrap();
|
||||
s.execute("paint.setFill", &json!({"ids": [b.0], "color": "#ff8000"})).unwrap();
|
||||
let r = s.execute("addon.color.fillToStroke", &json!({"ids": [a.0, b.0], "skipNone": true})).unwrap();
|
||||
assert_eq!(r["objects"], 1, "only the object with a fill changed");
|
||||
assert_eq!(paints(&s, a).1.color().unwrap().to_hex(), "#123456", "skipped: its stroke stays");
|
||||
assert_eq!(paints(&s, b).1.color().unwrap().to_hex(), "#ff8000");
|
||||
s.execute("addon.color.fillToStroke", &json!({"ids": [a.0]})).unwrap();
|
||||
assert!(paints(&s, a).1.is_none(), "without skipNone, no fill gives no stroke");
|
||||
}
|
||||
|
||||
/// The objects inside a group each copy their own paint, as for Swap Fill and Stroke.
|
||||
#[test]
|
||||
fn a_groups_members_each_copy_their_own() {
|
||||
let mut s = session();
|
||||
let (a, b) = (rect(&mut s), rect(&mut s));
|
||||
s.execute("paint.setFill", &json!({"ids": [a.0], "color": "#ff0000"})).unwrap();
|
||||
s.execute("paint.setFill", &json!({"ids": [b.0], "color": "#00ff00"})).unwrap();
|
||||
s.execute("select.set", &json!({"ids": [a.0, b.0]})).unwrap();
|
||||
let g = NodeId(s.execute("object.group", &json!({})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("select.set", &json!({"ids": [g.0]})).unwrap();
|
||||
s.execute("addon.color.fillToStroke", &json!({})).unwrap();
|
||||
assert_eq!(paints(&s, a).1.color().unwrap().to_hex(), "#ff0000");
|
||||
assert_eq!(paints(&s, b).1.color().unwrap().to_hex(), "#00ff00");
|
||||
}
|
||||
|
||||
/// Type: each run's stroke takes its own fill, so multi-colour text keeps its colours.
|
||||
#[test]
|
||||
fn each_text_run_copies_its_own_fill() {
|
||||
let mut s = session();
|
||||
let id = NodeId(s.execute("text.create", &json!({"x": 10, "y": 50, "text": "Hi"})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("paint.setFill", &json!({"ids": [id.0], "color": "#aa0000"})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [id.0], "none": true})).unwrap();
|
||||
s.execute("addon.color.fillToStroke", &json!({"ids": [id.0]})).unwrap();
|
||||
let NodeKind::Text(t) = &node(&s, id).kind else { panic!("not text") };
|
||||
for r in &t.runs {
|
||||
assert_eq!(r.style.stroke, r.style.fill, "{:?}", r.text);
|
||||
assert!(r.style.stroke_width > 0.0, "a painted stroke is visible");
|
||||
}
|
||||
}
|
||||
|
||||
/// One undo step each; when nothing changes, none, and the document stays unmodified. Bad
|
||||
/// parameters change nothing, not even the defaults.
|
||||
#[test]
|
||||
fn one_undo_step_none_when_nothing_changes_and_bad_params_change_nothing() {
|
||||
let mut s = session();
|
||||
let id = rect(&mut s);
|
||||
s.execute("paint.setFill", &json!({"ids": [id.0], "color": "#ff0000"})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [id.0], "color": "#ff0000"})).unwrap();
|
||||
select_with_a_step_to_redo(&mut s, &[id]);
|
||||
let before = history(&s);
|
||||
s.execute("addon.color.fillToStroke", &json!({})).unwrap();
|
||||
s.execute("addon.color.strokeToFill", &json!({})).unwrap();
|
||||
assert_eq!(history(&s), before, "the paints were already the same");
|
||||
s.execute("paint.setStroke", &json!({"ids": [id.0], "color": "#0000ff"})).unwrap();
|
||||
let before = history(&s);
|
||||
s.execute("addon.color.fillToStroke", &json!({})).unwrap();
|
||||
assert_eq!(history(&s), (before.0 + 1, 0, true), "one step");
|
||||
assert_eq!(s.doc().unwrap().history.undo.last().map(|e| e.label.as_str()), Some("Apply Fill to Stroke"));
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(paints(&s, id).1.color().unwrap().to_hex(), "#0000ff");
|
||||
let defaults = (s.paint.fill.clone(), s.paint.stroke.clone());
|
||||
for (cmd, p) in [("addon.color.fillToStroke", json!({"ids": "not an array"})), ("addon.color.strokeToFill", json!({"skipNone": "yes"}))] {
|
||||
assert!(s.execute(cmd, &p).is_err(), "{cmd} {p}");
|
||||
}
|
||||
assert_eq!((s.paint.fill.clone(), s.paint.stroke.clone()), defaults, "the defaults are as they were");
|
||||
}
|
||||
|
||||
/// With nothing selected the defaults for new art change the same way: the default stroke takes
|
||||
/// the default fill, with the weight Swap gives a stroke that had none.
|
||||
#[test]
|
||||
fn with_nothing_selected_the_defaults_take_it() {
|
||||
let mut s = session();
|
||||
s.execute("select.set", &json!({"ids": []})).unwrap();
|
||||
s.execute("paint.setFill", &json!({"color": "#336699"})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"none": true})).unwrap();
|
||||
let r = s.execute("addon.color.fillToStroke", &json!({})).unwrap();
|
||||
assert_eq!(r["objects"], 0);
|
||||
assert_eq!(s.paint.stroke, s.paint.fill);
|
||||
assert!(s.paint.stroke_width > 0.0);
|
||||
s.execute("paint.setStroke", &json!({"color": "#ff00ff"})).unwrap();
|
||||
s.execute("addon.color.strokeToFill", &json!({})).unwrap();
|
||||
assert_eq!(s.paint.fill.color().unwrap().to_hex(), "#ff00ff");
|
||||
}
|
||||
|
||||
/// Copying None onto an item the object doesn't have adds nothing: with no fill and no stroke
|
||||
/// item at all, neither command records an undo step or touches the object.
|
||||
#[test]
|
||||
fn copying_none_onto_a_missing_item_changes_nothing() {
|
||||
let mut s = session();
|
||||
let id = rect(&mut s);
|
||||
s.edit("No paint items", |d, _| {
|
||||
d.node_mut(id).unwrap().appearance.items.clear();
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!((paints(&s, id).0, paints(&s, id).1), (Paint::None, Paint::None));
|
||||
select_with_a_step_to_redo(&mut s, &[id]);
|
||||
let (before, art) = (history(&s), node(&s, id));
|
||||
for cmd in ["addon.color.fillToStroke", "addon.color.strokeToFill"] {
|
||||
assert_eq!(s.execute(cmd, &json!({})).unwrap()["objects"], 0, "{cmd}");
|
||||
assert_eq!(history(&s), before, "{cmd}: no undo step");
|
||||
assert_eq!(node(&s, id), art, "{cmd}: no item added");
|
||||
}
|
||||
}
|
||||
|
||||
/// A graph's series and its labels keep the copied paint when the graph is drawn again: the
|
||||
/// graph takes it in the same undo step, as it does from paint.setFill.
|
||||
#[test]
|
||||
fn a_graph_series_and_its_labels_keep_the_copied_paint_when_drawn_again() {
|
||||
let mut s = session();
|
||||
let csv = ",2024,2025\nQ1,3,2\nQ2,5,4";
|
||||
let g = NodeId(
|
||||
s.execute("graph.create", &json!({"type": "column", "x": 100, "y": 100, "width": 300, "height": 200, "csv": csv})).unwrap()["id"]
|
||||
.as_u64()
|
||||
.unwrap(),
|
||||
);
|
||||
let series = |s: &Session| node(s, g).children().unwrap().iter().find(|c| c.extras().series_index == Some(0)).unwrap().clone();
|
||||
let label = |s: &Session| {
|
||||
let axes = node(s, g).children().unwrap().iter().find(|c| c.name.as_deref() == Some("Axes")).unwrap().clone();
|
||||
axes.children().unwrap().iter().find(|c| matches!(&c.kind, NodeKind::Text(t) if t.plain_text() == "4")).unwrap().clone()
|
||||
};
|
||||
let sid = series(&s).id;
|
||||
s.execute("paint.setFill", &json!({"ids": [sid.0], "color": "#12ab34"})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [sid.0], "none": true})).unwrap();
|
||||
let lid = label(&s).id;
|
||||
s.execute("paint.setFill", &json!({"ids": [lid.0], "color": "#e8573f"})).unwrap();
|
||||
let steps = s.doc().unwrap().history.undo.len();
|
||||
s.execute("addon.color.fillToStroke", &json!({"ids": [sid.0, lid.0]})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), steps + 1, "one step");
|
||||
let kept = s.doc().unwrap().doc.node(g).unwrap().extras().graph.as_deref().unwrap().clone();
|
||||
assert_eq!(kept.series_paints[0].stroke.as_ref().and_then(Paint::color).map(|c| c.to_hex()), Some("#12ab34".into()));
|
||||
assert_eq!(kept.label_styles.values.as_ref().and_then(|st| st.stroke.color()).map(|c| c.to_hex()), Some("#e8573f".into()));
|
||||
s.execute("graph.setData", &json!({"id": g.0, "rows": [[1, 2], [3, 4]]})).unwrap();
|
||||
let marks = series(&s).children().unwrap().to_vec();
|
||||
let bars: Vec<_> = marks.iter().filter(|m| matches!(m.kind, NodeKind::Path { .. })).collect();
|
||||
assert!(!bars.is_empty());
|
||||
for m in bars {
|
||||
assert_eq!(m.appearance.stroke_paint().color().map(|c| c.to_hex()), Some("#12ab34".into()), "a redrawn mark keeps the stroke");
|
||||
}
|
||||
let redrawn = node(&s, g).children().unwrap().iter().find(|c| c.name.as_deref() == Some("Axes")).unwrap().clone();
|
||||
let text = redrawn.children().unwrap().iter().find_map(|c| if let NodeKind::Text(t) = &c.kind { Some(t.clone()) } else { None }).unwrap();
|
||||
assert_eq!(text.runs[0].style.stroke.color().map(|c| c.to_hex()), Some("#e8573f".into()), "a redrawn value label keeps the stroke");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
let back = s.doc().unwrap().doc.node(g).unwrap().extras().graph.as_deref().unwrap().clone();
|
||||
assert!(
|
||||
back.series_paints[0].stroke.as_ref().is_none_or(|p| p.is_none()),
|
||||
"undo takes the graph's stroke back: {:?}",
|
||||
back.series_paints[0].stroke
|
||||
);
|
||||
}
|
||||
|
||||
/// A series drawn with a marker design: its own marks copy their paint, but the design's art
|
||||
/// keeps the design's paint, as paint.setFill leaves it (painting it would last only until the
|
||||
/// graph is drawn again).
|
||||
#[test]
|
||||
fn a_marker_designs_art_in_a_series_keeps_its_paint() {
|
||||
let mut s = session();
|
||||
let r = s.execute("shape.rectangle", &json!({"x": 600, "y": 600, "width": 10, "height": 10})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("paint.setFill", &json!({"ids": [r], "color": "#0000ff"})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"ids": [r], "none": true})).unwrap();
|
||||
s.execute("select.set", &json!({"ids": [r]})).unwrap();
|
||||
s.execute("graph.design", &json!({"new": "Square"})).unwrap();
|
||||
let csv = ",2024,2025\nQ1,3,2\nQ2,5,4";
|
||||
let g = NodeId(
|
||||
s.execute("graph.create", &json!({"type": "line", "x": 100, "y": 100, "width": 300, "height": 200, "csv": csv})).unwrap()["id"]
|
||||
.as_u64()
|
||||
.unwrap(),
|
||||
);
|
||||
s.execute("select.set", &json!({"ids": [g.0]})).unwrap();
|
||||
s.execute("graph.marker", &json!({"design": "Square"})).unwrap();
|
||||
let series = node(&s, g).children().unwrap().iter().find(|c| c.extras().series_index == Some(0)).unwrap().clone();
|
||||
// The design's paths sit in groups inside the series; its own marks are its direct children.
|
||||
let design_strokes = |s: &Session| {
|
||||
let grp = node(s, series.id);
|
||||
let mut out = vec![];
|
||||
for c in grp.children().unwrap() {
|
||||
if !matches!(c.kind, NodeKind::Path { .. }) {
|
||||
c.walk(&mut |n| {
|
||||
if let NodeKind::Path { .. } = n.kind {
|
||||
out.push(n.appearance.stroke_paint());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
out
|
||||
};
|
||||
let before = design_strokes(&s);
|
||||
assert!(!before.is_empty(), "the series draws the design");
|
||||
s.execute("addon.color.fillToStroke", &json!({"ids": [series.id.0]})).unwrap();
|
||||
assert_eq!(design_strokes(&s), before, "the design's art keeps its paint");
|
||||
}
|
||||
|
||||
@@ -3003,3 +3003,28 @@ fn the_fallback_glyph_of_a_consonant_after_its_vowel_sign_is_reported() {
|
||||
let query = s.execute("text.glyphAlternates", &json!({"id": boxed.0, "start": 0})).unwrap();
|
||||
assert_eq!(query["chosen"], json!(ka), "an overflowing Ka reports the fallback face's glyph for Ka");
|
||||
}
|
||||
|
||||
/// Apply Fill to Stroke with characters selected with the Type tool: only those characters take
|
||||
/// a stroke of their own fill, as one undo step (#5530).
|
||||
#[test]
|
||||
fn apply_fill_to_stroke_with_characters_selected_changes_only_them() {
|
||||
let mut s = session();
|
||||
let v = ViewInfo::default();
|
||||
s.select_tool("type", v).unwrap();
|
||||
click(&mut s, 50.0, 300.0);
|
||||
let id = s.doc().unwrap().selection.objects[0];
|
||||
s.tool_text("Sample Text", v).unwrap();
|
||||
// All of it red, then the first word green: a stroke on the rest would show.
|
||||
s.execute("paint.setFill", &json!({"ids": [id.0], "color": "#ff0000"})).unwrap();
|
||||
s.set_tool_option("select", &json!({"start": 0, "end": 6}));
|
||||
s.execute("paint.setFill", &json!({"color": "#00a000"})).unwrap();
|
||||
let steps = undo_labels(&s).len();
|
||||
s.execute("addon.color.fillToStroke", &json!({})).unwrap();
|
||||
let t = obj(&s, id);
|
||||
assert_eq!(t.runs[0].text, "Sample");
|
||||
assert_eq!(t.runs[0].style.stroke, t.runs[0].style.fill, "the selected characters take their fill as a stroke");
|
||||
assert!(t.runs[0].style.stroke_width > 0.0);
|
||||
assert!(t.runs[1].style.stroke.is_none(), "the rest of the type keeps its stroke");
|
||||
let labels = undo_labels(&s);
|
||||
assert_eq!((labels.len(), labels.last().map(String::as_str)), (steps + 1, Some("Apply Fill to Stroke")));
|
||||
}
|
||||
|
||||
@@ -104,6 +104,10 @@ pub fn menu() -> Vec<Item> {
|
||||
Item::Cmd("Find Nearest Swatch…", nearest::COMMAND, Value::Null),
|
||||
Item::Cmd("Create Swatch Legend…", legend::COMMAND, Value::Null),
|
||||
Item::Sep,
|
||||
// Each selected object's stroke takes its own fill, or the other way (#5530).
|
||||
Item::Cmd("Apply Fill to Stroke", "addon.color.fillToStroke", json!({})),
|
||||
Item::Cmd("Apply Stroke to Fill", "addon.color.strokeToFill", json!({})),
|
||||
Item::Sep,
|
||||
Item::Sub(
|
||||
"Select by Color Kind",
|
||||
[
|
||||
|
||||
@@ -5952,6 +5952,9 @@ anchor Points: Точки:
|
||||
Find Nearest Swatch… Намиране на най-близкия образец…
|
||||
Find Nearest Swatch Намиране на най-близкия образец
|
||||
Apply Nearest Swatch Прилагане на най-близкия образец
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Прилагане на запълването към щриха
|
||||
Apply Stroke to Fill Прилагане на щриха към запълването
|
||||
Select objects to find the swatches nearest their colors. Изберете обекти, за да намерите най-близките до цветовете им образци.
|
||||
@msg select objects or give `color` изберете обекти или задайте `color`
|
||||
@msg `color` is not a colour `color` не е цвят
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6078,6 +6078,9 @@ shape Open Otvoren
|
||||
Find Nearest Swatch… Pronađi najbliži uzorak boje…
|
||||
Find Nearest Swatch Pronađi najbliži uzorak boje
|
||||
Apply Nearest Swatch Primijeni najbliži uzorak boje
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Primijeni ispunu na potez
|
||||
Apply Stroke to Fill Primijeni potez na ispunu
|
||||
Select objects to find the swatches nearest their colors. Odaberite objekte da pronađete uzorke boja najbliže njihovim bojama.
|
||||
@msg select objects or give `color` odaberite objekte ili navedite `color`
|
||||
@msg `color` is not a colour `color` nije boja
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6087,6 +6087,9 @@ anchor Points: Punts:
|
||||
Find Nearest Swatch… Cerca la mostra més propera…
|
||||
Find Nearest Swatch Cerca la mostra més propera
|
||||
Apply Nearest Swatch Aplica la mostra més propera
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Aplica el farciment al traç
|
||||
Apply Stroke to Fill Aplica el traç al farciment
|
||||
Select objects to find the swatches nearest their colors. Seleccioneu objectes per trobar les mostres més properes als seus colors.
|
||||
@msg select objects or give `color` seleccioneu objectes o indiqueu `color`
|
||||
@msg `color` is not a colour `color` no és un color
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6103,6 +6103,9 @@ anchor Points: Body:
|
||||
Find Nearest Swatch… Najít nejbližší položku vzorníku…
|
||||
Find Nearest Swatch Najít nejbližší položku vzorníku
|
||||
Apply Nearest Swatch Použít nejbližší položku vzorníku
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Použít výplň na tah
|
||||
Apply Stroke to Fill Použít tah na výplň
|
||||
Select objects to find the swatches nearest their colors. Vyberte objekty, k jejichž barvám chcete najít nejbližší položky vzorníku.
|
||||
@msg select objects or give `color` vyberte objekty nebo zadejte `color`
|
||||
@msg `color` is not a colour `color` není barva
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5969,6 +5969,9 @@ anchor Points: Punkter:
|
||||
Find Nearest Swatch… Find nærmeste farveprøve…
|
||||
Find Nearest Swatch Find nærmeste farveprøve
|
||||
Apply Nearest Swatch Anvend nærmeste farveprøve
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Anvend udfyldning på kontur
|
||||
Apply Stroke to Fill Anvend kontur på udfyldning
|
||||
Select objects to find the swatches nearest their colors. Markér objekter for at finde de farveprøver, der ligger tættest på deres farver.
|
||||
@msg select objects or give `color` markér objekter, eller angiv `color`
|
||||
@msg `color` is not a colour `color` er ikke en farve
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5688,6 +5688,9 @@ anchor Points: Punkte:
|
||||
Find Nearest Swatch… Ähnlichstes Farbfeld suchen…
|
||||
Find Nearest Swatch Ähnlichstes Farbfeld suchen
|
||||
Apply Nearest Swatch Ähnlichstes Farbfeld anwenden
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Fläche auf Kontur anwenden
|
||||
Apply Stroke to Fill Kontur auf Fläche anwenden
|
||||
Select objects to find the swatches nearest their colors. Wählen Sie Objekte aus, um die Farbfelder zu finden, die ihren Farben am nächsten kommen.
|
||||
@msg select objects or give `color` wählen Sie Objekte aus oder geben Sie `color` an
|
||||
@msg `color` is not a colour `color` ist keine Farbe
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6054,6 +6054,9 @@ anchor Points: Σημεία:
|
||||
Find Nearest Swatch… Εύρεση πλησιέστερου δείγματος χρώματος…
|
||||
Find Nearest Swatch Εύρεση πλησιέστερου δείγματος χρώματος
|
||||
Apply Nearest Swatch Εφαρμογή πλησιέστερου δείγματος χρώματος
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Εφαρμογή γεμίσματος στο περίγραμμα
|
||||
Apply Stroke to Fill Εφαρμογή περιγράμματος στο γέμισμα
|
||||
Select objects to find the swatches nearest their colors. Επιλέξτε αντικείμενα για να βρείτε τα δείγματα χρωμάτων που πλησιάζουν περισσότερο τα χρώματά τους.
|
||||
@msg select objects or give `color` επιλέξτε αντικείμενα ή δώστε `color`
|
||||
@msg `color` is not a colour το `color` δεν είναι χρώμα
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 163 and column 5.
|
@@ -6045,6 +6045,9 @@ anchor Points: Puntos:
|
||||
Find Nearest Swatch… Buscar muestra más cercana…
|
||||
Find Nearest Swatch Buscar muestra más cercana
|
||||
Apply Nearest Swatch Aplicar muestra más cercana
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Aplicar relleno al trazo
|
||||
Apply Stroke to Fill Aplicar trazo al relleno
|
||||
Select objects to find the swatches nearest their colors. Seleccione objetos para buscar las muestras más cercanas a sus colores.
|
||||
@msg select objects or give `color` seleccione objetos o indique `color`
|
||||
@msg `color` is not a colour `color` no es un color
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6133,6 +6133,9 @@ anchor Points: Pisteet:
|
||||
Find Nearest Swatch… Etsi lähin värimalli…
|
||||
Find Nearest Swatch Etsi lähin värimalli
|
||||
Apply Nearest Swatch Käytä lähintä värimallia
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Käytä täyttöä viivaan
|
||||
Apply Stroke to Fill Käytä viivaa täyttöön
|
||||
Select objects to find the swatches nearest their colors. Valitse objektit, joiden väreille haluat etsiä lähimmät värimallit.
|
||||
@msg select objects or give `color` valitse objekteja tai anna `color`
|
||||
@msg `color` is not a colour `color` ei ole väri
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6098,6 +6098,9 @@ anchor Points: Points :
|
||||
Find Nearest Swatch… Rechercher la nuance la plus proche…
|
||||
Find Nearest Swatch Rechercher la nuance la plus proche
|
||||
Apply Nearest Swatch Appliquer la nuance la plus proche
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Appliquer le fond au contour
|
||||
Apply Stroke to Fill Appliquer le contour au fond
|
||||
Select objects to find the swatches nearest their colors. Sélectionnez des objets pour trouver les nuances les plus proches de leurs couleurs.
|
||||
@msg select objects or give `color` sélectionnez des objets ou indiquez `color`
|
||||
@msg `color` is not a colour `color` n’est pas une couleur
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6087,6 +6087,9 @@ anchor Points: Pontok:
|
||||
Find Nearest Swatch… Legközelebbi színminta keresése…
|
||||
Find Nearest Swatch Legközelebbi színminta keresése
|
||||
Apply Nearest Swatch Legközelebbi színminta alkalmazása
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Kitöltés alkalmazása a körvonalra
|
||||
Apply Stroke to Fill Körvonal alkalmazása a kitöltésre
|
||||
Select objects to find the swatches nearest their colors. Jelöljön ki objektumokat a színeikhez legközelebbi színminták megkereséséhez.
|
||||
@msg select objects or give `color` jelöljön ki objektumokat, vagy adja meg ezt: `color`
|
||||
@msg `color` is not a colour a(z) `color` nem szín
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5969,6 +5969,9 @@ anchor Points: Titik:
|
||||
Find Nearest Swatch… Cari Swatch Terdekat…
|
||||
Find Nearest Swatch Cari Swatch Terdekat
|
||||
Apply Nearest Swatch Terapkan Swatch Terdekat
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Terapkan isian ke guratan
|
||||
Apply Stroke to Fill Terapkan guratan ke isian
|
||||
Select objects to find the swatches nearest their colors. Pilih objek untuk menemukan swatch yang paling dekat dengan warnanya.
|
||||
@msg select objects or give `color` pilih objek atau berikan `color`
|
||||
@msg `color` is not a colour `color` bukan warna
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2235 and column 5.
|
@@ -5722,6 +5722,9 @@ anchor Points: Punti:
|
||||
Find Nearest Swatch… Trova campione più vicino…
|
||||
Find Nearest Swatch Trova campione più vicino
|
||||
Apply Nearest Swatch Applica campione più vicino
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Applica riempimento alla traccia
|
||||
Apply Stroke to Fill Applica traccia al riempimento
|
||||
Select objects to find the swatches nearest their colors. Seleziona gli oggetti per trovare i campioni più vicini ai loro colori.
|
||||
@msg select objects or give `color` seleziona gli oggetti o indica `color`
|
||||
@msg `color` is not a colour `color` non è un colore
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5787,6 +5787,9 @@ anchor Points: ポイント:
|
||||
Find Nearest Swatch… 最も近いスウォッチを検索…
|
||||
Find Nearest Swatch 最も近いスウォッチを検索
|
||||
Apply Nearest Swatch 最も近いスウォッチを適用
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke 塗りを線に適用
|
||||
Apply Stroke to Fill 線を塗りに適用
|
||||
Select objects to find the swatches nearest their colors. カラーに最も近いスウォッチを探すオブジェクトを選択してください。
|
||||
@msg select objects or give `color` オブジェクトを選択するか `color` を指定してください
|
||||
@msg `color` is not a colour `color` はカラーではありません
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6100,6 +6100,9 @@ anchor Points: წერტილები:
|
||||
Find Nearest Swatch… უახლოესი ფერის ნიმუშის პოვნა…
|
||||
Find Nearest Swatch უახლოესი ფერის ნიმუშის პოვნა
|
||||
Apply Nearest Swatch უახლოესი ფერის ნიმუშის გამოყენება
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke შევსების გამოყენება კონტურზე
|
||||
Apply Stroke to Fill კონტურის გამოყენება შევსებაზე
|
||||
Select objects to find the swatches nearest their colors. აირჩიეთ ობიექტები მათ ფერებთან უახლოესი ფერის ნიმუშების საპოვნელად.
|
||||
@msg select objects or give `color` აირჩიეთ ობიექტები ან მიუთითეთ `color`
|
||||
@msg `color` is not a colour `color` ფერი არ არის
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -5683,6 +5683,9 @@ anchor Points: 포인트:
|
||||
Find Nearest Swatch… 가장 가까운 견본 찾기…
|
||||
Find Nearest Swatch 가장 가까운 견본 찾기
|
||||
Apply Nearest Swatch 가장 가까운 견본 적용
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke 칠을 선에 적용
|
||||
Apply Stroke to Fill 선을 칠에 적용
|
||||
Select objects to find the swatches nearest their colors. 색상에 가장 가까운 견본을 찾을 개체를 선택하십시오.
|
||||
@msg select objects or give `color` 개체를 선택하거나 `color`를 지정하십시오
|
||||
@msg `color` is not a colour `color`은(는) 색상이 아닙니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6013,6 +6013,9 @@ anchor Points: Punten:
|
||||
Find Nearest Swatch… Dichtstbijzijnde staal zoeken…
|
||||
Find Nearest Swatch Dichtstbijzijnde staal zoeken
|
||||
Apply Nearest Swatch Dichtstbijzijnde staal toepassen
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Vulling op streek toepassen
|
||||
Apply Stroke to Fill Streek op vulling toepassen
|
||||
Select objects to find the swatches nearest their colors. Selecteer objecten om de stalen te vinden die het dichtst bij hun kleuren liggen.
|
||||
@msg select objects or give `color` selecteer objecten of geef `color` op
|
||||
@msg `color` is not a colour `color` is geen kleur
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5957,6 +5957,9 @@ anchor Points: Punkty:
|
||||
Find Nearest Swatch… Znajdź najbliższą próbkę…
|
||||
Find Nearest Swatch Znajdź najbliższą próbkę
|
||||
Apply Nearest Swatch Zastosuj najbliższą próbkę
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Zastosuj wypełnienie do obrysu
|
||||
Apply Stroke to Fill Zastosuj obrys do wypełnienia
|
||||
Select objects to find the swatches nearest their colors. Zaznacz obiekty, aby znaleźć próbki najbliższe ich kolorom.
|
||||
@msg select objects or give `color` zaznacz obiekty lub podaj `color`
|
||||
@msg `color` is not a colour `color` nie jest kolorem
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6019,6 +6019,9 @@ anchor Points: Pontos:
|
||||
Find Nearest Swatch… Localizar Amostra Mais Próxima…
|
||||
Find Nearest Swatch Localizar Amostra Mais Próxima
|
||||
Apply Nearest Swatch Aplicar Amostra Mais Próxima
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Aplicar Preenchimento ao Traçado
|
||||
Apply Stroke to Fill Aplicar Traçado ao Preenchimento
|
||||
Select objects to find the swatches nearest their colors. Selecione objetos para localizar as amostras mais próximas de suas cores.
|
||||
@msg select objects or give `color` selecione objetos ou informe `color`
|
||||
@msg `color` is not a colour `color` não é uma cor
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -6080,6 +6080,9 @@ anchor Points: Точки:
|
||||
Find Nearest Swatch… Найти ближайший образец…
|
||||
Find Nearest Swatch Найти ближайший образец
|
||||
Apply Nearest Swatch Применить ближайший образец
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Применить заливку к обводке
|
||||
Apply Stroke to Fill Применить обводку к заливке
|
||||
Select objects to find the swatches nearest their colors. Выделите объекты, чтобы найти образцы, ближайшие к их цветам.
|
||||
@msg select objects or give `color` выделите объекты или укажите `color`
|
||||
@msg `color` is not a colour `color` не является цветом
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6155,6 +6155,9 @@ shape Open Öppen
|
||||
Find Nearest Swatch… Sök närmaste färgruta…
|
||||
Find Nearest Swatch Sök närmaste färgruta
|
||||
Apply Nearest Swatch Använd närmaste färgruta
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Använd fyllning på kontur
|
||||
Apply Stroke to Fill Använd kontur på fyllning
|
||||
Select objects to find the swatches nearest their colors. Markera objekt för att hitta de färgrutor som ligger närmast deras färger.
|
||||
@msg select objects or give `color` markera objekt eller ange `color`
|
||||
@msg `color` is not a colour `color` är ingen färg
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -6060,6 +6060,9 @@ anchor Points: Noktalar:
|
||||
Find Nearest Swatch… En Yakın Renk Örneğini Bul…
|
||||
Find Nearest Swatch En Yakın Renk Örneğini Bul
|
||||
Apply Nearest Swatch En Yakın Renk Örneğini Uygula
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Dolguyu Kontura Uygula
|
||||
Apply Stroke to Fill Konturu Dolguya Uygula
|
||||
Select objects to find the swatches nearest their colors. Renklerine en yakın renk örneklerini bulmak için nesneleri seçin.
|
||||
@msg select objects or give `color` nesneleri seçin veya `color` verin
|
||||
@msg `color` is not a colour `color` bir renk değil
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -5702,6 +5702,9 @@ anchor Points: Точки:
|
||||
Find Nearest Swatch… Знайти найближчий зразок…
|
||||
Find Nearest Swatch Знайти найближчий зразок
|
||||
Apply Nearest Swatch Застосувати найближчий зразок
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Застосувати заливку до обведення
|
||||
Apply Stroke to Fill Застосувати обведення до заливки
|
||||
Select objects to find the swatches nearest their colors. Виділіть об’єкти, щоб знайти зразки, найближчі до їхніх кольорів.
|
||||
@msg select objects or give `color` виділіть об’єкти або вкажіть `color`
|
||||
@msg `color` is not a colour `color` не є кольором
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 177 and column 5.
|
@@ -5703,6 +5703,9 @@ anchor Points: Điểm:
|
||||
Find Nearest Swatch… Tìm mẫu màu gần nhất…
|
||||
Find Nearest Swatch Tìm mẫu màu gần nhất
|
||||
Apply Nearest Swatch Áp dụng mẫu màu gần nhất
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke Áp dụng màu tô cho nét
|
||||
Apply Stroke to Fill Áp dụng nét cho màu tô
|
||||
Select objects to find the swatches nearest their colors. Chọn đối tượng để tìm các mẫu màu gần nhất với màu của chúng.
|
||||
@msg select objects or give `color` chọn đối tượng hoặc cung cấp `color`
|
||||
@msg `color` is not a colour `color` không phải là màu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 199 and column 5.
|
@@ -5944,6 +5944,9 @@ anchor Points: 点:
|
||||
Find Nearest Swatch… 查找最接近的色板…
|
||||
Find Nearest Swatch 查找最接近的色板
|
||||
Apply Nearest Swatch 应用最接近的色板
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke 将填色应用于描边
|
||||
Apply Stroke to Fill 将描边应用于填色
|
||||
Select objects to find the swatches nearest their colors. 选择对象以查找与其颜色最接近的色板。
|
||||
@msg select objects or give `color` 请选择对象或提供 `color`
|
||||
@msg `color` is not a colour `color` 不是颜色
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5740,6 +5740,9 @@ anchor Points: 點:
|
||||
Find Nearest Swatch… 尋找最接近的色票…
|
||||
Find Nearest Swatch 尋找最接近的色票
|
||||
Apply Nearest Swatch 套用最接近的色票
|
||||
# Color Effects add-on: Apply Fill to Stroke and Apply Stroke to Fill (Object › Plug-ins › Color Effects, #5530).
|
||||
Apply Fill to Stroke 將填色套用至筆畫
|
||||
Apply Stroke to Fill 將筆畫套用至填色
|
||||
Select objects to find the swatches nearest their colors. 選取物件以尋找與其顏色最接近的色票。
|
||||
@msg select objects or give `color` 請選取物件或提供 `color`
|
||||
@msg `color` is not a colour `color` 不是顏色
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
Reference in New Issue
Block a user