mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
Add-ons: Artwork Cleanup — text tools
Object › Plug-ins › Artwork Cleanup and a hideable Text row in its panel gain text tools, each one undo step: - Break Text into Lines / Paragraphs / Words / Glyphs: point type pieces placed by the glyph of their first character, keeping their styles. - Combine Point Text: one-line point type merged into as few objects as it can, every glyph staying where it was (tracking and spaces, checked against the layout). - Split Text at Cursor, Remove Line Breaks, Remove Paragraph Breaks, Set Alignment, Keep Position, Reset Text Transform and Replace Missing Fonts.
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
//! Artwork Cleanup (`addon.cleanup.*`), a built-in add-on: Simplify Anchors (Keep Shape), the
|
||||
//! Document Health Check (check, show and fix the issues it finds), Deep Ungroup and Rejoin Path
|
||||
//! Pieces. Its panel and its submenu, Object › Plug-ins › Artwork Cleanup, are the UI's.
|
||||
//! Pieces, and its text tools ([`text`]). Its panel and its submenu, Object › Plug-ins › Artwork
|
||||
//! Cleanup, are the UI's.
|
||||
|
||||
mod checks;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod text;
|
||||
|
||||
use serde_json::{Map, Value, json};
|
||||
use vectorcraft_doc::{Document, Node, NodeId, NodeKind};
|
||||
@@ -30,7 +32,7 @@ const FIX_ROUNDS: usize = 3;
|
||||
const MAX_LISTED: usize = 1000;
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
vec![
|
||||
let mut v = vec![
|
||||
cmd!(
|
||||
"addon.cleanup.simplify",
|
||||
"Simplify Anchors (Keep Shape)…",
|
||||
@@ -85,7 +87,9 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_selection,
|
||||
rejoin
|
||||
),
|
||||
]
|
||||
];
|
||||
v.extend(text::specs());
|
||||
v
|
||||
}
|
||||
|
||||
/// The paths (not guides) under `roots`, compound path members included.
|
||||
|
||||
@@ -0,0 +1,865 @@
|
||||
//! Artwork Cleanup's text tools: Break Text into Lines / Paragraphs / Words / Glyphs, Combine Point
|
||||
//! Text, Split Text at Cursor, Remove Line / Paragraph Breaks, Set Alignment, Keep Position, Reset
|
||||
//! Text Transform and Replace Missing Fonts. Each is one undo step. Pieces keep their characters'
|
||||
//! styles and stay where the layout drew them: each is moved so the glyph of its first character
|
||||
//! lands where it was.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::{CharStyle, Document, Justify, Node, NodeId, NodeKind, ParaStyle, RubySpan, TextKind, TextObject};
|
||||
use vectorcraft_geom::{Affine, Point, Vec2};
|
||||
use vectorcraft_text::{FontDb, FontMatch, TextLayout, edit};
|
||||
|
||||
use crate::cmd::textedit::editing_range;
|
||||
use crate::cmd::typecmd::refresh_bounds;
|
||||
use crate::cmd::{CommandSpec, bad, checked_ids_or_selection, cmd, has_doc, has_selection, switch_or, text_param};
|
||||
use crate::{EngineError, Result, Session};
|
||||
|
||||
/// Most text objects one command takes.
|
||||
const MAX_TEXTS: usize = 10_000;
|
||||
/// Most pieces Break Text and Split Text at Cursor make at once.
|
||||
const MAX_PIECES: usize = 20_000;
|
||||
/// Most breaks Remove Line / Paragraph Breaks removes at once.
|
||||
const MAX_BREAKS: usize = 200_000;
|
||||
/// Most pieces Combine Point Text tries to join, counted over every try: past it, what it joined
|
||||
/// so far is the result.
|
||||
const MAX_JOIN_TRIES: usize = 200_000;
|
||||
/// How far (pt) a glyph Combine Point Text sets may land from where it was.
|
||||
const TOLERANCE: f64 = 0.01;
|
||||
/// Combine Point Text: pieces whose baselines are within this many ems of each other share a line
|
||||
/// (the difference becomes baseline shift); a gap wider than `MAX_GAP` ems, or an overlap of more
|
||||
/// than `MAX_OVERLAP`, starts another object.
|
||||
const SAME_LINE: f64 = 0.4;
|
||||
const MAX_GAP: f64 = 10.0;
|
||||
const MAX_OVERLAP: f64 = 1.0;
|
||||
/// Tracking Combine Point Text may give a character (thousandths of an em).
|
||||
const TRACKING: std::ops::RangeInclusive<f64> = -1000.0..=10000.0;
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
vec![
|
||||
cmd!(
|
||||
"addon.cleanup.breakText",
|
||||
"Break Text",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{by?: \"lines\"|\"paragraphs\"|\"words\"|\"glyphs\" (lines), ids?: [id…] (default: the selection)} each horizontal point or area type object becomes point type objects, one per line, paragraph, word or glyph, each where its characters were and with their character styles, as one undo step; spaces between pieces go, a paragraph's lines stay lines (a wrapped line ends in a line break), justified lines close up, and a paragraph broken out whole keeps its bullet (not its number; other pieces have no list markers). Type on a path, vertical type, threaded type and area type whose text doesn't fit stay as they are → {ids (the pieces, selected), skipped}",
|
||||
has_selection,
|
||||
break_text
|
||||
),
|
||||
cmd!(
|
||||
"addon.cleanup.combineText",
|
||||
"Combine Point Text",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{ids?: [id…] (default: the selection)} merge one-line horizontal point type into as few objects as it can, every glyph staying where it was: pieces turned and sheared alike whose baselines line up (within 0.4 em; the difference becomes baseline shift) join left to right, a space goes between pieces at least half a space apart, and tracking on the character before each piece keeps the spacing; each object keeps its character styles, and the leftmost piece of each run its place and paint, as one undo step → {ids (the objects made, selected), combined (pieces merged into them)}",
|
||||
has_selection,
|
||||
combine_text
|
||||
),
|
||||
cmd!(
|
||||
"addon.cleanup.removeBreaks",
|
||||
"Remove Breaks",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{kind: \"line\"|\"paragraph\", ids?: [id…]} remove the forced line breaks (line) or paragraph returns (paragraph) in the characters selected with a Type tool, else in all the text of the selected type, as one undo step; a break between two words becomes a space → {ids, removed}",
|
||||
has_selection,
|
||||
remove_breaks
|
||||
),
|
||||
cmd!(
|
||||
"addon.cleanup.splitText",
|
||||
"Split Text at Cursor",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{} while a Type tool edits horizontal point or area type: the text before the selected characters, they and the text after become point type objects of their own (at a cursor: before and after it), each where its characters were, as one undo step; spaces at the ends of each piece go, and editing ends with the pieces selected → {ids}",
|
||||
editing_text,
|
||||
split_text
|
||||
),
|
||||
cmd!(
|
||||
"addon.cleanup.alignInPlace",
|
||||
"Set Alignment, Keep Position",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{align: \"left\"|\"center\"|\"right\", ids?: [id…] (default: the selection)} align every paragraph of each horizontal point type object so, moving the object so its longest line stays where it is (one line: the text doesn't move), as one undo step → {ids (the objects changed)}",
|
||||
has_selection,
|
||||
align_in_place
|
||||
),
|
||||
cmd!(
|
||||
"addon.cleanup.resetTextTransform",
|
||||
"Reset Text Transform",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{scale?: bool (false: the horizontal scale stays; true: it goes too, the object's and every character's), ids?: [id…] (default: the selection)} take the rotation, shear and reflection off each point type object, its size and the centre of its text staying, as one undo step → {ids (the objects changed)}",
|
||||
has_selection,
|
||||
reset_transform
|
||||
),
|
||||
cmd!(
|
||||
"addon.cleanup.replaceFonts",
|
||||
"Replace Missing Fonts…",
|
||||
["Object", "Plug-ins", "Artwork Cleanup"],
|
||||
None,
|
||||
"{font?: family (default: the default type font, Source Sans 3; any of its names)} set every character of the document's type whose font family isn't available in `font`, in the style it has closest to the one each had, as one undo step → {runs (style runs changed), font}",
|
||||
has_doc,
|
||||
replace_fonts
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
/// Enabled while a Type tool edits text.
|
||||
fn editing_text(s: &Session) -> std::result::Result<(), String> {
|
||||
match s.tool_options().get("editing") {
|
||||
Some(v) if !v.is_null() => Ok(()),
|
||||
_ => Err("Click in type with a Type tool to split it".into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// The type objects under `roots` (inside groups and layers, not live art) that can be edited.
|
||||
fn texts_under(d: &Document, roots: &[NodeId]) -> Result<Vec<NodeId>> {
|
||||
fn visit(n: &Node, out: &mut Vec<NodeId>) {
|
||||
match &n.kind {
|
||||
NodeKind::Text(_) => out.push(n.id),
|
||||
NodeKind::Group { children, .. } | NodeKind::Layer { children, .. } => children.iter().for_each(|c| visit(c, out)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut out = vec![];
|
||||
roots.iter().filter_map(|id| d.node(*id)).for_each(|n| visit(n, &mut out));
|
||||
let editable = d.editable();
|
||||
out.retain(|id| editable(*id));
|
||||
out.dedup();
|
||||
if out.len() > MAX_TEXTS {
|
||||
return Err(EngineError::Other("Too many type objects to change at once".into()));
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn text_of(d: &Document, id: NodeId) -> Option<&TextObject> {
|
||||
match &d.node(id)?.kind {
|
||||
NodeKind::Text(t) => Some(t),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn layout(t: &TextObject) -> TextLayout {
|
||||
vectorcraft_text::layout(FontDb::global(), t)
|
||||
}
|
||||
|
||||
/// Where the layout draws the character at `byte` (the one it starts in): its glyph's pen position.
|
||||
fn glyph_at(lay: &TextLayout, byte: usize) -> Option<Point> {
|
||||
let start = lay.glyphs.iter().filter(|g| g.len > 0 && g.byte <= byte).map(|g| g.byte).max()?;
|
||||
lay.glyphs.iter().find(|g| g.len > 0 && g.byte == start).map(|g| g.origin)
|
||||
}
|
||||
|
||||
/// The pen position of the glyph that starts at `byte`, if one does.
|
||||
fn glyph_starting(lay: &TextLayout, byte: usize) -> Option<Point> {
|
||||
lay.glyphs.iter().find(|g| g.len > 0 && g.byte == byte).map(|g| g.origin)
|
||||
}
|
||||
|
||||
/// The first glyph of line `l`, in text order.
|
||||
fn line_start(lay: &TextLayout, l: usize) -> Option<Point> {
|
||||
let line = lay.lines.get(l)?;
|
||||
let g = lay.glyphs.get(line.glyph_start..line.glyph_end)?.iter().filter(|g| g.len > 0).min_by_key(|g| g.byte)?;
|
||||
Some(g.origin)
|
||||
}
|
||||
|
||||
/// `a..b` of `text` without the white space at its ends; None when nothing else is left.
|
||||
fn trimmed(text: &str, a: usize, b: usize) -> Option<(usize, usize)> {
|
||||
let s = text.get(a..b)?;
|
||||
let start = a + (s.len() - s.trim_start().len());
|
||||
let end = a + s.trim_end().len();
|
||||
(start < end).then_some((start, end))
|
||||
}
|
||||
|
||||
/// Paragraph alignment as point type keeps it: justified lines align to their side.
|
||||
fn point_justify(j: Justify) -> Justify {
|
||||
match j {
|
||||
Justify::JustifyLeft | Justify::JustifyAll => Justify::Left,
|
||||
Justify::JustifyCenter => Justify::Center,
|
||||
Justify::JustifyRight => Justify::Right,
|
||||
j => j,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum By {
|
||||
Lines,
|
||||
Paragraphs,
|
||||
Words,
|
||||
Glyphs,
|
||||
}
|
||||
|
||||
/// A type object being cut into point type pieces: its text as drawn (Shrink Text to Fit's sizes
|
||||
/// taken in) and its layout.
|
||||
struct Source {
|
||||
t: TextObject,
|
||||
lay: TextLayout,
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl Source {
|
||||
/// Horizontal point or area type that isn't threaded and whose text all fits; None otherwise.
|
||||
fn of(d: &Document, id: NodeId) -> Option<Self> {
|
||||
let t = text_of(d, id)?;
|
||||
if t.vertical || matches!(t.kind, TextKind::OnPath { .. }) || d.text_threads.iter().any(|th| th.contains(&id)) {
|
||||
return None;
|
||||
}
|
||||
let lay = layout(t);
|
||||
// Text left out of a frame would be lost with it.
|
||||
if lay.overflow {
|
||||
return None;
|
||||
}
|
||||
let t = if (lay.fit_scale - 1.0).abs() > 1e-9 { vectorcraft_text::scaled(t, lay.fit_scale) } else { t.clone() };
|
||||
Some(Self { text: t.plain_text(), t, lay })
|
||||
}
|
||||
|
||||
/// The byte ranges of the pieces `by` cuts the text into.
|
||||
fn ranges(&self, by: By) -> Vec<(usize, usize)> {
|
||||
let text = &self.text;
|
||||
match by {
|
||||
By::Paragraphs => {
|
||||
let mut out = vec![];
|
||||
let mut a = 0;
|
||||
for (i, _) in text.match_indices('\n') {
|
||||
out.push((a, i));
|
||||
a = i + 1;
|
||||
}
|
||||
out.push((a, text.len()));
|
||||
out
|
||||
}
|
||||
By::Lines => self.lay.lines.iter().map(|l| (l.start, l.end)).collect(),
|
||||
By::Words => {
|
||||
let mut out = vec![];
|
||||
for l in &self.lay.lines {
|
||||
let Some(s) = text.get(l.start..l.end) else { continue };
|
||||
let mut word: Option<usize> = None;
|
||||
for (i, c) in s.char_indices() {
|
||||
match (c.is_whitespace(), word) {
|
||||
(true, Some(w)) => {
|
||||
out.push((l.start + w, l.start + i));
|
||||
word = None;
|
||||
}
|
||||
(false, None) => word = Some(i),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if let Some(w) = word {
|
||||
out.push((l.start + w, l.end));
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
By::Glyphs => {
|
||||
// One piece per cluster (a ligature's characters stay together).
|
||||
let mut clusters = std::collections::BTreeMap::new();
|
||||
for g in self.lay.glyphs.iter().filter(|g| g.len > 0) {
|
||||
let end = clusters.entry(g.byte).or_insert(g.byte + g.len);
|
||||
*end = (*end).max(g.byte + g.len);
|
||||
}
|
||||
clusters.into_iter().collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Point type holding bytes `a..b` (white space at its ends left out) where they were drawn.
|
||||
/// Lines the layout wrapped end in a forced line break; `lists` keeps bulleted paragraphs'
|
||||
/// bullets where the piece starts its paragraph.
|
||||
fn piece(&self, (a, b): (usize, usize), lists: bool) -> Option<TextObject> {
|
||||
let (a, b) = trimmed(&self.text, a, b)?;
|
||||
let mut p = TextObject::point(Point::ZERO, "", CharStyle::default());
|
||||
p.runs = edit::slice_runs(&self.t.runs, a, b);
|
||||
p.xf = self.t.xf;
|
||||
p.optical_margin = self.t.optical_margin;
|
||||
p.system_layout = self.t.system_layout;
|
||||
p.fractional_widths = self.t.fractional_widths;
|
||||
p.ruby =
|
||||
self.t.ruby.iter().filter(|r| a <= r.start && r.end <= b).map(|r| RubySpan { start: r.start - a, end: r.end - a, ..r.clone() }).collect();
|
||||
// The paragraphs it holds, with their styles; the first keeps its bullet only from its start.
|
||||
let starts_para = self.text.get(..a).is_some_and(|s| s.rsplit('\n').next().is_some_and(|line| line.trim().is_empty()));
|
||||
let styles = self.t.paragraph_styles();
|
||||
let mut paras: Vec<ParaStyle> = styles.get(self.t.paragraphs_in(a, b))?.to_vec();
|
||||
for (i, para) in paras.iter_mut().enumerate() {
|
||||
para.justify = point_justify(para.justify);
|
||||
if !(lists && (i > 0 || starts_para) && para.list.as_ref().is_some_and(|l| l.number.is_none())) {
|
||||
para.list = None;
|
||||
}
|
||||
}
|
||||
p.set_paragraph_styles(paras);
|
||||
// Lines the layout wrapped end in a forced line break, in place of the spaces they ended in.
|
||||
let mut wraps = vec![];
|
||||
for next in self.lay.lines.iter().skip(1).filter(|l| a < l.start && l.start < b) {
|
||||
let content = self.text.get(..next.start)?.trim_end_matches([' ', '\t']);
|
||||
// A line that ends in a break of its own keeps it.
|
||||
if !content.ends_with(['\n', '\u{2028}']) {
|
||||
wraps.push((content.len().max(a) - a, next.start - a));
|
||||
}
|
||||
}
|
||||
for &(s, e) in wraps.iter().rev() {
|
||||
edit::replace_range(&mut p.runs, s, e, "\u{2028}");
|
||||
p.ruby_after_replace(s, e, '\u{2028}'.len_utf8());
|
||||
}
|
||||
self.place(&mut p, a)?;
|
||||
Some(p)
|
||||
}
|
||||
|
||||
/// Move `p` (cut from byte `a`) so the glyph of its first character lands where it was drawn.
|
||||
/// A piece of several lines that starts inside a left-aligned line takes a first-line indent,
|
||||
/// so its later lines stay where they were too.
|
||||
fn place(&self, p: &mut TextObject, a: usize) -> Option<()> {
|
||||
let lay = layout(p);
|
||||
let mut shift: Vec2 = glyph_at(&self.lay, a)? - glyph_at(&lay, 0)?;
|
||||
let first = self.lay.lines.iter().rposition(|l| l.start <= a);
|
||||
if let (Some(now), Some(was)) = (line_start(&lay, 1), first.and_then(|l| line_start(&self.lay, l + 1))) {
|
||||
let off = was.x - (now.x + shift.x);
|
||||
let left = match p.para.justify {
|
||||
Justify::Left => true,
|
||||
Justify::Auto => lay.lines.first().is_some_and(|l| !l.rtl),
|
||||
_ => false,
|
||||
};
|
||||
if left && off.abs() > 1e-6 {
|
||||
p.edit_paras(Some(0..1), |para| para.first_line_indent -= off);
|
||||
shift.x += off;
|
||||
}
|
||||
}
|
||||
p.xf = self.t.xf * Affine::translate(shift);
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Put each object of `items` (id, the node, its pieces) out of the document, its pieces in its
|
||||
/// place, as one undo step labelled `label`, the pieces selected → their ids.
|
||||
fn replace_with_pieces(s: &mut Session, label: &str, items: Vec<(NodeId, Node, Vec<TextObject>)>) -> Result<Vec<u64>> {
|
||||
s.edit(label, |d, sel| {
|
||||
let (mut made, mut places) = (vec![], vec![]);
|
||||
for (id, mut node, pieces) in items {
|
||||
// A light template: the pieces take its paint and attributes, not its text.
|
||||
node.kind = NodeKind::Text(Box::new(TextObject::point(Point::ZERO, "", CharStyle::default())));
|
||||
let nodes: Vec<Node> = pieces
|
||||
.into_iter()
|
||||
.map(|mut t| {
|
||||
refresh_bounds(&mut t);
|
||||
let mut n = d.reid(&node);
|
||||
n.kind = NodeKind::Text(Box::new(t));
|
||||
n
|
||||
})
|
||||
.collect();
|
||||
made.extend(nodes.iter().map(|n| n.id));
|
||||
places.push((id, nodes));
|
||||
}
|
||||
d.insert_beside(places, true)?;
|
||||
sel.set(made.iter().copied());
|
||||
Ok(made.iter().map(|i| i.0).collect())
|
||||
})
|
||||
}
|
||||
|
||||
fn ids_json(ids: &[NodeId]) -> Vec<u64> {
|
||||
ids.iter().map(|i| i.0).collect()
|
||||
}
|
||||
|
||||
fn break_text(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.cleanup.breakText";
|
||||
let by = match text_param(p, "by", C)?.unwrap_or("lines") {
|
||||
"lines" => By::Lines,
|
||||
"paragraphs" => By::Paragraphs,
|
||||
"words" => By::Words,
|
||||
"glyphs" => By::Glyphs,
|
||||
other => return Err(bad(C, format!("`by` must be lines, paragraphs, words or glyphs, not {other:?}"))),
|
||||
};
|
||||
let d = &s.doc()?.doc;
|
||||
let (mut items, mut skipped, mut count) = (vec![], vec![], 0);
|
||||
for id in texts_under(d, &checked_ids_or_selection(s, p, C)?)? {
|
||||
let (Some(src), Some(node)) = (Source::of(d, id), d.node(id)) else {
|
||||
skipped.push(id);
|
||||
continue;
|
||||
};
|
||||
let ranges = src.ranges(by);
|
||||
count += ranges.len();
|
||||
if count > MAX_PIECES {
|
||||
return Err(EngineError::Other("Too many pieces to make at once".into()));
|
||||
}
|
||||
let pieces: Vec<TextObject> = ranges.into_iter().filter_map(|r| src.piece(r, by == By::Paragraphs)).collect();
|
||||
if pieces.is_empty() {
|
||||
skipped.push(id);
|
||||
} else {
|
||||
items.push((id, node.clone(), pieces));
|
||||
}
|
||||
}
|
||||
if items.is_empty() {
|
||||
return Err(EngineError::Other("Select horizontal point or area type whose text fits".into()));
|
||||
}
|
||||
let ids = replace_with_pieces(s, "Break Text", items)?;
|
||||
Ok(json!({ "ids": ids, "skipped": ids_json(&skipped) }))
|
||||
}
|
||||
|
||||
fn split_text(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
let Some((id, a, b)) = editing_range(s)? else {
|
||||
return Err(EngineError::Other("Click in type with a Type tool to split it".into()));
|
||||
};
|
||||
let d = &s.doc()?.doc;
|
||||
let (Some(src), Some(node)) = (Source::of(d, id), d.node(id).filter(|_| d.is_editable(id))) else {
|
||||
return Err(EngineError::Other("Select horizontal point or area type whose text fits".into()));
|
||||
};
|
||||
let text = &src.text;
|
||||
let (a, b) = (edit::floor_char(text, a.min(b)), edit::floor_char(text, a.max(b)));
|
||||
let cuts: Vec<(usize, usize)> = if a == b { vec![(0, a), (a, text.len())] } else { vec![(0, a), (a, b), (b, text.len())] };
|
||||
let pieces: Vec<TextObject> = cuts.into_iter().filter_map(|r| src.piece(r, true)).collect();
|
||||
if pieces.len() < 2 {
|
||||
return Err(EngineError::Other("Nothing to split at the cursor".into()));
|
||||
}
|
||||
let node = node.clone();
|
||||
let ids = replace_with_pieces(s, "Split Text at Cursor", vec![(id, node, pieces)])?;
|
||||
// The text edited is gone: the pieces stay selected.
|
||||
s.set_tool_option("stopEditing", &Value::Bool(true));
|
||||
Ok(json!({ "ids": ids }))
|
||||
}
|
||||
|
||||
/// One piece of point type Combine Point Text takes: its text with its object's scale taken into
|
||||
/// its characters, and where it starts and ends along its line in the frame of its turn and shear.
|
||||
struct Piece {
|
||||
id: NodeId,
|
||||
t: TextObject,
|
||||
/// The object's turn and shear (`xf` without its move).
|
||||
turn: [f64; 4],
|
||||
/// Where its first character's glyph starts on its baseline, in that frame.
|
||||
at: Point,
|
||||
/// Where its last glyph ends along the line, in that frame.
|
||||
end: f64,
|
||||
/// Its first character's size.
|
||||
size: f64,
|
||||
/// Each character's pen position from the first's (byte, x), as it lays out alone.
|
||||
pens: Vec<(usize, f64)>,
|
||||
}
|
||||
|
||||
impl Piece {
|
||||
fn of(d: &Document, id: NodeId) -> Option<(Self, &Node)> {
|
||||
let node = d.node(id)?;
|
||||
let NodeKind::Text(t) = &node.kind else { return None };
|
||||
let text = t.plain_text();
|
||||
if t.vertical || !matches!(t.kind, TextKind::Point) || text.trim().is_empty() || text.contains(['\n', '\u{2028}']) {
|
||||
return None;
|
||||
}
|
||||
let mut t = (**t).clone();
|
||||
t.scale_text_attributes();
|
||||
t.style_scale()?;
|
||||
let lay = layout(&t);
|
||||
let line = lay.lines.first().filter(|l| !l.rtl && lay.lines.len() == 1)?;
|
||||
let first = glyph_at(&lay, 0)?;
|
||||
// The first glyph of each cluster (a mark drawn over it shares its byte).
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
let pens = lay.glyphs.iter().filter(|g| g.len > 0 && seen.insert(g.byte)).map(|g| (g.byte, g.origin.x - first.x)).collect();
|
||||
let end = lay.glyphs.iter().map(|g| g.origin.x + g.advance).fold(first.x, f64::max) - first.x;
|
||||
let [a, b, c, dd, _, _] = t.xf.as_coeffs();
|
||||
let turn = Affine::new([a, b, c, dd, 0.0, 0.0]);
|
||||
let at = turn.inverse() * (t.xf * Point::new(first.x, line.baseline));
|
||||
let size = t.runs.first()?.style.size;
|
||||
if !(at.x.is_finite() && at.y.is_finite() && size > 0.0) {
|
||||
return None;
|
||||
}
|
||||
Some((Self { id, t, turn: [a, b, c, dd], at, end: at.x + end, size, pens }, node))
|
||||
}
|
||||
|
||||
/// Whether `o` is turned and sheared alike.
|
||||
fn turned_like(&self, o: &Piece) -> bool {
|
||||
self.turn.iter().zip(&o.turn).all(|(x, y)| (x - y).abs() <= 1e-6 * x.abs().max(y.abs()).max(1.0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether two objects look alike apart from their text (paint, opacity, blending, effects).
|
||||
fn same_look(a: &Node, b: &Node) -> bool {
|
||||
a.appearance == b.appearance
|
||||
&& a.opacity == b.opacity
|
||||
&& a.blend == b.blend
|
||||
&& a.isolate == b.isolate
|
||||
&& a.knockout == b.knockout
|
||||
&& a.extras == b.extras
|
||||
}
|
||||
|
||||
/// How wide a space of `style` is.
|
||||
fn space_width(style: &CharStyle) -> f64 {
|
||||
let probe = TextObject::point(Point::ZERO, " ", CharStyle { tracking: 0.0, ..style.clone() });
|
||||
layout(&probe).glyphs.first().map_or(style.size * 0.25, |g| g.advance)
|
||||
}
|
||||
|
||||
/// `chain` (pieces left to right on one line) as one point type object whose glyphs land where
|
||||
/// theirs were, or the index of the first piece that can't join the ones before it so.
|
||||
fn merge(chain: &[&Piece]) -> std::result::Result<TextObject, usize> {
|
||||
let Some(first) = chain.first() else { return Err(0) };
|
||||
let mut runs = vec![];
|
||||
// Each piece's first byte, and the byte range of the character before it (whose tracking sets
|
||||
// the gap).
|
||||
let (mut starts, mut before) = (vec![], vec![]);
|
||||
let mut text = String::new();
|
||||
for (k, p) in chain.iter().enumerate() {
|
||||
if let Some(prev) = k.checked_sub(1).and_then(|i| chain.get(i)) {
|
||||
let starts_blank = p.t.plain_text().starts_with(char::is_whitespace);
|
||||
let last = prev.t.runs.iter().rev().find(|r| !r.text.is_empty()).map(|r| r.style.clone()).unwrap_or_default();
|
||||
if !text.ends_with(char::is_whitespace) && !starts_blank && p.at.x - prev.end >= 0.5 * space_width(&last) {
|
||||
runs.push(vectorcraft_doc::TextRun::new(" ", last));
|
||||
text.push(' ');
|
||||
}
|
||||
let c = text.chars().next_back().map_or(1, char::len_utf8);
|
||||
before.push((text.len() - c, text.len()));
|
||||
}
|
||||
starts.push(text.len());
|
||||
// Baselines a little apart: the difference is baseline shift (up is positive).
|
||||
let shift = first.at.y - p.at.y;
|
||||
for r in &p.t.runs {
|
||||
let mut r = r.clone();
|
||||
r.style.baseline_shift += shift;
|
||||
text.push_str(&r.text);
|
||||
runs.push(r);
|
||||
}
|
||||
}
|
||||
let mut m = first.t.clone();
|
||||
m.set_all_paras(ParaStyle { justify: Justify::Left, ..first.t.para.clone() });
|
||||
let [a, b, c, d] = first.turn;
|
||||
let base = Affine::new([a, b, c, d, 0.0, 0.0]) * Affine::translate(first.at.to_vec2());
|
||||
m.xf = base;
|
||||
m.runs = runs;
|
||||
m.ruby.clear();
|
||||
// Tracking after the character before each piece, until each lands where it was.
|
||||
let targets: Vec<f64> = chain.iter().map(|p| p.at.x - first.at.x).collect();
|
||||
let mut lay = layout(&m);
|
||||
for _ in 0..4 {
|
||||
// A piece whose first character joins the one before it (a ligature) can't keep its place.
|
||||
let xs: Vec<f64> = match starts.iter().enumerate().map(|(k, b)| glyph_starting(&lay, *b).map(|g| g.x).ok_or(k)).collect() {
|
||||
Ok(xs) => xs,
|
||||
Err(k) => return Err(k.max(1)),
|
||||
};
|
||||
let x0 = xs.first().copied().unwrap_or(0.0);
|
||||
let off: Vec<f64> = targets.iter().zip(&xs).map(|(t, x)| t - (x - x0)).collect();
|
||||
if off.iter().all(|o| o.abs() <= TOLERANCE * 0.5) {
|
||||
break;
|
||||
}
|
||||
// Moving piece k moves those after it as far.
|
||||
for (k, w) in off.windows(2).enumerate() {
|
||||
let (delta, Some(&(s, e))) = (w[1] - w[0], before.get(k)) else { continue };
|
||||
if delta.abs() > 1e-9 {
|
||||
edit::style_range(&mut m.runs, s, e, |st| st.tracking += delta / st.size.max(1e-6) * 1000.0);
|
||||
if !TRACKING.contains(&edit::style_at(&m.runs, s).tracking) {
|
||||
return Err(k + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
lay = layout(&m);
|
||||
}
|
||||
// Every glyph where it was, within the tolerance; else the run ends before the piece that moved.
|
||||
let x0 = glyph_starting(&lay, 0).map_or(0.0, |g| g.x);
|
||||
for (k, p) in chain.iter().enumerate() {
|
||||
let (Some(&start), Some(&target)) = (starts.get(k), targets.get(k)) else { return Err(k.max(1)) };
|
||||
let moved = p.pens.iter().any(|(byte, x)| glyph_starting(&lay, start + byte).is_none_or(|g| (g.x - x0 - target - x).abs() > TOLERANCE));
|
||||
if moved {
|
||||
return Err(k.max(1));
|
||||
}
|
||||
}
|
||||
m.xf = base * Affine::translate((-x0, 0.0));
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
fn combine_text(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.cleanup.combineText";
|
||||
let d = &s.doc()?.doc;
|
||||
let mut pieces: Vec<(Piece, &Node)> =
|
||||
texts_under(d, &checked_ids_or_selection(s, p, C)?)?.into_iter().filter_map(|id| Piece::of(d, id)).collect();
|
||||
// Lines: pieces turned alike and looking alike, by baseline, then left to right.
|
||||
pieces.sort_by(|x, y| x.0.at.y.total_cmp(&y.0.at.y).then(x.0.at.x.total_cmp(&y.0.at.x)));
|
||||
let mut lines: Vec<Vec<(&Piece, &Node)>> = vec![];
|
||||
for (piece, node) in &pieces {
|
||||
let fits = |l: &Vec<(&Piece, &Node)>| {
|
||||
l.first()
|
||||
.is_some_and(|(f, n)| f.turned_like(piece) && same_look(n, node) && (f.at.y - piece.at.y).abs() <= SAME_LINE * f.size.min(piece.size))
|
||||
};
|
||||
match lines.iter_mut().find(|l| fits(l)) {
|
||||
Some(l) => l.push((piece, node)),
|
||||
None => lines.push(vec![(piece, node)]),
|
||||
}
|
||||
}
|
||||
// Runs along each line: a wide gap or an overlap starts another.
|
||||
let mut chains: Vec<Vec<&Piece>> = vec![];
|
||||
for mut l in lines {
|
||||
l.sort_by(|x, y| x.0.at.x.total_cmp(&y.0.at.x));
|
||||
let mut chain: Vec<&Piece> = vec![];
|
||||
for (piece, _) in l {
|
||||
if let Some(prev) = chain.last() {
|
||||
let gap = piece.at.x - prev.end;
|
||||
if gap > MAX_GAP * prev.size || gap < -MAX_OVERLAP * prev.size {
|
||||
chains.push(std::mem::take(&mut chain));
|
||||
}
|
||||
}
|
||||
chain.push(piece);
|
||||
}
|
||||
chains.push(chain);
|
||||
}
|
||||
// Each run as one object, or as several where a piece can't keep its place joined.
|
||||
let mut made: Vec<(NodeId, TextObject, Vec<NodeId>)> = vec![];
|
||||
let mut tries = 0;
|
||||
'chains: for chain in chains {
|
||||
let mut rest: &[&Piece] = &chain;
|
||||
while rest.len() > 1 {
|
||||
let mut upto = rest.len();
|
||||
while let Some(part) = rest.get(..upto) {
|
||||
tries += part.len();
|
||||
if tries > MAX_JOIN_TRIES {
|
||||
break 'chains;
|
||||
}
|
||||
match merge(part) {
|
||||
Ok(m) => {
|
||||
let gone = part.iter().skip(1).map(|p| p.id).collect();
|
||||
if let Some(first) = part.first() {
|
||||
made.push((first.id, m, gone));
|
||||
}
|
||||
break;
|
||||
}
|
||||
// A run of one stays as it is.
|
||||
Err(k) if k <= 1 => {
|
||||
upto = 1;
|
||||
break;
|
||||
}
|
||||
Err(k) => upto = k,
|
||||
}
|
||||
}
|
||||
rest = rest.get(upto.max(1)..).unwrap_or_default();
|
||||
}
|
||||
}
|
||||
if made.is_empty() {
|
||||
return Err(EngineError::Other("Select two or more one-line point type objects on one baseline to combine".into()));
|
||||
}
|
||||
let combined: usize = made.iter().map(|m| m.2.len()).sum();
|
||||
let ids: Vec<u64> = made.iter().map(|m| m.0.0).collect();
|
||||
s.edit("Combine Point Text", |d, sel| {
|
||||
let mut gone = vec![];
|
||||
for (id, mut t, others) in made {
|
||||
refresh_bounds(&mut t);
|
||||
if let Some(n) = d.node_mut(id) {
|
||||
n.kind = NodeKind::Text(Box::new(t));
|
||||
}
|
||||
gone.extend(others);
|
||||
}
|
||||
d.remove_many(&gone)?;
|
||||
sel.set(ids.iter().map(|i| NodeId(*i)));
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(json!({ "ids": ids, "combined": combined }))
|
||||
}
|
||||
|
||||
/// Remove the breaks `brk` in bytes `a..b` of `t`: one between two words becomes a space → how many
|
||||
/// went.
|
||||
fn strip_breaks(t: &mut TextObject, a: usize, b: usize, brk: char) -> usize {
|
||||
let text = t.plain_text();
|
||||
let (a, b) = (edit::floor_char(&text, a), edit::floor_char(&text, b));
|
||||
let Some(range) = text.get(a..b) else { return 0 };
|
||||
let mut prev = text.get(..a).and_then(|s| s.chars().next_back());
|
||||
let mut cuts = vec![];
|
||||
for (i, c) in range.char_indices() {
|
||||
let at = a + i;
|
||||
if c != brk {
|
||||
prev = Some(c);
|
||||
continue;
|
||||
}
|
||||
// The next character left: past the breaks that go too.
|
||||
let after = at + c.len_utf8();
|
||||
let next = text.get(after..).and_then(|rest| rest.char_indices().find(|(j, n)| *n != brk || after + j >= b).map(|(_, n)| n));
|
||||
let space = prev.is_some_and(|p| !p.is_whitespace()) && next.is_some_and(|n| !n.is_whitespace());
|
||||
if space {
|
||||
prev = Some(' ');
|
||||
}
|
||||
cuts.push((at, space));
|
||||
}
|
||||
for &(at, space) in cuts.iter().rev() {
|
||||
let insert = if space { " " } else { "" };
|
||||
let end = at + brk.len_utf8();
|
||||
t.splice_paras(at, end, insert);
|
||||
edit::replace_range(&mut t.runs, at, end, insert);
|
||||
t.ruby_after_replace(at, end, insert.len());
|
||||
}
|
||||
cuts.len()
|
||||
}
|
||||
|
||||
fn remove_breaks(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.cleanup.removeBreaks";
|
||||
let (brk, label, none) = match text_param(p, "kind", C)? {
|
||||
Some("line") => ('\u{2028}', "Remove Line Breaks", "No line breaks to remove"),
|
||||
Some("paragraph") => ('\n', "Remove Paragraph Breaks", "No paragraph breaks to remove"),
|
||||
Some(other) => return Err(bad(C, format!("`kind` must be \"line\" or \"paragraph\", not {other:?}"))),
|
||||
None => return Err(bad(C, "missing `kind`")),
|
||||
};
|
||||
// The characters a Type tool has selected, else all the text of the selected type.
|
||||
let editing = if p.get("ids").is_some() { None } else { editing_range(s)?.filter(|(_, a, b)| a != b) };
|
||||
let d = &s.doc()?.doc;
|
||||
let targets: Vec<(NodeId, usize, usize)> = match editing {
|
||||
Some((id, a, b)) => vec![(id, a.min(b), a.max(b))].into_iter().filter(|(id, ..)| d.is_editable(*id)).collect(),
|
||||
None => texts_under(d, &checked_ids_or_selection(s, p, C)?)?.into_iter().map(|id| (id, 0, usize::MAX)).collect(),
|
||||
};
|
||||
let count: usize = targets
|
||||
.iter()
|
||||
.filter_map(|(id, a, b)| {
|
||||
let text = text_of(d, *id)?.plain_text();
|
||||
let (a, b) = (edit::floor_char(&text, *a), edit::floor_char(&text, *b));
|
||||
Some(text.get(a..b)?.matches(brk).count())
|
||||
})
|
||||
.sum();
|
||||
if count == 0 {
|
||||
return Err(EngineError::Other(none.into()));
|
||||
}
|
||||
if count > MAX_BREAKS {
|
||||
return Err(EngineError::Other("Too many breaks to remove at once".into()));
|
||||
}
|
||||
let (removed, ids) = s.edit(label, |d, _| {
|
||||
let (mut removed, mut ids) = (0, vec![]);
|
||||
for (id, a, b) in targets {
|
||||
let Some(NodeKind::Text(t)) = d.node_mut(id).map(|n| &mut n.kind) else { continue };
|
||||
let n = strip_breaks(t, a, b, brk);
|
||||
if n > 0 {
|
||||
refresh_bounds(t);
|
||||
removed += n;
|
||||
ids.push(id.0);
|
||||
}
|
||||
}
|
||||
Ok((removed, ids))
|
||||
})?;
|
||||
Ok(json!({ "ids": ids, "removed": removed }))
|
||||
}
|
||||
|
||||
/// Horizontal point type among the objects `p` names.
|
||||
fn point_texts(s: &Session, p: &Value, cmd: &str) -> Result<Vec<NodeId>> {
|
||||
let d = &s.doc()?.doc;
|
||||
let ids: Vec<NodeId> = texts_under(d, &checked_ids_or_selection(s, p, cmd)?)?
|
||||
.into_iter()
|
||||
.filter(|id| text_of(d, *id).is_some_and(|t| matches!(t.kind, TextKind::Point)))
|
||||
.collect();
|
||||
if ids.is_empty() {
|
||||
return Err(EngineError::Other("Select point type".into()));
|
||||
}
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
/// Replace the type objects of `changed` as one undo step labelled `label` → their ids.
|
||||
fn set_texts(s: &mut Session, label: &str, changed: Vec<(NodeId, TextObject)>, reset_angle: bool) -> Result<Value> {
|
||||
let ids: Vec<u64> = changed.iter().map(|c| c.0.0).collect();
|
||||
s.edit(label, |d, _| {
|
||||
for (id, mut t) in changed {
|
||||
refresh_bounds(&mut t);
|
||||
if let Some(n) = d.node_mut(id) {
|
||||
n.kind = NodeKind::Text(Box::new(t));
|
||||
if reset_angle {
|
||||
n.bbox_angle = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(json!({ "ids": ids }))
|
||||
}
|
||||
|
||||
fn align_in_place(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.cleanup.alignInPlace";
|
||||
let justify = match text_param(p, "align", C)? {
|
||||
Some("left") => Justify::Left,
|
||||
Some("center") => Justify::Center,
|
||||
Some("right") => Justify::Right,
|
||||
Some(other) => return Err(bad(C, format!("`align` must be \"left\", \"center\" or \"right\", not {other:?}"))),
|
||||
None => return Err(bad(C, "missing `align`")),
|
||||
};
|
||||
let ids = point_texts(s, p, C)?;
|
||||
let d = &s.doc()?.doc;
|
||||
let mut changed = vec![];
|
||||
for id in ids {
|
||||
let Some(t) = text_of(d, id).filter(|t| !t.vertical && t.para_styles().any(|para| para.justify != justify)) else { continue };
|
||||
let was = layout(t);
|
||||
// The longest line stays where it is.
|
||||
let Some((i, line)) = was.lines.iter().enumerate().max_by(|a, b| (a.1.x1 - a.1.x0).total_cmp(&(b.1.x1 - b.1.x0))) else { continue };
|
||||
let mut n = t.clone();
|
||||
n.edit_paras(None, |para| para.justify = justify);
|
||||
let Some(now) = layout(&n).lines.get(i).map(|l| l.x0) else { continue };
|
||||
n.xf *= Affine::translate((line.x0 - now, 0.0));
|
||||
changed.push((id, n));
|
||||
}
|
||||
if changed.is_empty() {
|
||||
return Err(EngineError::Other("The point type is aligned that way already".into()));
|
||||
}
|
||||
set_texts(s, "Set Alignment, Keep Position", changed, false)
|
||||
}
|
||||
|
||||
fn reset_transform(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.cleanup.resetTextTransform";
|
||||
let scale = switch_or(p, "scale", false, C)?;
|
||||
let ids = point_texts(s, p, C)?;
|
||||
let d = &s.doc()?.doc;
|
||||
let mut changed = vec![];
|
||||
for id in ids {
|
||||
let Some(t) = text_of(d, id) else { continue };
|
||||
let [a, b, c, dd, _, _] = t.xf.as_coeffs();
|
||||
// The object's own axes: its width along its baseline, and its height square to it.
|
||||
let (sx, det) = (a.hypot(b), a * dd - b * c);
|
||||
if !(sx > 1e-12 && sx.is_finite() && det.is_finite() && det.abs() > 1e-12) {
|
||||
continue;
|
||||
}
|
||||
let sy = det.abs() / sx;
|
||||
let unscaled = |t: &TextObject| t.runs.iter().all(|r| r.style.h_scale == 100.0);
|
||||
let upright = b.abs() <= 1e-9 * sx && c.abs() <= 1e-9 * sy && a > 0.0 && dd > 0.0;
|
||||
if upright && (!scale || ((sx - sy).abs() <= 1e-9 * sy && unscaled(t))) {
|
||||
continue;
|
||||
}
|
||||
let mut n = t.clone();
|
||||
let w = if scale {
|
||||
n.runs.iter_mut().for_each(|r| r.style.h_scale = 100.0);
|
||||
sy
|
||||
} else {
|
||||
sx
|
||||
};
|
||||
// The centre of the text stays where it is.
|
||||
let centre = t.xf * layout(t).bounds.center();
|
||||
let turn = Affine::scale_non_uniform(w, sy);
|
||||
let now = turn * layout(&n).bounds.center();
|
||||
n.xf = Affine::translate(centre - now) * turn;
|
||||
changed.push((id, n));
|
||||
}
|
||||
if changed.is_empty() {
|
||||
return Err(EngineError::Other("The point type has no transform to reset".into()));
|
||||
}
|
||||
set_texts(s, "Reset Text Transform", changed, true)
|
||||
}
|
||||
|
||||
fn replace_fonts(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "addon.cleanup.replaceFonts";
|
||||
let default = CharStyle::default().font_family;
|
||||
let wanted = text_param(p, "font", C)?.filter(|f| !f.trim().is_empty()).unwrap_or(&default);
|
||||
let db = FontDb::global();
|
||||
// Any name of the family is stored as its own name.
|
||||
let family = match db.resolve(wanted, "Regular") {
|
||||
Some((f, m)) if m != FontMatch::Missing => f.family.clone(),
|
||||
_ => return Err(bad(C, "the replacement font is not available")),
|
||||
};
|
||||
let missing = |st: &CharStyle| db.resolve(&st.font_family, &st.font_style).is_none_or(|(_, m)| m == FontMatch::Missing);
|
||||
let d = &s.doc()?.doc;
|
||||
let mut ids = vec![];
|
||||
for l in &d.layers {
|
||||
l.walk(&mut |n| {
|
||||
if let NodeKind::Text(t) = &n.kind
|
||||
&& t.runs.iter().any(|r| missing(&r.style))
|
||||
{
|
||||
ids.push(n.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
if ids.is_empty() {
|
||||
return Err(EngineError::Other("No fonts are missing".into()));
|
||||
}
|
||||
let runs = s.edit("Replace Missing Fonts", |d, _| {
|
||||
let mut runs = 0;
|
||||
for id in &ids {
|
||||
let Some(NodeKind::Text(t)) = d.node_mut(*id).map(|n| &mut n.kind) else { continue };
|
||||
for r in t.runs.iter_mut().filter(|r| missing(&r.style)) {
|
||||
// The style the font has closest to the one the character had.
|
||||
r.style.font_style = db.face(&family, &r.style.font_style).map_or_else(|| r.style.font_style.clone(), |f| f.style.clone());
|
||||
r.style.font_family = family.clone();
|
||||
r.style.font_version = None;
|
||||
r.style.font_axes.clear();
|
||||
runs += 1;
|
||||
}
|
||||
edit::normalize(&mut t.runs);
|
||||
refresh_bounds(t);
|
||||
}
|
||||
Ok(runs)
|
||||
})?;
|
||||
Ok(json!({ "runs": runs, "font": family }))
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
//! Artwork Cleanup's text tools: pieces stay where their glyphs were drawn and keep their styles,
|
||||
//! each command is one undo step and refuses cleanly when there is nothing to do.
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::{Justify, NodeId, NodeKind, TextKind, TextObject};
|
||||
use vectorcraft_geom::Point;
|
||||
|
||||
use crate::{EngineError, Session};
|
||||
|
||||
fn session() -> Session {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 600, "height": 400})).unwrap();
|
||||
s
|
||||
}
|
||||
|
||||
fn text(s: &mut Session, p: Value) -> NodeId {
|
||||
NodeId(s.execute("text.create", &p).unwrap()["id"].as_u64().unwrap())
|
||||
}
|
||||
|
||||
fn obj(s: &Session, id: NodeId) -> TextObject {
|
||||
match &s.doc().unwrap().doc.node(id).unwrap().kind {
|
||||
NodeKind::Text(t) => (**t).clone(),
|
||||
_ => panic!("not text"),
|
||||
}
|
||||
}
|
||||
|
||||
fn select(s: &mut Session, ids: &[NodeId]) {
|
||||
s.select(|_, sel| sel.set(ids.iter().copied())).unwrap();
|
||||
}
|
||||
|
||||
fn ids(v: &Value) -> Vec<NodeId> {
|
||||
v["ids"].as_array().unwrap().iter().map(|i| NodeId(i.as_u64().unwrap())).collect()
|
||||
}
|
||||
|
||||
/// Each drawn character of `ids` (spaces left out) with where its glyph starts on the page, in
|
||||
/// the order of the objects and their text.
|
||||
fn glyphs(s: &Session, ids: &[NodeId]) -> Vec<(char, Point)> {
|
||||
let mut out = vec![];
|
||||
for id in ids {
|
||||
let t = obj(s, *id);
|
||||
let text = t.plain_text();
|
||||
let lay = vectorcraft_text::layout(vectorcraft_text::FontDb::global(), &t);
|
||||
let mut gs: Vec<_> = lay.glyphs.iter().filter(|g| g.len > 0).collect();
|
||||
gs.sort_by_key(|g| g.byte);
|
||||
gs.dedup_by_key(|g| g.byte);
|
||||
for g in gs {
|
||||
let c = text[g.byte..].chars().next().unwrap();
|
||||
if !c.is_whitespace() {
|
||||
out.push((c, t.xf * g.origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn assert_same_places(was: &[(char, Point)], now: &[(char, Point)]) {
|
||||
assert_eq!(was.iter().map(|g| g.0).collect::<String>(), now.iter().map(|g| g.0).collect::<String>());
|
||||
for (a, b) in was.iter().zip(now) {
|
||||
assert!((a.1 - b.1).hypot() < 0.02, "{:?} moved to {:?}", a, b);
|
||||
}
|
||||
}
|
||||
|
||||
fn undo_steps(s: &Session) -> usize {
|
||||
s.doc().unwrap().history.undo.len()
|
||||
}
|
||||
|
||||
fn doc_json(s: &Session) -> String {
|
||||
serde_json::to_string(&s.doc().unwrap().doc.layers).unwrap()
|
||||
}
|
||||
|
||||
fn other(r: Result<Value, EngineError>) -> String {
|
||||
match r {
|
||||
Err(EngineError::Other(m)) => m,
|
||||
r => panic!("expected a refusal, got {r:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn break_into_words_keeps_places_styles_and_is_one_step() {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 40, "y": 100, "text": "Hello big World", "size": 24}));
|
||||
s.execute("text.setRangeStyle", &json!({"id": id.0, "start": 6, "end": 9, "size": 36, "tracking": 50})).unwrap();
|
||||
let rotated = text(&mut s, json!({"x": 300, "y": 200, "text": "Turned words", "size": 18, "rotation": 30}));
|
||||
let was = glyphs(&s, &[id, rotated]);
|
||||
let before = doc_json(&s);
|
||||
let steps = undo_steps(&s);
|
||||
select(&mut s, &[id, rotated]);
|
||||
let r = s.execute("addon.cleanup.breakText", &json!({"by": "words"})).unwrap();
|
||||
let pieces = ids(&r);
|
||||
assert_eq!(pieces.len(), 5);
|
||||
assert_eq!(undo_steps(&s), steps + 1);
|
||||
assert_eq!(s.doc().unwrap().selection.objects.len(), 5, "the pieces are selected");
|
||||
let texts: Vec<String> = pieces.iter().map(|p| obj(&s, *p).plain_text()).collect();
|
||||
assert_eq!(texts, ["Hello", "big", "World", "Turned", "words"]);
|
||||
assert_same_places(&was, &glyphs(&s, &pieces));
|
||||
let big = obj(&s, pieces[1]);
|
||||
assert!(matches!(big.kind, TextKind::Point));
|
||||
assert_eq!((big.runs[0].style.size, big.runs[0].style.tracking), (36.0, 50.0));
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(doc_json(&s), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn break_area_type_into_lines_paragraphs_and_glyphs() {
|
||||
for (by, count) in [("lines", None), ("paragraphs", Some(2)), ("glyphs", None)] {
|
||||
let mut s = session();
|
||||
let id = text(
|
||||
&mut s,
|
||||
json!({"x": 40, "y": 40, "text": "A paragraph long enough to wrap in its frame\nSecond one", "size": 14, "area": {"width": 140, "height": 200}}),
|
||||
);
|
||||
let t = obj(&s, id);
|
||||
let lay = vectorcraft_text::layout(vectorcraft_text::FontDb::global(), &t);
|
||||
assert!(lay.lines.len() >= 3, "the first paragraph wraps");
|
||||
let was = glyphs(&s, &[id]);
|
||||
select(&mut s, &[id]);
|
||||
let r = s.execute("addon.cleanup.breakText", &json!({"by": by})).unwrap();
|
||||
let pieces = ids(&r);
|
||||
let want = count.unwrap_or(if by == "lines" { lay.lines.len() } else { was.len() });
|
||||
assert_eq!(pieces.len(), want, "{by}");
|
||||
assert_same_places(&was, &glyphs(&s, &pieces));
|
||||
if by == "paragraphs" {
|
||||
// The wrapped lines end in line breaks.
|
||||
assert!(obj(&s, pieces[0]).plain_text().contains('\u{2028}'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn break_text_refuses_what_it_cannot_break() {
|
||||
let mut s = session();
|
||||
s.execute("shape.rectangle", &json!({"x": 10, "y": 10, "width": 40, "height": 40})).unwrap();
|
||||
assert!(other(s.execute("addon.cleanup.breakText", &json!({}))).contains("point or area type"));
|
||||
let r = s.execute("addon.cleanup.breakText", &json!({"by": "sentences"}));
|
||||
assert!(matches!(r, Err(EngineError::BadParams { .. })), "{r:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn combine_puts_glyph_pieces_back_together_where_they_were() {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 50, "y": 120, "text": "Water Lily", "size": 30}));
|
||||
s.execute("text.setRangeStyle", &json!({"id": id.0, "start": 6, "end": 10, "fill": "#ff0000"})).unwrap();
|
||||
let was = glyphs(&s, &[id]);
|
||||
select(&mut s, &[id]);
|
||||
let pieces = ids(&s.execute("addon.cleanup.breakText", &json!({"by": "glyphs"})).unwrap());
|
||||
assert_eq!(pieces.len(), 9);
|
||||
let steps = undo_steps(&s);
|
||||
let r = s.execute("addon.cleanup.combineText", &json!({})).unwrap();
|
||||
assert_eq!(undo_steps(&s), steps + 1);
|
||||
let made = ids(&r);
|
||||
assert_eq!((made.len(), r["combined"].as_u64()), (1, Some(8)));
|
||||
let t = obj(&s, made[0]);
|
||||
assert_eq!(t.plain_text(), "Water Lily", "a space goes back between the words");
|
||||
assert_same_places(&was, &glyphs(&s, &made));
|
||||
let red = t.runs.iter().find(|r| r.text.contains('L')).unwrap();
|
||||
assert_ne!(red.style.fill, t.runs[0].style.fill, "styles stay");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert!(s.doc().unwrap().doc.node(pieces[1]).is_some(), "undo brings the pieces back");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn combine_joins_only_pieces_on_one_line_turned_alike() {
|
||||
let mut s = session();
|
||||
let a = text(&mut s, json!({"x": 50, "y": 100, "text": "Left", "size": 20}));
|
||||
let b = text(&mut s, json!({"x": 110, "y": 100, "text": "Right", "size": 20}));
|
||||
let c = text(&mut s, json!({"x": 50, "y": 200, "text": "Below", "size": 20}));
|
||||
let d = text(&mut s, json!({"x": 300, "y": 100, "text": "Turned", "size": 20, "rotation": 45}));
|
||||
let was = glyphs(&s, &[a, b]);
|
||||
select(&mut s, &[a, b, c, d]);
|
||||
let r = s.execute("addon.cleanup.combineText", &json!({})).unwrap();
|
||||
assert_eq!(ids(&r), [a]);
|
||||
assert_eq!(obj(&s, a).plain_text(), "Left Right");
|
||||
assert_same_places(&was, &glyphs(&s, &[a]));
|
||||
let doc = &s.doc().unwrap().doc;
|
||||
assert!(doc.node(b).is_none() && doc.node(c).is_some() && doc.node(d).is_some());
|
||||
select(&mut s, &[c, d]);
|
||||
assert!(other(s.execute("addon.cleanup.combineText", &json!({}))).contains("combine"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_line_and_paragraph_breaks() {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 40, "y": 60, "text": "one\u{2028}two \u{2028}three\nfour\n\nfive", "size": 12}));
|
||||
select(&mut s, &[id]);
|
||||
let before = doc_json(&s);
|
||||
let r = s.execute("addon.cleanup.removeBreaks", &json!({"kind": "line"})).unwrap();
|
||||
assert_eq!(r["removed"], 2);
|
||||
assert_eq!(obj(&s, id).plain_text(), "one two three\nfour\n\nfive");
|
||||
let r = s.execute("addon.cleanup.removeBreaks", &json!({"kind": "paragraph"})).unwrap();
|
||||
assert_eq!(r["removed"], 3);
|
||||
let t = obj(&s, id);
|
||||
assert_eq!((t.plain_text().as_str(), t.paragraph_count()), ("one two three four five", 1));
|
||||
assert_eq!(other(s.execute("addon.cleanup.removeBreaks", &json!({"kind": "line"}))), "No line breaks to remove");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(doc_json(&s), before);
|
||||
assert!(matches!(s.execute("addon.cleanup.removeBreaks", &json!({})), Err(EngineError::BadParams { .. })));
|
||||
}
|
||||
|
||||
/// The Type tool editing `id` with bytes `anchor..caret` selected.
|
||||
fn edit_text(s: &mut Session, id: NodeId, anchor: usize, caret: usize) {
|
||||
s.select_tool("type", Default::default()).unwrap();
|
||||
s.set_tool_option("textSelection", &json!({"editing": id.0, "anchor": anchor, "caret": caret}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_breaks_in_the_characters_a_type_tool_selected() {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 40, "y": 60, "text": "a\nb\nc", "size": 12}));
|
||||
select(&mut s, &[id]);
|
||||
edit_text(&mut s, id, 0, 2);
|
||||
s.execute("addon.cleanup.removeBreaks", &json!({"kind": "paragraph"})).unwrap();
|
||||
assert_eq!(obj(&s, id).plain_text(), "a b\nc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_at_the_cursor_and_around_a_selection() {
|
||||
for (anchor, caret, want) in [(6, 6, &["Split", "here please"][..]), (6, 10, &["Split", "here", "please"][..])] {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 40, "y": 60, "text": "Split here please", "size": 20, "justify": "center"}));
|
||||
let was = glyphs(&s, &[id]);
|
||||
select(&mut s, &[id]);
|
||||
let r = s.execute("addon.cleanup.splitText", &json!({}));
|
||||
assert!(matches!(&r, Err(EngineError::Disabled(_, why)) if why.contains("Type tool")), "{r:?}");
|
||||
edit_text(&mut s, id, anchor, caret);
|
||||
let steps = undo_steps(&s);
|
||||
let r = s.execute("addon.cleanup.splitText", &json!({})).unwrap();
|
||||
assert_eq!(undo_steps(&s), steps + 1);
|
||||
let pieces = ids(&r);
|
||||
let texts: Vec<String> = pieces.iter().map(|p| obj(&s, *p).plain_text()).collect();
|
||||
assert_eq!(texts, want);
|
||||
assert_same_places(&was, &glyphs(&s, &pieces));
|
||||
assert!(s.tool_options()["editing"].is_null(), "editing ends");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_keeps_the_later_lines_of_a_wrapped_piece() {
|
||||
let mut s = session();
|
||||
let id = text(
|
||||
&mut s,
|
||||
json!({"x": 40, "y": 40, "text": "First words then a long run of text that wraps in the frame", "size": 14, "area": {"width": 160, "height": 200}}),
|
||||
);
|
||||
let was = glyphs(&s, &[id]);
|
||||
select(&mut s, &[id]);
|
||||
edit_text(&mut s, id, 6, 6);
|
||||
let pieces = ids(&s.execute("addon.cleanup.splitText", &json!({})).unwrap());
|
||||
assert_eq!(pieces.len(), 2);
|
||||
assert_same_places(&was, &glyphs(&s, &pieces));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_alignment_keeps_the_text_in_place() {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 100, "y": 60, "text": "Stay put", "size": 20}));
|
||||
let multi = text(&mut s, json!({"x": 100, "y": 160, "text": "Short\u{2028}The longest line", "size": 20}));
|
||||
let was = glyphs(&s, &[id]);
|
||||
let longest: Vec<_> = glyphs(&s, &[multi]).into_iter().skip(5).collect();
|
||||
select(&mut s, &[id, multi]);
|
||||
for align in ["center", "right", "left"] {
|
||||
s.execute("addon.cleanup.alignInPlace", &json!({"align": align})).unwrap();
|
||||
assert_same_places(&was, &glyphs(&s, &[id]));
|
||||
assert_same_places(&longest, &glyphs(&s, &[multi]).into_iter().skip(5).collect::<Vec<_>>());
|
||||
}
|
||||
assert_eq!(obj(&s, id).para.justify, Justify::Left);
|
||||
assert!(other(s.execute("addon.cleanup.alignInPlace", &json!({"align": "left"}))).contains("already"));
|
||||
assert!(matches!(s.execute("addon.cleanup.alignInPlace", &json!({"align": "up"})), Err(EngineError::BadParams { .. })));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reset_text_transform_takes_off_rotation_and_with_scale_the_horizontal_scale() {
|
||||
let mut s = session();
|
||||
let id = text(&mut s, json!({"x": 100, "y": 100, "text": "Tilted", "size": 20, "rotation": 30}));
|
||||
s.execute("text.setRangeStyle", &json!({"id": id.0, "hScale": 150})).unwrap();
|
||||
let centre = |s: &Session| {
|
||||
let t = obj(s, id);
|
||||
t.xf * vectorcraft_text::layout(vectorcraft_text::FontDb::global(), &t).bounds.center()
|
||||
};
|
||||
let was = centre(&s);
|
||||
let size = obj(&s, id).effective_char_style(&obj(&s, id).runs[0].style).unwrap().size;
|
||||
select(&mut s, &[id]);
|
||||
s.execute("addon.cleanup.resetTextTransform", &json!({})).unwrap();
|
||||
let t = obj(&s, id);
|
||||
let [_, b, c, _, _, _] = t.xf.as_coeffs();
|
||||
assert!(b.abs() < 1e-9 && c.abs() < 1e-9, "{:?}", t.xf);
|
||||
assert!((centre(&s) - was).hypot() < 1e-6);
|
||||
assert!((t.effective_char_style(&t.runs[0].style).unwrap().size - size).abs() < 1e-6, "the size stays");
|
||||
assert!(t.runs[0].style.h_scale > 100.0, "the horizontal scale stays");
|
||||
assert!(other(s.execute("addon.cleanup.resetTextTransform", &json!({}))).contains("no transform"));
|
||||
s.execute("addon.cleanup.resetTextTransform", &json!({"scale": true})).unwrap();
|
||||
assert_eq!(obj(&s, id).runs[0].style.h_scale, 100.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_missing_fonts_with_the_default_or_a_chosen_font() {
|
||||
let mut s = session();
|
||||
let gone = text(&mut s, json!({"x": 40, "y": 60, "text": "Lost", "size": 20, "font": "No Such Font Family", "style": "Bold"}));
|
||||
let kept = text(&mut s, json!({"x": 40, "y": 120, "text": "Fine", "size": 20}));
|
||||
let fine = obj(&s, kept);
|
||||
let r = s.execute("addon.cleanup.replaceFonts", &json!({})).unwrap();
|
||||
assert_eq!((r["runs"].as_u64(), r["font"].as_str()), (Some(1), Some("Source Sans 3")));
|
||||
let t = obj(&s, gone);
|
||||
assert_eq!((t.runs[0].style.font_family.as_str(), t.runs[0].style.font_style.as_str()), ("Source Sans 3", "Bold"));
|
||||
assert_eq!(obj(&s, kept), fine);
|
||||
assert_eq!(other(s.execute("addon.cleanup.replaceFonts", &json!({}))), "No fonts are missing");
|
||||
let r = s.execute("addon.cleanup.replaceFonts", &json!({"font": "No Such Font Family"}));
|
||||
assert!(matches!(r, Err(EngineError::BadParams { .. })), "{r:?}");
|
||||
}
|
||||
@@ -559,6 +559,23 @@ fn structured_junk() {
|
||||
("addon.pen.reshape", json!({"id": 2, "segment": 0, "t": "x", "dx": 1, "dy": 1, "mode": "symmetric"})),
|
||||
("addon.pen.nextSegment", json!({"curved": "yes"})),
|
||||
("addon.pen.closeJoin", json!({"ids": [u64::MAX]})),
|
||||
("addon.cleanup.breakText", json!({"by": "glyphs", "ids": [0, 1, 2, 3, 4, 5, 6, 7, 8, u64::MAX]})),
|
||||
("addon.cleanup.breakText", json!({"by": ["lines"]})),
|
||||
("addon.cleanup.breakText", json!({"by": "paragraphs"})),
|
||||
("addon.cleanup.breakText", json!({"by": "words", "ids": "all"})),
|
||||
("addon.cleanup.combineText", json!({"ids": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})),
|
||||
("addon.cleanup.combineText", json!({"ids": [-1, 1e308]})),
|
||||
("addon.cleanup.removeBreaks", json!({"kind": "paragraph", "ids": [1, 2, 3, 4, 5, 6, 7, 8, u64::MAX]})),
|
||||
("addon.cleanup.removeBreaks", json!({"kind": 3})),
|
||||
("addon.cleanup.removeBreaks", json!({"kind": "line", "ids": null})),
|
||||
("addon.cleanup.splitText", json!({"at": 1e308})),
|
||||
("addon.cleanup.alignInPlace", json!({"align": "right", "ids": [1, 2, 3, 4, 5, 6, 7, 8]})),
|
||||
("addon.cleanup.alignInPlace", json!({"align": null, "ids": [-1]})),
|
||||
("addon.cleanup.resetTextTransform", json!({"scale": "yes"})),
|
||||
("addon.cleanup.resetTextTransform", json!({"scale": true, "ids": [1, 2, 3, 4, 5, 6, 7, 8]})),
|
||||
("addon.cleanup.replaceFonts", json!({"font": ""})),
|
||||
("addon.cleanup.replaceFonts", json!({"font": ["Source Sans 3"]})),
|
||||
("addon.cleanup.replaceFonts", json!({"font": "\u{0}"})),
|
||||
];
|
||||
let mut failures = vec![];
|
||||
for fx in Fixture::ALL {
|
||||
@@ -571,6 +588,43 @@ fn structured_junk() {
|
||||
assert!(failures.is_empty(), "{} failures:\n{}", failures.len(), failures.join("\n"));
|
||||
}
|
||||
|
||||
/// Artwork Cleanup's text tools while a Type tool edits type with junk ranges (past the end,
|
||||
/// reversed, inside a character): never a panic, and the document stays sound.
|
||||
#[test]
|
||||
fn cleanup_text_tools_with_junk_editing_ranges() {
|
||||
let ranges = [(0, u64::MAX / 4), (u64::MAX, 1), (5, 5), (1, 2), (u64::MAX / 4, u64::MAX / 4)];
|
||||
let mut failures = vec![];
|
||||
for fx in Fixture::ALL {
|
||||
let mut texts = vec![];
|
||||
for l in &fx.session().doc().unwrap().doc.layers {
|
||||
l.walk(&mut |n| {
|
||||
if matches!(n.kind, vectorcraft_doc::NodeKind::Text(_)) {
|
||||
texts.push(n.id.0);
|
||||
}
|
||||
});
|
||||
}
|
||||
for id in texts {
|
||||
for (anchor, caret) in ranges {
|
||||
for (cmd, p) in [("addon.cleanup.splitText", json!({})), ("addon.cleanup.removeBreaks", json!({"kind": "paragraph"}))] {
|
||||
let mut s = fx.session();
|
||||
let r = catch_quiet(|| {
|
||||
let _ = s.execute("select.set", &json!({"ids": [id]}));
|
||||
let _ = s.select_tool("type", Default::default());
|
||||
s.set_tool_option("textSelection", &json!({"editing": id, "anchor": anchor, "caret": caret}));
|
||||
no_panic(s.execute(cmd, &p))
|
||||
});
|
||||
if let Err(msg) = r {
|
||||
failures.push(format!("PANIC {cmd} {id} {anchor}..{caret} [{fx:?}]: {msg}"));
|
||||
} else if let Err(e) = check_session(&s) {
|
||||
failures.push(format!("{cmd} {id} {anchor}..{caret} [{fx:?}]: {e}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(failures.is_empty(), "{} failures:\n{}", failures.len(), failures.join("\n"));
|
||||
}
|
||||
|
||||
/// Shape Builder Tool Options (Gap Detection) with junk values: never a panic, and the tool still
|
||||
/// answers with options and works on a drag afterwards.
|
||||
#[test]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Artwork Cleanup's panel and submenu (Object › Plug-ins › Artwork Cleanup). The panel runs the
|
||||
//! Document Health Check on the selection, or the document while nothing is selected, lists what it
|
||||
//! found, and shows or fixes the issues picked in the list (Fix All: every issue listed), each fix
|
||||
//! one undo step. Below, the add-on's one-click tools open their options as their menu items do.
|
||||
//! one undo step. Below, the add-on's one-click tools open their options as their menu items do,
|
||||
//! and its text tools, which the panel can hide, act on the selected type.
|
||||
|
||||
use egui::{Align, Layout, Ui};
|
||||
use serde_json::{Value, json};
|
||||
@@ -16,6 +17,8 @@ pub const ID: &str = "artworkCleanup";
|
||||
|
||||
/// Where the panel keeps its last check (panel state).
|
||||
const STATE: &str = "artwork-cleanup";
|
||||
/// Where the panel keeps whether its text tools are hidden (panel state).
|
||||
const TEXT_HIDDEN: &str = "artwork-cleanup-text-hidden";
|
||||
|
||||
/// The one-click tools: (menu label, command, the options their dialog opens with).
|
||||
fn tools() -> [(&'static str, &'static str, Value); 3] {
|
||||
@@ -26,11 +29,92 @@ fn tools() -> [(&'static str, &'static str, Value); 3] {
|
||||
]
|
||||
}
|
||||
|
||||
/// Replace Missing Fonts' options: the default type font.
|
||||
fn replace_fonts() -> Value {
|
||||
json!({ "font": vectorcraft_doc::CharStyle::default().font_family })
|
||||
}
|
||||
|
||||
/// A row of the panel's text tools: a label above (if any), then its buttons (label, what a
|
||||
/// modifier click does, command, params).
|
||||
type TextRow = (Option<&'static str>, Vec<(&'static str, Option<&'static str>, &'static str, Value)>);
|
||||
|
||||
fn text_rows() -> [TextRow; 4] {
|
||||
let align = |a: &str| json!({ "align": a });
|
||||
let by = |b: &str| json!({ "by": b });
|
||||
[
|
||||
(
|
||||
Some("Set Alignment, Keep Position:"),
|
||||
vec![
|
||||
("Left", None, "addon.cleanup.alignInPlace", align("left")),
|
||||
("Center", None, "addon.cleanup.alignInPlace", align("center")),
|
||||
("Right", None, "addon.cleanup.alignInPlace", align("right")),
|
||||
],
|
||||
),
|
||||
(
|
||||
Some("Break Text into:"),
|
||||
vec![
|
||||
("Lines", Some("Shift-click: break into paragraphs"), "addon.cleanup.breakText", by("lines")),
|
||||
("Words", None, "addon.cleanup.breakText", by("words")),
|
||||
("Glyphs", None, "addon.cleanup.breakText", by("glyphs")),
|
||||
],
|
||||
),
|
||||
(
|
||||
None,
|
||||
vec![
|
||||
("Split at Cursor", None, "addon.cleanup.splitText", json!({})),
|
||||
("Reset Transform", Some("Alt-click: reset the horizontal scale too"), "addon.cleanup.resetTextTransform", json!({})),
|
||||
],
|
||||
),
|
||||
(None, vec![("Combine Point Text", None, "addon.cleanup.combineText", json!({}))]),
|
||||
]
|
||||
}
|
||||
|
||||
/// The text tools one to a row below the others: (label, command, params).
|
||||
fn text_singles() -> [(&'static str, &'static str, Value); 3] {
|
||||
[
|
||||
("Remove Line Breaks", "addon.cleanup.removeBreaks", json!({ "kind": "line" })),
|
||||
("Remove Paragraph Breaks", "addon.cleanup.removeBreaks", json!({ "kind": "paragraph" })),
|
||||
("Replace Missing Fonts…", "addon.cleanup.replaceFonts", replace_fonts()),
|
||||
]
|
||||
}
|
||||
|
||||
/// `p` for a click with `held`: Shift-click on Lines breaks into paragraphs, Alt-click on Reset
|
||||
/// Transform resets the horizontal scale too.
|
||||
fn modified(id: &str, mut p: Value, held: egui::Modifiers) -> Value {
|
||||
match id {
|
||||
"addon.cleanup.breakText" if held.shift && p["by"] == "lines" => p["by"] = json!("paragraphs"),
|
||||
"addon.cleanup.resetTextTransform" if held.alt => p["scale"] = json!(true),
|
||||
_ => {}
|
||||
}
|
||||
p
|
||||
}
|
||||
|
||||
/// Object › Plug-ins › Artwork Cleanup.
|
||||
pub fn menu() -> Vec<Item> {
|
||||
let mut items = vec![Item::Cmd("Document Health Check", "window.panel", json!({ "panel": ID })), Item::Sep];
|
||||
items.extend(tools().into_iter().map(|(label, id, p)| Item::Cmd(label, id, p)));
|
||||
items.extend([Item::Sep, Item::Cmd("Fix All Issues", "addon.cleanup.fix", Value::Null)]);
|
||||
items.extend([Item::Sep, Item::Cmd("Fix All Issues", "addon.cleanup.fix", Value::Null), Item::Sep]);
|
||||
let by = |b: &str| json!({ "by": b });
|
||||
let align = |a: &str| json!({ "align": a });
|
||||
items.extend([
|
||||
Item::Cmd("Combine Point Text", "addon.cleanup.combineText", json!({})),
|
||||
Item::Cmd("Break Text into Lines", "addon.cleanup.breakText", by("lines")),
|
||||
Item::Cmd("Break Text into Paragraphs", "addon.cleanup.breakText", by("paragraphs")),
|
||||
Item::Cmd("Break Text into Words", "addon.cleanup.breakText", by("words")),
|
||||
Item::Cmd("Break Text into Glyphs", "addon.cleanup.breakText", by("glyphs")),
|
||||
Item::Cmd("Split Text at Cursor", "addon.cleanup.splitText", json!({})),
|
||||
Item::Sub(
|
||||
"Set Alignment, Keep Position",
|
||||
vec![
|
||||
Item::Cmd("Left", "addon.cleanup.alignInPlace", align("left")),
|
||||
Item::Cmd("Center", "addon.cleanup.alignInPlace", align("center")),
|
||||
Item::Cmd("Right", "addon.cleanup.alignInPlace", align("right")),
|
||||
],
|
||||
),
|
||||
Item::Cmd("Reset Text Transform", "addon.cleanup.resetTextTransform", json!({})),
|
||||
Item::Cmd("Reset Text Transform and Scale", "addon.cleanup.resetTextTransform", json!({ "scale": true })),
|
||||
]);
|
||||
items.extend(text_singles().into_iter().map(|(label, id, p)| Item::Cmd(label, id, p)));
|
||||
items
|
||||
}
|
||||
|
||||
@@ -94,7 +178,8 @@ enum Action {
|
||||
Check,
|
||||
Show(String),
|
||||
Fix(Vec<String>),
|
||||
Tool(usize),
|
||||
/// A tool's button: (its label, command, params), run as its menu item is.
|
||||
Run(&'static str, &'static str, Value),
|
||||
}
|
||||
|
||||
pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
@@ -121,12 +206,21 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
}
|
||||
widgets::divider(ui);
|
||||
ui.add_enabled_ui(selected, |ui| {
|
||||
for (i, (label, ..)) in tools().iter().enumerate() {
|
||||
for (label, id, p) in tools() {
|
||||
if widgets::flat_button(ui, tl!(label), width).clicked() {
|
||||
action = Some(Action::Tool(i));
|
||||
action = Some(Action::Run(label, id, p));
|
||||
}
|
||||
}
|
||||
});
|
||||
let hidden: bool = pstate(ui.ctx(), TEXT_HIDDEN);
|
||||
widgets::divider(ui);
|
||||
if widgets::section_toggle(ui, "Text", !hidden) {
|
||||
set_pstate(ui.ctx(), TEXT_HIDDEN, !hidden);
|
||||
}
|
||||
if !hidden {
|
||||
let editing = app.session.tool_options().get("editing").is_some_and(|v| !v.is_null());
|
||||
text_tools(ui, width, selected, editing, &mut action);
|
||||
}
|
||||
match action {
|
||||
Some(Action::Check) => r = check(app, None),
|
||||
Some(Action::Show(kind)) => {
|
||||
@@ -135,17 +229,53 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
}
|
||||
}
|
||||
Some(Action::Fix(kinds)) => r = fix(app, &r, kinds),
|
||||
Some(Action::Tool(i)) => {
|
||||
if let Some((label, id, p)) = tools().into_iter().nth(i) {
|
||||
let (id, p) = crate::menus::click_target(label, id, &p);
|
||||
crate::menus::invoke(app, &id, p);
|
||||
}
|
||||
Some(Action::Run(label, id, p)) => {
|
||||
let (id, p) = crate::menus::click_target(label, id, &p);
|
||||
crate::menus::invoke(app, &id, p);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
set_pstate(ui.ctx(), STATE, r);
|
||||
}
|
||||
|
||||
/// The text tools: rows of buttons, then one to a row. Each is enabled when its command can act:
|
||||
/// Split at Cursor while a Type tool edits text, Replace Missing Fonts always, the others with a
|
||||
/// selection.
|
||||
fn text_tools(ui: &mut Ui, width: f32, selected: bool, editing: bool, action: &mut Option<Action>) {
|
||||
let enabled = |id: &str| match id {
|
||||
"addon.cleanup.splitText" => editing,
|
||||
"addon.cleanup.replaceFonts" => true,
|
||||
_ => selected,
|
||||
};
|
||||
let mut button = |ui: &mut Ui, label: &'static str, tip: Option<&str>, id: &'static str, p: Value, w: f32| {
|
||||
// Lines and words of text, not lines drawn: their own catalog rows (the button translates
|
||||
// the others).
|
||||
let shown = if id == "addon.cleanup.breakText" { crate::i18n::tr_ctx(crate::i18n::current(), "breakText", label) } else { label };
|
||||
let mut resp = ui.add_enabled_ui(enabled(id), |ui| widgets::flat_button(ui, shown, w)).inner;
|
||||
if let Some(tip) = tip {
|
||||
resp = resp.on_hover_text(tl!(tip));
|
||||
}
|
||||
if resp.clicked() {
|
||||
*action = Some(Action::Run(label, id, modified(id, p, ui.input(|i| i.modifiers))));
|
||||
}
|
||||
};
|
||||
for (heading, buttons) in text_rows() {
|
||||
if let Some(h) = heading {
|
||||
widgets::subheader(ui, h);
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
let n = buttons.len() as f32;
|
||||
let each = ((width - ui.spacing().item_spacing.x * (n - 1.0)) / n).max(40.0);
|
||||
for (label, tip, id, p) in buttons {
|
||||
button(ui, label, tip, id, p, each);
|
||||
}
|
||||
});
|
||||
}
|
||||
for (label, id, p) in text_singles() {
|
||||
button(ui, label, None, id, p, width);
|
||||
}
|
||||
}
|
||||
|
||||
/// The list of what the check found (click picks a row, Ctrl/Cmd- or Shift-click adds one), and
|
||||
/// Show, Fix Selected and Fix All.
|
||||
fn results(ui: &mut Ui, r: &mut Results, action: &mut Option<Action>) {
|
||||
|
||||
@@ -65,3 +65,111 @@ fn check_lists_what_it_found_and_fix_clears_it() {
|
||||
});
|
||||
assert!(text.contains("No issues found."), "{text}");
|
||||
}
|
||||
|
||||
/// An app with the point type `text`, selected.
|
||||
fn type_app(text: &str) -> (VectorcraftApp, u64) {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 300, "height": 200})).unwrap();
|
||||
let id = app.run("text.create", json!({"x": 20, "y": 60, "text": text, "size": 20})).unwrap()["id"].as_u64().unwrap();
|
||||
app.run("select.set", json!({"ids": [id]})).unwrap();
|
||||
(app, id)
|
||||
}
|
||||
|
||||
fn texts(app: &VectorcraftApp) -> Vec<String> {
|
||||
let mut out = vec![];
|
||||
for l in &app.session.doc().unwrap().doc.layers {
|
||||
l.walk(&mut |n| {
|
||||
if let vectorcraft_doc::NodeKind::Text(t) = &n.kind {
|
||||
out.push(t.plain_text());
|
||||
}
|
||||
});
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_plugins_submenu_runs_the_text_tools() {
|
||||
let (mut app, _) = type_app("one two");
|
||||
let entries = menus::menu_entries(&app);
|
||||
let under = |path: &[&str], label: &str| entries.iter().find(|e| e.path == path && e.label == label);
|
||||
let cleanup = ["Object", "Plug-ins", "Artwork Cleanup"];
|
||||
for (label, id) in [
|
||||
("Combine Point Text", "addon.cleanup.combineText"),
|
||||
("Break Text into Lines", "addon.cleanup.breakText"),
|
||||
("Break Text into Paragraphs", "addon.cleanup.breakText"),
|
||||
("Break Text into Glyphs", "addon.cleanup.breakText"),
|
||||
("Split Text at Cursor", "addon.cleanup.splitText"),
|
||||
("Reset Text Transform", "addon.cleanup.resetTextTransform"),
|
||||
("Reset Text Transform and Scale", "addon.cleanup.resetTextTransform"),
|
||||
("Remove Line Breaks", "addon.cleanup.removeBreaks"),
|
||||
("Remove Paragraph Breaks", "addon.cleanup.removeBreaks"),
|
||||
("Replace Missing Fonts…", "addon.cleanup.replaceFonts"),
|
||||
] {
|
||||
assert_eq!(under(&cleanup, label).and_then(|e| e.command.as_deref()), Some(id), "{label}");
|
||||
}
|
||||
let center = under(&["Object", "Plug-ins", "Artwork Cleanup", "Set Alignment, Keep Position"], "Center").expect("listed");
|
||||
assert_eq!((center.command.as_deref(), ¢er.params), (Some("addon.cleanup.alignInPlace"), &json!({"align": "center"})));
|
||||
// Replace Missing Fonts opens its options first, with the default type font.
|
||||
let fonts = under(&cleanup, "Replace Missing Fonts…").unwrap();
|
||||
let (target, p) = menus::click_target(&fonts.label, "addon.cleanup.replaceFonts", &fonts.params);
|
||||
assert_eq!((target.as_str(), &p["params"]["font"]), ("ui.paramDialog", &json!("Source Sans 3")));
|
||||
let words = under(&cleanup, "Break Text into Words").unwrap();
|
||||
menus::invoke(&mut app, "addon.cleanup.breakText", words.params.clone());
|
||||
assert_eq!(texts(&app), ["one", "two"]);
|
||||
let combine = under(&cleanup, "Combine Point Text").unwrap();
|
||||
menus::invoke(&mut app, "addon.cleanup.combineText", combine.params.clone());
|
||||
assert_eq!(texts(&app), ["one two"]);
|
||||
}
|
||||
|
||||
/// One frame of the panel in `ctx` with `events` and `modifiers` held: the texts drawn and where.
|
||||
fn frame_with(app: &mut VectorcraftApp, ctx: &egui::Context, events: Vec<egui::Event>, modifiers: egui::Modifiers) -> Vec<(String, egui::Rect)> {
|
||||
fn collect(s: &egui::Shape, out: &mut Vec<(String, egui::Rect)>) {
|
||||
match s {
|
||||
egui::Shape::Text(t) => out.push((t.galley.text().to_string(), t.visual_bounding_rect())),
|
||||
egui::Shape::Vec(v) => v.iter().for_each(|s| collect(s, out)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let time = ctx.input(|i| i.time) + 0.1;
|
||||
let events = std::iter::once(egui::Event::ModifiersChanged(modifiers)).chain(events).collect();
|
||||
let mut out = ctx.run_ui(egui::RawInput { events, time: Some(time), ..Default::default() }, |ui| show(app, ui));
|
||||
out.textures_delta.clear();
|
||||
let mut v = vec![];
|
||||
out.shapes.iter().for_each(|c| collect(&c.shape, &mut v));
|
||||
v
|
||||
}
|
||||
|
||||
fn panel_frame(app: &mut VectorcraftApp, ctx: &egui::Context, events: Vec<egui::Event>) -> Vec<(String, egui::Rect)> {
|
||||
frame_with(app, ctx, events, egui::Modifiers::NONE)
|
||||
}
|
||||
|
||||
/// Click the text `label` the panel draws, with `modifiers` held.
|
||||
fn click(app: &mut VectorcraftApp, ctx: &egui::Context, label: &str, modifiers: egui::Modifiers) {
|
||||
let shown = panel_frame(app, ctx, vec![]);
|
||||
let at = shown.iter().find(|(s, _)| s == label).unwrap_or_else(|| panic!("no {label:?} in {shown:?}")).1.center();
|
||||
let button = |pressed| egui::Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed, modifiers };
|
||||
for events in [vec![egui::Event::PointerMoved(at)], vec![button(true)], vec![button(false)]] {
|
||||
frame_with(app, ctx, events, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_panels_text_row_runs_the_text_tools_and_hides() {
|
||||
let (mut app, _) = type_app("Hello there\nworld");
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
let steps = app.session.doc().unwrap().history.undo.len();
|
||||
// Shift-click on Lines breaks into paragraphs.
|
||||
click(&mut app, &ctx, "Lines", egui::Modifiers::SHIFT);
|
||||
assert_eq!(texts(&app), ["Hello there", "world"]);
|
||||
assert_eq!(app.session.doc().unwrap().history.undo.len(), steps + 1, "one undo step");
|
||||
click(&mut app, &ctx, "Words", egui::Modifiers::NONE);
|
||||
assert_eq!(texts(&app), ["Hello", "there", "world"]);
|
||||
click(&mut app, &ctx, "Combine Point Text", egui::Modifiers::NONE);
|
||||
assert_eq!(texts(&app), ["Hello there", "world"]);
|
||||
// The row hides and shows again.
|
||||
click(&mut app, &ctx, "Text", egui::Modifiers::NONE);
|
||||
assert!(!panel_frame(&mut app, &ctx, vec![]).iter().any(|(s, _)| s == "Words"));
|
||||
click(&mut app, &ctx, "Text", egui::Modifiers::NONE);
|
||||
assert!(panel_frame(&mut app, &ctx, vec![]).iter().any(|(s, _)| s == "Words"));
|
||||
}
|
||||
|
||||
@@ -5772,3 +5772,47 @@ anchor Points: Точки:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` задайте `inkLimit`, `removeWhiteOverprint` или `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Корекциите на мастилата за печат работят върху CMYK документи: първо изберете Файл › Цветен режим на документа › CMYK цвят
|
||||
@msg `{key}` must be 0..{max} `{key}` трябва да е 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Разделяне на текст
|
||||
Combine Point Text Обединяване на точков текст
|
||||
Remove Breaks Премахване на прекъсвания
|
||||
Split Text at Cursor Разделяне на текст при курсора
|
||||
Set Alignment, Keep Position Задаване на подравняване със запазване на позицията
|
||||
Reset Text Transform Нулиране на трансформацията на текста
|
||||
Replace Missing Fonts… Замяна на липсващите шрифтове…
|
||||
Replace Missing Fonts Замяна на липсващите шрифтове
|
||||
Remove Line Breaks Премахване на прекъсванията на редове
|
||||
Remove Paragraph Breaks Премахване на прекъсванията на абзаци
|
||||
Break Text into Lines Разделяне на текста на редове
|
||||
Break Text into Paragraphs Разделяне на текста на абзаци
|
||||
Break Text into Words Разделяне на текста на думи
|
||||
Break Text into Glyphs Разделяне на текста на глифи
|
||||
Reset Text Transform and Scale Нулиране на трансформацията и мащаба на текста
|
||||
Set Alignment, Keep Position: Подравняване със запазване на позицията:
|
||||
Break Text into: Разделяне на текста на:
|
||||
Split at Cursor Разделяне при курсора
|
||||
Reset Transform Нулиране на трансформацията
|
||||
Shift-click: break into paragraphs Shift-щракване: разделяне на абзаци
|
||||
Alt-click: reset the horizontal scale too Alt-щракване: нулиране и на хоризонталния мащаб
|
||||
breakText Lines Редове
|
||||
breakText Words Думи
|
||||
breakText Glyphs Глифи
|
||||
@msg Click in type with a Type tool to split it Щракнете в текст с инструмента „Текст“, за да го разделите
|
||||
@msg Too many type objects to change at once Твърде много текстови обекти за промяна наведнъж
|
||||
@msg Too many pieces to make at once Твърде много части за създаване наведнъж
|
||||
@msg Select horizontal point or area type whose text fits Изберете хоризонтален точков текст или текст в зона, чийто текст се побира
|
||||
@msg Nothing to split at the cursor При курсора няма какво да се раздели
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Изберете два или повече едноредови обекта с точков текст на една базова линия, за да ги обедините
|
||||
@msg No line breaks to remove Няма прекъсвания на редове за премахване
|
||||
@msg No paragraph breaks to remove Няма прекъсвания на абзаци за премахване
|
||||
@msg Too many breaks to remove at once Твърде много прекъсвания за премахване наведнъж
|
||||
@msg Select point type Изберете точков текст
|
||||
@msg The point type is aligned that way already Точковият текст вече е подравнен така
|
||||
@msg The point type has no transform to reset Точковият текст няма трансформация за нулиране
|
||||
@msg No fonts are missing Няма липсващи шрифтове
|
||||
@msg the replacement font is not available заместващият шрифт не е наличен
|
||||
@msg missing `align` липсва `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` трябва да е lines, paragraphs, words или glyphs, а не {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` трябва да е "line" или "paragraph", а не {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` трябва да е "left", "center" или "right", а не {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5873,3 +5873,47 @@ anchor Points: Punts:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` indiqueu `inkLimit`, `removeWhiteOverprint` o `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Les correccions de tinta per a impressió funcionen en documents CMYK: trieu primer Fitxer › Mode de color del document › Color CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` ha de ser 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Divideix el text
|
||||
Combine Point Text Combina el text de punt
|
||||
Remove Breaks Elimina els salts
|
||||
Split Text at Cursor Divideix el text al cursor
|
||||
Set Alignment, Keep Position Defineix l’alineació i manté la posició
|
||||
Reset Text Transform Restableix la transformació del text
|
||||
Replace Missing Fonts… Reemplaça els tipus de lletra que falten…
|
||||
Replace Missing Fonts Reemplaça els tipus de lletra que falten
|
||||
Remove Line Breaks Elimina els salts de línia
|
||||
Remove Paragraph Breaks Elimina els salts de paràgraf
|
||||
Break Text into Lines Divideix el text en línies
|
||||
Break Text into Paragraphs Divideix el text en paràgrafs
|
||||
Break Text into Words Divideix el text en paraules
|
||||
Break Text into Glyphs Divideix el text en glifs
|
||||
Reset Text Transform and Scale Restableix la transformació i l’escala del text
|
||||
Set Alignment, Keep Position: Defineix l’alineació i manté la posició:
|
||||
Break Text into: Divideix el text en:
|
||||
Split at Cursor Divideix al cursor
|
||||
Reset Transform Restableix la transformació
|
||||
Shift-click: break into paragraphs Maj+clic: divideix en paràgrafs
|
||||
Alt-click: reset the horizontal scale too Alt-clic: restableix també l’escala horitzontal
|
||||
breakText Lines Línies
|
||||
breakText Words Paraules
|
||||
breakText Glyphs Glifs
|
||||
@msg Click in type with a Type tool to split it Feu clic en un text amb una eina de text per dividir-lo
|
||||
@msg Too many type objects to change at once Massa objectes de text per canviar-los alhora
|
||||
@msg Too many pieces to make at once Massa peces per crear-les alhora
|
||||
@msg Select horizontal point or area type whose text fits Seleccioneu text de punt o d’àrea horitzontal el text del qual hi càpiga
|
||||
@msg Nothing to split at the cursor No hi ha res a dividir al cursor
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Seleccioneu dos o més objectes de text de punt d’una línia sobre una mateixa línia de base per combinar-los
|
||||
@msg No line breaks to remove No hi ha salts de línia per eliminar
|
||||
@msg No paragraph breaks to remove No hi ha salts de paràgraf per eliminar
|
||||
@msg Too many breaks to remove at once Massa salts per eliminar-los alhora
|
||||
@msg Select point type Seleccioneu text de punt
|
||||
@msg The point type is aligned that way already El text de punt ja està alineat així
|
||||
@msg The point type has no transform to reset El text de punt no té cap transformació per restablir
|
||||
@msg No fonts are missing No falta cap tipus de lletra
|
||||
@msg the replacement font is not available el tipus de lletra de reemplaçament no està disponible
|
||||
@msg missing `align` falta `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` ha de ser lines, paragraphs, words o glyphs, no {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` ha de ser "line" o "paragraph", no {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` ha de ser "left", "center" o "right", no {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5882,3 +5882,47 @@ anchor Points: Body:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` zadejte `inkLimit`, `removeWhiteOverprint` nebo `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Opravy tiskových barev fungují v dokumentech CMYK: nejprve zvolte Soubor › Barevný režim dokumentu › Barvy CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` musí být 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Rozdělit text
|
||||
Combine Point Text Sloučit bodový text
|
||||
Remove Breaks Odstranit zalomení
|
||||
Split Text at Cursor Rozdělit text u kurzoru
|
||||
Set Alignment, Keep Position Nastavit zarovnání, zachovat polohu
|
||||
Reset Text Transform Obnovit transformaci textu
|
||||
Replace Missing Fonts… Nahradit chybějící písma…
|
||||
Replace Missing Fonts Nahradit chybějící písma
|
||||
Remove Line Breaks Odstranit zalomení řádků
|
||||
Remove Paragraph Breaks Odstranit zalomení odstavců
|
||||
Break Text into Lines Rozdělit text na řádky
|
||||
Break Text into Paragraphs Rozdělit text na odstavce
|
||||
Break Text into Words Rozdělit text na slova
|
||||
Break Text into Glyphs Rozdělit text na glyfy
|
||||
Reset Text Transform and Scale Obnovit transformaci a měřítko textu
|
||||
Set Alignment, Keep Position: Nastavit zarovnání, zachovat polohu:
|
||||
Break Text into: Rozdělit text na:
|
||||
Split at Cursor Rozdělit u kurzoru
|
||||
Reset Transform Obnovit transformaci
|
||||
Shift-click: break into paragraphs Shift+kliknutí: rozdělit na odstavce
|
||||
Alt-click: reset the horizontal scale too Alt+kliknutí: obnovit i vodorovné měřítko
|
||||
breakText Lines Řádky
|
||||
breakText Words Slova
|
||||
breakText Glyphs Glyfy
|
||||
@msg Click in type with a Type tool to split it Klikněte do textu nástrojem Text, abyste jej rozdělili
|
||||
@msg Too many type objects to change at once Příliš mnoho textových objektů ke změně najednou
|
||||
@msg Too many pieces to make at once Příliš mnoho částí k vytvoření najednou
|
||||
@msg Select horizontal point or area type whose text fits Vyberte vodorovný bodový text nebo text v oblasti, jehož text se vejde
|
||||
@msg Nothing to split at the cursor U kurzoru není co rozdělit
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Vyberte dva nebo více jednořádkových objektů bodového textu na jednom účaří, abyste je sloučili
|
||||
@msg No line breaks to remove Žádná zalomení řádků k odstranění
|
||||
@msg No paragraph breaks to remove Žádná zalomení odstavců k odstranění
|
||||
@msg Too many breaks to remove at once Příliš mnoho zalomení k odstranění najednou
|
||||
@msg Select point type Vyberte bodový text
|
||||
@msg The point type is aligned that way already Bodový text je již takto zarovnán
|
||||
@msg The point type has no transform to reset Bodový text nemá žádnou transformaci k obnovení
|
||||
@msg No fonts are missing Žádná písma nechybějí
|
||||
@msg the replacement font is not available náhradní písmo není k dispozici
|
||||
@msg missing `align` chybí `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` musí být lines, paragraphs, words nebo glyphs, ne {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` musí být "line" nebo "paragraph", ne {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` musí být "left", "center" nebo "right", ne {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5787,3 +5787,47 @@ anchor Points: Punkter:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` angiv `inkLimit`, `removeWhiteOverprint` eller `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Trykfarverettelser virker på CMYK-dokumenter: vælg først Filer › Dokumentets farvetilstand › CMYK-farve
|
||||
@msg `{key}` must be 0..{max} `{key}` skal være 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Opdel tekst
|
||||
Combine Point Text Kombiner punkttekst
|
||||
Remove Breaks Fjern skift
|
||||
Split Text at Cursor Opdel tekst ved markøren
|
||||
Set Alignment, Keep Position Angiv justering, bevar placering
|
||||
Reset Text Transform Nulstil teksttransformation
|
||||
Replace Missing Fonts… Erstat manglende skrifttyper…
|
||||
Replace Missing Fonts Erstat manglende skrifttyper
|
||||
Remove Line Breaks Fjern linjeskift
|
||||
Remove Paragraph Breaks Fjern afsnitsskift
|
||||
Break Text into Lines Opdel tekst i linjer
|
||||
Break Text into Paragraphs Opdel tekst i afsnit
|
||||
Break Text into Words Opdel tekst i ord
|
||||
Break Text into Glyphs Opdel tekst i glyffer
|
||||
Reset Text Transform and Scale Nulstil teksttransformation og skalering
|
||||
Set Alignment, Keep Position: Angiv justering, bevar placering:
|
||||
Break Text into: Opdel tekst i:
|
||||
Split at Cursor Opdel ved markøren
|
||||
Reset Transform Nulstil transformation
|
||||
Shift-click: break into paragraphs Skift-klik: opdel i afsnit
|
||||
Alt-click: reset the horizontal scale too Alt-klik: nulstil også den vandrette skalering
|
||||
breakText Lines Linjer
|
||||
breakText Words Ord
|
||||
breakText Glyphs Glyffer
|
||||
@msg Click in type with a Type tool to split it Klik i tekst med et tekstværktøj for at opdele den
|
||||
@msg Too many type objects to change at once For mange tekstobjekter til at ændre på én gang
|
||||
@msg Too many pieces to make at once For mange dele til at oprette på én gang
|
||||
@msg Select horizontal point or area type whose text fits Vælg vandret punkt- eller områdetekst, hvis tekst kan være der
|
||||
@msg Nothing to split at the cursor Intet at opdele ved markøren
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Vælg to eller flere punkttekstobjekter på én linje på samme grundlinje for at kombinere dem
|
||||
@msg No line breaks to remove Ingen linjeskift at fjerne
|
||||
@msg No paragraph breaks to remove Ingen afsnitsskift at fjerne
|
||||
@msg Too many breaks to remove at once For mange skift til at fjerne på én gang
|
||||
@msg Select point type Vælg punkttekst
|
||||
@msg The point type is aligned that way already Punktteksten er allerede justeret sådan
|
||||
@msg The point type has no transform to reset Punktteksten har ingen transformation at nulstille
|
||||
@msg No fonts are missing Ingen skrifttyper mangler
|
||||
@msg the replacement font is not available erstatningsskrifttypen er ikke tilgængelig
|
||||
@msg missing `align` `align` mangler
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` skal være lines, paragraphs, words eller glyphs, ikke {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` skal være "line" eller "paragraph", ikke {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` skal være "left", "center" eller "right", ikke {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5467,3 +5467,47 @@ anchor Points: Punkte:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` geben Sie `inkLimit`, `removeWhiteOverprint` oder `overprintBlack` an
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Druckfarbkorrekturen wirken in CMYK-Dokumenten: Wählen Sie zuerst Datei › Dokumentfarbmodus › CMYK-Farbe
|
||||
@msg `{key}` must be 0..{max} `{key}` muss 0..{max} sein
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Text aufteilen
|
||||
Combine Point Text Punkttext zusammenfügen
|
||||
Remove Breaks Umbrüche entfernen
|
||||
Split Text at Cursor Text an der Einfügemarke teilen
|
||||
Set Alignment, Keep Position Ausrichtung festlegen, Position beibehalten
|
||||
Reset Text Transform Texttransformation zurücksetzen
|
||||
Replace Missing Fonts… Fehlende Schriften ersetzen…
|
||||
Replace Missing Fonts Fehlende Schriften ersetzen
|
||||
Remove Line Breaks Zeilenumbrüche entfernen
|
||||
Remove Paragraph Breaks Absatzumbrüche entfernen
|
||||
Break Text into Lines Text in Zeilen aufteilen
|
||||
Break Text into Paragraphs Text in Absätze aufteilen
|
||||
Break Text into Words Text in Wörter aufteilen
|
||||
Break Text into Glyphs Text in Glyphen aufteilen
|
||||
Reset Text Transform and Scale Texttransformation und Skalierung zurücksetzen
|
||||
Set Alignment, Keep Position: Ausrichtung festlegen, Position beibehalten:
|
||||
Break Text into: Text aufteilen in:
|
||||
Split at Cursor An Einfügemarke teilen
|
||||
Reset Transform Transformation zurücksetzen
|
||||
Shift-click: break into paragraphs Shift-Klick: in Absätze aufteilen
|
||||
Alt-click: reset the horizontal scale too Alt-Klick: auch die horizontale Skalierung zurücksetzen
|
||||
breakText Lines Zeilen
|
||||
breakText Words Wörter
|
||||
breakText Glyphs Glyphen
|
||||
@msg Click in type with a Type tool to split it Klicken Sie mit einem Text-Werkzeug in Text, um ihn zu teilen
|
||||
@msg Too many type objects to change at once Zu viele Textobjekte, um sie auf einmal zu ändern
|
||||
@msg Too many pieces to make at once Zu viele Teile, um sie auf einmal zu erstellen
|
||||
@msg Select horizontal point or area type whose text fits Wählen Sie horizontalen Punkt- oder Flächentext aus, dessen Text hineinpasst
|
||||
@msg Nothing to split at the cursor An der Einfügemarke gibt es nichts zu teilen
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Wählen Sie zwei oder mehr einzeilige Punkttextobjekte auf einer Grundlinie aus, um sie zusammenzufügen
|
||||
@msg No line breaks to remove Keine Zeilenumbrüche zu entfernen
|
||||
@msg No paragraph breaks to remove Keine Absatzumbrüche zu entfernen
|
||||
@msg Too many breaks to remove at once Zu viele Umbrüche, um sie auf einmal zu entfernen
|
||||
@msg Select point type Wählen Sie Punkttext aus
|
||||
@msg The point type is aligned that way already Der Punkttext ist bereits so ausgerichtet
|
||||
@msg The point type has no transform to reset Der Punkttext hat keine Transformation zum Zurücksetzen
|
||||
@msg No fonts are missing Es fehlen keine Schriften
|
||||
@msg the replacement font is not available die Ersatzschrift ist nicht verfügbar
|
||||
@msg missing `align` `align` fehlt
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` muss lines, paragraphs, words oder glyphs sein, nicht {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` muss "line" oder "paragraph" sein, nicht {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` muss "left", "center" oder "right" sein, nicht {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5834,3 +5834,47 @@ anchor Points: Σημεία:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` δώστε `inkLimit`, `removeWhiteOverprint` ή `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Οι διορθώσεις μελανιών εκτύπωσης ισχύουν σε έγγραφα CMYK: επιλέξτε πρώτα Αρχείο › Λειτουργία χρώματος εγγράφου › Χρώμα CMYK
|
||||
@msg `{key}` must be 0..{max} το `{key}` πρέπει να είναι 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Διαίρεση κειμένου
|
||||
Combine Point Text Συνδυασμός κειμένου σημείου
|
||||
Remove Breaks Αφαίρεση αλλαγών
|
||||
Split Text at Cursor Διαίρεση κειμένου στον δρομέα
|
||||
Set Alignment, Keep Position Ορισμός στοίχισης με διατήρηση θέσης
|
||||
Reset Text Transform Επαναφορά μετασχηματισμού κειμένου
|
||||
Replace Missing Fonts… Αντικατάσταση γραμματοσειρών που λείπουν…
|
||||
Replace Missing Fonts Αντικατάσταση γραμματοσειρών που λείπουν
|
||||
Remove Line Breaks Αφαίρεση αλλαγών γραμμής
|
||||
Remove Paragraph Breaks Αφαίρεση αλλαγών παραγράφου
|
||||
Break Text into Lines Διαίρεση κειμένου σε γραμμές
|
||||
Break Text into Paragraphs Διαίρεση κειμένου σε παραγράφους
|
||||
Break Text into Words Διαίρεση κειμένου σε λέξεις
|
||||
Break Text into Glyphs Διαίρεση κειμένου σε γλύφους
|
||||
Reset Text Transform and Scale Επαναφορά μετασχηματισμού και κλίμακας κειμένου
|
||||
Set Alignment, Keep Position: Στοίχιση με διατήρηση θέσης:
|
||||
Break Text into: Διαίρεση κειμένου σε:
|
||||
Split at Cursor Διαίρεση στον δρομέα
|
||||
Reset Transform Επαναφορά μετασχηματισμού
|
||||
Shift-click: break into paragraphs Shift-κλικ: διαίρεση σε παραγράφους
|
||||
Alt-click: reset the horizontal scale too Alt-κλικ: επαναφορά και της οριζόντιας κλίμακας
|
||||
breakText Lines Γραμμές
|
||||
breakText Words Λέξεις
|
||||
breakText Glyphs Γλύφοι
|
||||
@msg Click in type with a Type tool to split it Κάντε κλικ σε κείμενο με ένα εργαλείο κειμένου για να το διαιρέσετε
|
||||
@msg Too many type objects to change at once Πάρα πολλά αντικείμενα κειμένου για αλλαγή ταυτόχρονα
|
||||
@msg Too many pieces to make at once Πάρα πολλά κομμάτια για δημιουργία ταυτόχρονα
|
||||
@msg Select horizontal point or area type whose text fits Επιλέξτε οριζόντιο κείμενο σημείου ή περιοχής του οποίου το κείμενο χωράει
|
||||
@msg Nothing to split at the cursor Δεν υπάρχει τίποτα για διαίρεση στον δρομέα
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Επιλέξτε δύο ή περισσότερα μονογραμμικά αντικείμενα κειμένου σημείου στην ίδια γραμμή βάσης για να τα συνδυάσετε
|
||||
@msg No line breaks to remove Δεν υπάρχουν αλλαγές γραμμής για αφαίρεση
|
||||
@msg No paragraph breaks to remove Δεν υπάρχουν αλλαγές παραγράφου για αφαίρεση
|
||||
@msg Too many breaks to remove at once Πάρα πολλές αλλαγές για αφαίρεση ταυτόχρονα
|
||||
@msg Select point type Επιλέξτε κείμενο σημείου
|
||||
@msg The point type is aligned that way already Το κείμενο σημείου είναι ήδη στοιχισμένο έτσι
|
||||
@msg The point type has no transform to reset Το κείμενο σημείου δεν έχει μετασχηματισμό για επαναφορά
|
||||
@msg No fonts are missing Δεν λείπει καμία γραμματοσειρά
|
||||
@msg the replacement font is not available η γραμματοσειρά αντικατάστασης δεν είναι διαθέσιμη
|
||||
@msg missing `align` λείπει το `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} το `by` πρέπει να είναι lines, paragraphs, words ή glyphs, όχι {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} το `kind` πρέπει να είναι "line" ή "paragraph", όχι {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} το `align` πρέπει να είναι "left", "center" ή "right", όχι {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 164 and column 5.
|
@@ -5825,3 +5825,47 @@ anchor Points: Puntos:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` indique `inkLimit`, `removeWhiteOverprint` u `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Las correcciones de tinta para impresión funcionan en documentos CMYK: elija primero Archivo › Modo de color del documento › Color CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` debe ser 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Dividir texto
|
||||
Combine Point Text Combinar texto de punto
|
||||
Remove Breaks Quitar saltos
|
||||
Split Text at Cursor Dividir texto en el cursor
|
||||
Set Alignment, Keep Position Definir alineación manteniendo la posición
|
||||
Reset Text Transform Restablecer transformación del texto
|
||||
Replace Missing Fonts… Reemplazar fuentes que faltan…
|
||||
Replace Missing Fonts Reemplazar fuentes que faltan
|
||||
Remove Line Breaks Quitar saltos de línea
|
||||
Remove Paragraph Breaks Quitar saltos de párrafo
|
||||
Break Text into Lines Dividir texto en líneas
|
||||
Break Text into Paragraphs Dividir texto en párrafos
|
||||
Break Text into Words Dividir texto en palabras
|
||||
Break Text into Glyphs Dividir texto en glifos
|
||||
Reset Text Transform and Scale Restablecer transformación y escala del texto
|
||||
Set Alignment, Keep Position: Definir alineación manteniendo la posición:
|
||||
Break Text into: Dividir texto en:
|
||||
Split at Cursor Dividir en el cursor
|
||||
Reset Transform Restablecer transformación
|
||||
Shift-click: break into paragraphs Shift+clic: dividir en párrafos
|
||||
Alt-click: reset the horizontal scale too Alt+clic: restablecer también la escala horizontal
|
||||
breakText Lines Líneas
|
||||
breakText Words Palabras
|
||||
breakText Glyphs Glifos
|
||||
@msg Click in type with a Type tool to split it Haga clic en un texto con una herramienta Texto para dividirlo
|
||||
@msg Too many type objects to change at once Demasiados objetos de texto para cambiarlos a la vez
|
||||
@msg Too many pieces to make at once Demasiadas piezas para crearlas a la vez
|
||||
@msg Select horizontal point or area type whose text fits Seleccione texto de punto o de área horizontal cuyo texto quepa
|
||||
@msg Nothing to split at the cursor No hay nada que dividir en el cursor
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Seleccione dos o más objetos de texto de punto de una línea sobre la misma línea base para combinarlos
|
||||
@msg No line breaks to remove No hay saltos de línea que quitar
|
||||
@msg No paragraph breaks to remove No hay saltos de párrafo que quitar
|
||||
@msg Too many breaks to remove at once Demasiados saltos para quitarlos a la vez
|
||||
@msg Select point type Seleccione texto de punto
|
||||
@msg The point type is aligned that way already El texto de punto ya está alineado así
|
||||
@msg The point type has no transform to reset El texto de punto no tiene ninguna transformación que restablecer
|
||||
@msg No fonts are missing No falta ninguna fuente
|
||||
@msg the replacement font is not available la fuente de reemplazo no está disponible
|
||||
@msg missing `align` falta `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` debe ser lines, paragraphs, words o glyphs, no {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` debe ser "line" o "paragraph", no {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` debe ser "left", "center" o "right", no {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5913,3 +5913,47 @@ anchor Points: Pisteet:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` anna `inkLimit`, `removeWhiteOverprint` tai `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Painovärien korjaukset toimivat CMYK-asiakirjoissa: valitse ensin Tiedosto › Asiakirjan väritila › CMYK-väri
|
||||
@msg `{key}` must be 0..{max} `{key}` on oltava 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Jaa teksti
|
||||
Combine Point Text Yhdistä pisteteksti
|
||||
Remove Breaks Poista vaihdot
|
||||
Split Text at Cursor Jaa teksti kohdistimen kohdalta
|
||||
Set Alignment, Keep Position Aseta tasaus, säilytä sijainti
|
||||
Reset Text Transform Palauta tekstin muunnos
|
||||
Replace Missing Fonts… Korvaa puuttuvat fontit…
|
||||
Replace Missing Fonts Korvaa puuttuvat fontit
|
||||
Remove Line Breaks Poista rivinvaihdot
|
||||
Remove Paragraph Breaks Poista kappaleenvaihdot
|
||||
Break Text into Lines Jaa teksti riveiksi
|
||||
Break Text into Paragraphs Jaa teksti kappaleiksi
|
||||
Break Text into Words Jaa teksti sanoiksi
|
||||
Break Text into Glyphs Jaa teksti merkeiksi
|
||||
Reset Text Transform and Scale Palauta tekstin muunnos ja skaalaus
|
||||
Set Alignment, Keep Position: Aseta tasaus, säilytä sijainti:
|
||||
Break Text into: Jaa teksti:
|
||||
Split at Cursor Jaa kohdistimen kohdalta
|
||||
Reset Transform Palauta muunnos
|
||||
Shift-click: break into paragraphs Vaihto-napsautus: jaa kappaleiksi
|
||||
Alt-click: reset the horizontal scale too Alt-napsautus: palauta myös vaakaskaalaus
|
||||
breakText Lines Rivit
|
||||
breakText Words Sanat
|
||||
breakText Glyphs Merkit
|
||||
@msg Click in type with a Type tool to split it Napsauta tekstiä tekstityökalulla jakaaksesi sen
|
||||
@msg Too many type objects to change at once Liian monta tekstiobjektia muutettavaksi kerralla
|
||||
@msg Too many pieces to make at once Liian monta osaa luotavaksi kerralla
|
||||
@msg Select horizontal point or area type whose text fits Valitse vaakasuora piste- tai alueteksti, jonka teksti mahtuu
|
||||
@msg Nothing to split at the cursor Kohdistimen kohdalla ei ole jaettavaa
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Valitse kaksi tai useampia yksirivisiä pistetekstiobjekteja samalla perusviivalla yhdistääksesi ne
|
||||
@msg No line breaks to remove Ei poistettavia rivinvaihtoja
|
||||
@msg No paragraph breaks to remove Ei poistettavia kappaleenvaihtoja
|
||||
@msg Too many breaks to remove at once Liian monta vaihtoa poistettavaksi kerralla
|
||||
@msg Select point type Valitse pisteteksti
|
||||
@msg The point type is aligned that way already Pisteteksti on jo tasattu näin
|
||||
@msg The point type has no transform to reset Pistetekstillä ei ole palautettavaa muunnosta
|
||||
@msg No fonts are missing Fontteja ei puutu
|
||||
@msg the replacement font is not available korvaava fontti ei ole käytettävissä
|
||||
@msg missing `align` `align` puuttuu
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` on oltava lines, paragraphs, words tai glyphs, ei {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` on oltava "line" tai "paragraph", ei {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` on oltava "left", "center" tai "right", ei {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5881,3 +5881,47 @@ anchor Points: Points :
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` indiquez `inkLimit`, `removeWhiteOverprint` ou `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Les corrections d’encres pour l’impression s’appliquent aux documents CMJN : choisissez d’abord Fichier › Mode colorimétrique du document › Couleur CMJN
|
||||
@msg `{key}` must be 0..{max} `{key}` doit être compris entre 0 et {max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Diviser le texte
|
||||
Combine Point Text Combiner le texte de point
|
||||
Remove Breaks Supprimer les sauts
|
||||
Split Text at Cursor Diviser le texte au curseur
|
||||
Set Alignment, Keep Position Définir l’alignement en conservant la position
|
||||
Reset Text Transform Réinitialiser la transformation du texte
|
||||
Replace Missing Fonts… Remplacer les polices manquantes…
|
||||
Replace Missing Fonts Remplacer les polices manquantes
|
||||
Remove Line Breaks Supprimer les sauts de ligne
|
||||
Remove Paragraph Breaks Supprimer les sauts de paragraphe
|
||||
Break Text into Lines Diviser le texte en lignes
|
||||
Break Text into Paragraphs Diviser le texte en paragraphes
|
||||
Break Text into Words Diviser le texte en mots
|
||||
Break Text into Glyphs Diviser le texte en glyphes
|
||||
Reset Text Transform and Scale Réinitialiser la transformation et l’échelle du texte
|
||||
Set Alignment, Keep Position: Définir l’alignement en conservant la position :
|
||||
Break Text into: Diviser le texte en :
|
||||
Split at Cursor Diviser au curseur
|
||||
Reset Transform Réinitialiser la transformation
|
||||
Shift-click: break into paragraphs Maj+clic : diviser en paragraphes
|
||||
Alt-click: reset the horizontal scale too Alt+clic : réinitialiser aussi l’échelle horizontale
|
||||
breakText Lines Lignes
|
||||
breakText Words Mots
|
||||
breakText Glyphs Glyphes
|
||||
@msg Click in type with a Type tool to split it Cliquez dans du texte avec un outil Texte pour le diviser
|
||||
@msg Too many type objects to change at once Trop d’objets texte à modifier en une fois
|
||||
@msg Too many pieces to make at once Trop de morceaux à créer en une fois
|
||||
@msg Select horizontal point or area type whose text fits Sélectionnez du texte de point ou captif horizontal dont le texte tient dans son cadre
|
||||
@msg Nothing to split at the cursor Rien à diviser au curseur
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Sélectionnez au moins deux objets texte de point d’une ligne sur une même ligne de base pour les combiner
|
||||
@msg No line breaks to remove Aucun saut de ligne à supprimer
|
||||
@msg No paragraph breaks to remove Aucun saut de paragraphe à supprimer
|
||||
@msg Too many breaks to remove at once Trop de sauts à supprimer en une fois
|
||||
@msg Select point type Sélectionnez du texte de point
|
||||
@msg The point type is aligned that way already Le texte de point est déjà aligné ainsi
|
||||
@msg The point type has no transform to reset Le texte de point n’a aucune transformation à réinitialiser
|
||||
@msg No fonts are missing Aucune police ne manque
|
||||
@msg the replacement font is not available la police de remplacement n’est pas disponible
|
||||
@msg missing `align` `align` manquant
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` doit valoir lines, paragraphs, words ou glyphs, et non {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` doit valoir "line" ou "paragraph", et non {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` doit valoir "left", "center" ou "right", et non {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5869,3 +5869,47 @@ anchor Points: Pontok:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` adja meg: `inkLimit`, `removeWhiteOverprint` vagy `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first A nyomdai festékjavítások CMYK-dokumentumokon működnek: előbb válassza a Fájl › Dokumentum színmódja › CMYK-szín parancsot
|
||||
@msg `{key}` must be 0..{max} `{key}` értéke 0..{max} lehet
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Szöveg felosztása
|
||||
Combine Point Text Pontszöveg egyesítése
|
||||
Remove Breaks Törések eltávolítása
|
||||
Split Text at Cursor Szöveg felosztása a kurzornál
|
||||
Set Alignment, Keep Position Igazítás beállítása, helyzet megtartása
|
||||
Reset Text Transform Szövegátalakítás visszaállítása
|
||||
Replace Missing Fonts… Hiányzó betűtípusok cseréje…
|
||||
Replace Missing Fonts Hiányzó betűtípusok cseréje
|
||||
Remove Line Breaks Sortörések eltávolítása
|
||||
Remove Paragraph Breaks Bekezdéstörések eltávolítása
|
||||
Break Text into Lines Szöveg felosztása sorokra
|
||||
Break Text into Paragraphs Szöveg felosztása bekezdésekre
|
||||
Break Text into Words Szöveg felosztása szavakra
|
||||
Break Text into Glyphs Szöveg felosztása glifákra
|
||||
Reset Text Transform and Scale Szövegátalakítás és méretezés visszaállítása
|
||||
Set Alignment, Keep Position: Igazítás beállítása, helyzet megtartása:
|
||||
Break Text into: Szöveg felosztása:
|
||||
Split at Cursor Felosztás a kurzornál
|
||||
Reset Transform Átalakítás visszaállítása
|
||||
Shift-click: break into paragraphs Shift+kattintás: felosztás bekezdésekre
|
||||
Alt-click: reset the horizontal scale too Alt+kattintás: a vízszintes méretezés visszaállítása is
|
||||
breakText Lines Sorok
|
||||
breakText Words Szavak
|
||||
breakText Glyphs Glifák
|
||||
@msg Click in type with a Type tool to split it Kattintson a szövegbe egy szöveg eszközzel a felosztáshoz
|
||||
@msg Too many type objects to change at once Túl sok szövegobjektum az egyszerre történő módosításhoz
|
||||
@msg Too many pieces to make at once Túl sok darab az egyszerre történő létrehozáshoz
|
||||
@msg Select horizontal point or area type whose text fits Jelöljön ki vízszintes pont- vagy területszöveget, amelynek szövege elfér
|
||||
@msg Nothing to split at the cursor A kurzornál nincs mit felosztani
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Az egyesítéshez jelöljön ki legalább két egysoros pontszöveg-objektumot egy alapvonalon
|
||||
@msg No line breaks to remove Nincs eltávolítandó sortörés
|
||||
@msg No paragraph breaks to remove Nincs eltávolítandó bekezdéstörés
|
||||
@msg Too many breaks to remove at once Túl sok törés az egyszerre történő eltávolításhoz
|
||||
@msg Select point type Jelöljön ki pontszöveget
|
||||
@msg The point type is aligned that way already A pontszöveg már így van igazítva
|
||||
@msg The point type has no transform to reset A pontszövegnek nincs visszaállítandó átalakítása
|
||||
@msg No fonts are missing Nem hiányzik betűtípus
|
||||
@msg the replacement font is not available a helyettesítő betűtípus nem érhető el
|
||||
@msg missing `align` hiányzik az `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} a `by` értéke lines, paragraphs, words vagy glyphs lehet, nem {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} a `kind` értéke "line" vagy "paragraph" lehet, nem {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} az `align` értéke "left", "center" vagy "right" lehet, nem {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5787,3 +5787,47 @@ anchor Points: Titik:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` berikan `inkLimit`, `removeWhiteOverprint`, atau `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Perbaikan Tinta Cetak bekerja pada dokumen CMYK: pilih dulu Berkas › Mode warna dokumen › Warna CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` harus 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Pisahkan teks
|
||||
Combine Point Text Gabungkan teks titik
|
||||
Remove Breaks Hapus pemisah
|
||||
Split Text at Cursor Pisahkan teks di kursor
|
||||
Set Alignment, Keep Position Atur perataan, pertahankan posisi
|
||||
Reset Text Transform Atur ulang transformasi teks
|
||||
Replace Missing Fonts… Ganti font yang hilang…
|
||||
Replace Missing Fonts Ganti font yang hilang
|
||||
Remove Line Breaks Hapus putus baris
|
||||
Remove Paragraph Breaks Hapus putus paragraf
|
||||
Break Text into Lines Pisahkan teks menjadi baris
|
||||
Break Text into Paragraphs Pisahkan teks menjadi paragraf
|
||||
Break Text into Words Pisahkan teks menjadi kata
|
||||
Break Text into Glyphs Pisahkan teks menjadi glif
|
||||
Reset Text Transform and Scale Atur ulang transformasi dan skala teks
|
||||
Set Alignment, Keep Position: Atur perataan, pertahankan posisi:
|
||||
Break Text into: Pisahkan teks menjadi:
|
||||
Split at Cursor Pisahkan di kursor
|
||||
Reset Transform Atur ulang transformasi
|
||||
Shift-click: break into paragraphs Shift+klik: pisahkan menjadi paragraf
|
||||
Alt-click: reset the horizontal scale too Alt+klik: atur ulang juga skala horizontal
|
||||
breakText Lines Baris
|
||||
breakText Words Kata
|
||||
breakText Glyphs Glif
|
||||
@msg Click in type with a Type tool to split it Klik di dalam teks dengan alat teks untuk memisahkannya
|
||||
@msg Too many type objects to change at once Terlalu banyak objek teks untuk diubah sekaligus
|
||||
@msg Too many pieces to make at once Terlalu banyak bagian untuk dibuat sekaligus
|
||||
@msg Select horizontal point or area type whose text fits Pilih teks titik atau teks area horizontal yang teksnya muat
|
||||
@msg Nothing to split at the cursor Tidak ada yang dapat dipisahkan di kursor
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Pilih dua atau lebih objek teks titik satu baris pada satu garis dasar untuk menggabungkannya
|
||||
@msg No line breaks to remove Tidak ada putus baris untuk dihapus
|
||||
@msg No paragraph breaks to remove Tidak ada putus paragraf untuk dihapus
|
||||
@msg Too many breaks to remove at once Terlalu banyak pemisah untuk dihapus sekaligus
|
||||
@msg Select point type Pilih teks titik
|
||||
@msg The point type is aligned that way already Teks titik sudah diratakan seperti itu
|
||||
@msg The point type has no transform to reset Teks titik tidak memiliki transformasi untuk diatur ulang
|
||||
@msg No fonts are missing Tidak ada font yang hilang
|
||||
@msg the replacement font is not available font pengganti tidak tersedia
|
||||
@msg missing `align` `align` tidak ada
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` harus lines, paragraphs, words, atau glyphs, bukan {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` harus "line" atau "paragraph", bukan {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` harus "left", "center", atau "right", bukan {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2169 and column 5.
|
@@ -5501,3 +5501,47 @@ anchor Points: Punti:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` indica `inkLimit`, `removeWhiteOverprint` o `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Le correzioni inchiostri di stampa funzionano nei documenti CMYK: scegli prima File › Metodo colore documento › Colore CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` deve essere 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Dividi testo
|
||||
Combine Point Text Combina testo con punto
|
||||
Remove Breaks Rimuovi interruzioni
|
||||
Split Text at Cursor Dividi testo al cursore
|
||||
Set Alignment, Keep Position Imposta allineamento mantenendo la posizione
|
||||
Reset Text Transform Reimposta trasformazione testo
|
||||
Replace Missing Fonts… Sostituisci font mancanti…
|
||||
Replace Missing Fonts Sostituisci font mancanti
|
||||
Remove Line Breaks Rimuovi interruzioni di riga
|
||||
Remove Paragraph Breaks Rimuovi interruzioni di paragrafo
|
||||
Break Text into Lines Dividi testo in righe
|
||||
Break Text into Paragraphs Dividi testo in paragrafi
|
||||
Break Text into Words Dividi testo in parole
|
||||
Break Text into Glyphs Dividi testo in glifi
|
||||
Reset Text Transform and Scale Reimposta trasformazione e scala testo
|
||||
Set Alignment, Keep Position: Imposta allineamento mantenendo la posizione:
|
||||
Break Text into: Dividi testo in:
|
||||
Split at Cursor Dividi al cursore
|
||||
Reset Transform Reimposta trasformazione
|
||||
Shift-click: break into paragraphs Shift+clic: dividi in paragrafi
|
||||
Alt-click: reset the horizontal scale too Alt+clic: reimposta anche la scala orizzontale
|
||||
breakText Lines Righe
|
||||
breakText Words Parole
|
||||
breakText Glyphs Glifi
|
||||
@msg Click in type with a Type tool to split it Fai clic nel testo con uno strumento Testo per dividerlo
|
||||
@msg Too many type objects to change at once Troppi oggetti di testo da modificare in una volta
|
||||
@msg Too many pieces to make at once Troppi pezzi da creare in una volta
|
||||
@msg Select horizontal point or area type whose text fits Seleziona testo con punto o in area orizzontale il cui testo ci sta
|
||||
@msg Nothing to split at the cursor Niente da dividere al cursore
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Seleziona due o più oggetti di testo con punto su una riga sulla stessa linea di base per combinarli
|
||||
@msg No line breaks to remove Nessuna interruzione di riga da rimuovere
|
||||
@msg No paragraph breaks to remove Nessuna interruzione di paragrafo da rimuovere
|
||||
@msg Too many breaks to remove at once Troppe interruzioni da rimuovere in una volta
|
||||
@msg Select point type Seleziona testo con punto
|
||||
@msg The point type is aligned that way already Il testo con punto è già allineato così
|
||||
@msg The point type has no transform to reset Il testo con punto non ha trasformazioni da reimpostare
|
||||
@msg No fonts are missing Non mancano font
|
||||
@msg the replacement font is not available il font sostitutivo non è disponibile
|
||||
@msg missing `align` `align` mancante
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` deve essere lines, paragraphs, words o glyphs, non {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` deve essere "line" o "paragraph", non {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` deve essere "left", "center" o "right", non {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5570,3 +5570,47 @@ anchor Points: ポイント:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` `inkLimit`、`removeWhiteOverprint` または `overprintBlack` を指定してください
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first 印刷インキの修正は CMYK ドキュメントで使用できます。先にファイル › ドキュメントのカラーモード › CMYK カラーを選択してください
|
||||
@msg `{key}` must be 0..{max} `{key}` は 0..{max} にしてください
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text テキストを分割
|
||||
Combine Point Text ポイント文字を結合
|
||||
Remove Breaks 改行を削除
|
||||
Split Text at Cursor カーソル位置でテキストを分割
|
||||
Set Alignment, Keep Position 位置を保って行揃えを設定
|
||||
Reset Text Transform テキストの変形をリセット
|
||||
Replace Missing Fonts… 見つからないフォントを置換…
|
||||
Replace Missing Fonts 見つからないフォントを置換
|
||||
Remove Line Breaks 強制改行を削除
|
||||
Remove Paragraph Breaks 段落の区切りを削除
|
||||
Break Text into Lines テキストを行に分割
|
||||
Break Text into Paragraphs テキストを段落に分割
|
||||
Break Text into Words テキストを単語に分割
|
||||
Break Text into Glyphs テキストを字形に分割
|
||||
Reset Text Transform and Scale テキストの変形と比率をリセット
|
||||
Set Alignment, Keep Position: 位置を保って行揃えを設定:
|
||||
Break Text into: テキストを分割:
|
||||
Split at Cursor カーソル位置で分割
|
||||
Reset Transform 変形をリセット
|
||||
Shift-click: break into paragraphs Shift+クリック:段落に分割
|
||||
Alt-click: reset the horizontal scale too Alt+クリック:水平比率もリセット
|
||||
breakText Lines 行
|
||||
breakText Words 単語
|
||||
breakText Glyphs 字形
|
||||
@msg Click in type with a Type tool to split it 分割するには、文字ツールでテキスト内をクリックしてください
|
||||
@msg Too many type objects to change at once 一度に変更するテキストオブジェクトが多すぎます
|
||||
@msg Too many pieces to make at once 一度に作成する部分が多すぎます
|
||||
@msg Select horizontal point or area type whose text fits テキストが収まっている横組みのポイント文字またはエリア内文字を選択してください
|
||||
@msg Nothing to split at the cursor カーソル位置で分割するものがありません
|
||||
@msg Select two or more one-line point type objects on one baseline to combine 結合するには、同じベースライン上にある 1 行のポイント文字オブジェクトを 2 つ以上選択してください
|
||||
@msg No line breaks to remove 削除する強制改行がありません
|
||||
@msg No paragraph breaks to remove 削除する段落の区切りがありません
|
||||
@msg Too many breaks to remove at once 一度に削除する改行が多すぎます
|
||||
@msg Select point type ポイント文字を選択してください
|
||||
@msg The point type is aligned that way already ポイント文字はすでにその行揃えです
|
||||
@msg The point type has no transform to reset ポイント文字にリセットする変形がありません
|
||||
@msg No fonts are missing 見つからないフォントはありません
|
||||
@msg the replacement font is not available 置換用のフォントを使用できません
|
||||
@msg missing `align` `align` がありません
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` は lines、paragraphs、words、glyphs のいずれかにしてください({other} は使用できません)
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` は "line" または "paragraph" にしてください({other} は使用できません)
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` は "left"、"center"、"right" のいずれかにしてください({other} は使用できません)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5872,3 +5872,47 @@ anchor Points: წერტილები:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` მიუთითეთ `inkLimit`, `removeWhiteOverprint` ან `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first საბეჭდი მელნის შესწორებები მუშაობს CMYK დოკუმენტებზე: ჯერ აირჩიეთ ფაილი › დოკუმენტის ფერის რეჟიმი › CMYK ფერი
|
||||
@msg `{key}` must be 0..{max} `{key}` უნდა იყოს 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text ტექსტის დაყოფა
|
||||
Combine Point Text წერტილის ტექსტის გაერთიანება
|
||||
Remove Breaks წყვეტების წაშლა
|
||||
Split Text at Cursor ტექსტის დაყოფა კურსორთან
|
||||
Set Alignment, Keep Position სწორების დაყენება მდებარეობის შენარჩუნებით
|
||||
Reset Text Transform ტექსტის გარდაქმნის ჩამოყრა
|
||||
Replace Missing Fonts… დაკარგული შრიფტების ჩანაცვლება…
|
||||
Replace Missing Fonts დაკარგული შრიფტების ჩანაცვლება
|
||||
Remove Line Breaks სტრიქონის წყვეტების წაშლა
|
||||
Remove Paragraph Breaks აბზაცის წყვეტების წაშლა
|
||||
Break Text into Lines ტექსტის დაყოფა სტრიქონებად
|
||||
Break Text into Paragraphs ტექსტის დაყოფა აბზაცებად
|
||||
Break Text into Words ტექსტის დაყოფა სიტყვებად
|
||||
Break Text into Glyphs ტექსტის დაყოფა გლიფებად
|
||||
Reset Text Transform and Scale ტექსტის გარდაქმნისა და მასშტაბის ჩამოყრა
|
||||
Set Alignment, Keep Position: სწორების დაყენება მდებარეობის შენარჩუნებით:
|
||||
Break Text into: ტექსტის დაყოფა:
|
||||
Split at Cursor დაყოფა კურსორთან
|
||||
Reset Transform გარდაქმნის ჩამოყრა
|
||||
Shift-click: break into paragraphs Shift-დაწკაპუნება: დაყოფა აბზაცებად
|
||||
Alt-click: reset the horizontal scale too Alt-დაწკაპუნება: ჰორიზონტალური მასშტაბის ჩამოყრაც
|
||||
breakText Lines სტრიქონები
|
||||
breakText Words სიტყვები
|
||||
breakText Glyphs გლიფები
|
||||
@msg Click in type with a Type tool to split it დასაყოფად დააწკაპუნეთ ტექსტში ტექსტის ხელსაწყოთი
|
||||
@msg Too many type objects to change at once ერთდროულად შესაცვლელად ძალიან ბევრი ტექსტური ობიექტია
|
||||
@msg Too many pieces to make at once ერთდროულად შესაქმნელად ძალიან ბევრი ნაწილია
|
||||
@msg Select horizontal point or area type whose text fits აირჩიეთ ჰორიზონტალური წერტილის ან არის ტექსტი, რომლის ტექსტიც ეტევა
|
||||
@msg Nothing to split at the cursor კურსორთან დასაყოფი არაფერია
|
||||
@msg Select two or more one-line point type objects on one baseline to combine გასაერთიანებლად აირჩიეთ ერთ საბაზისო ხაზზე მდებარე ორი ან მეტი ერთსტრიქონიანი წერტილის ტექსტის ობიექტი
|
||||
@msg No line breaks to remove წასაშლელი სტრიქონის წყვეტები არ არის
|
||||
@msg No paragraph breaks to remove წასაშლელი აბზაცის წყვეტები არ არის
|
||||
@msg Too many breaks to remove at once ერთდროულად წასაშლელად ძალიან ბევრი წყვეტაა
|
||||
@msg Select point type აირჩიეთ წერტილის ტექსტი
|
||||
@msg The point type is aligned that way already წერტილის ტექსტი უკვე ასეა სწორებული
|
||||
@msg The point type has no transform to reset წერტილის ტექსტს ჩამოსაყრელი გარდაქმნა არ აქვს
|
||||
@msg No fonts are missing დაკარგული შრიფტები არ არის
|
||||
@msg the replacement font is not available ჩამნაცვლებელი შრიფტი მიუწვდომელია
|
||||
@msg missing `align` `align` აკლია
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` უნდა იყოს lines, paragraphs, words ან glyphs და არა {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` უნდა იყოს "line" ან "paragraph" და არა {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` უნდა იყოს "left", "center" ან "right" და არა {other}
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -5464,3 +5464,47 @@ anchor Points: 포인트:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` `inkLimit`, `removeWhiteOverprint` 또는 `overprintBlack`을 지정하십시오
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first 인쇄 잉크 수정은 CMYK 문서에서 작동합니다. 먼저 파일 › 문서 색상 모드 › CMYK 색상을 선택하십시오
|
||||
@msg `{key}` must be 0..{max} `{key}`은(는) 0..{max}이어야 합니다
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text 텍스트 나누기
|
||||
Combine Point Text 포인트 문자 결합
|
||||
Remove Breaks 나누기 제거
|
||||
Split Text at Cursor 커서 위치에서 텍스트 나누기
|
||||
Set Alignment, Keep Position 위치를 유지하며 정렬 설정
|
||||
Reset Text Transform 텍스트 변형 재설정
|
||||
Replace Missing Fonts… 누락된 글꼴 바꾸기…
|
||||
Replace Missing Fonts 누락된 글꼴 바꾸기
|
||||
Remove Line Breaks 강제 줄 바꿈 제거
|
||||
Remove Paragraph Breaks 단락 나누기 제거
|
||||
Break Text into Lines 텍스트를 줄로 나누기
|
||||
Break Text into Paragraphs 텍스트를 단락으로 나누기
|
||||
Break Text into Words 텍스트를 단어로 나누기
|
||||
Break Text into Glyphs 텍스트를 글리프로 나누기
|
||||
Reset Text Transform and Scale 텍스트 변형 및 비율 재설정
|
||||
Set Alignment, Keep Position: 위치를 유지하며 정렬 설정:
|
||||
Break Text into: 텍스트 나누기:
|
||||
Split at Cursor 커서 위치에서 나누기
|
||||
Reset Transform 변형 재설정
|
||||
Shift-click: break into paragraphs Shift-클릭: 단락으로 나누기
|
||||
Alt-click: reset the horizontal scale too Alt-클릭: 가로 비율도 재설정
|
||||
breakText Lines 줄
|
||||
breakText Words 단어
|
||||
breakText Glyphs 글리프
|
||||
@msg Click in type with a Type tool to split it 나누려면 문자 도구로 텍스트 안을 클릭하십시오
|
||||
@msg Too many type objects to change at once 한 번에 변경할 문자 오브젝트가 너무 많습니다
|
||||
@msg Too many pieces to make at once 한 번에 만들 조각이 너무 많습니다
|
||||
@msg Select horizontal point or area type whose text fits 텍스트가 모두 들어가는 가로 포인트 문자 또는 영역 문자를 선택하십시오
|
||||
@msg Nothing to split at the cursor 커서 위치에서 나눌 내용이 없습니다
|
||||
@msg Select two or more one-line point type objects on one baseline to combine 결합하려면 같은 기준선에 있는 한 줄짜리 포인트 문자 오브젝트를 두 개 이상 선택하십시오
|
||||
@msg No line breaks to remove 제거할 강제 줄 바꿈이 없습니다
|
||||
@msg No paragraph breaks to remove 제거할 단락 나누기가 없습니다
|
||||
@msg Too many breaks to remove at once 한 번에 제거할 나누기가 너무 많습니다
|
||||
@msg Select point type 포인트 문자를 선택하십시오
|
||||
@msg The point type is aligned that way already 포인트 문자가 이미 그렇게 정렬되어 있습니다
|
||||
@msg The point type has no transform to reset 포인트 문자에 재설정할 변형이 없습니다
|
||||
@msg No fonts are missing 누락된 글꼴이 없습니다
|
||||
@msg the replacement font is not available 대체 글꼴을 사용할 수 없습니다
|
||||
@msg missing `align` `align`이 없습니다
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by`는 lines, paragraphs, words 또는 glyphs여야 합니다({other}는 사용할 수 없음)
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind`는 "line" 또는 "paragraph"여야 합니다({other}는 사용할 수 없음)
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align`은 "left", "center" 또는 "right"여야 합니다({other}는 사용할 수 없음)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5831,3 +5831,47 @@ anchor Points: Punten:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` geef `inkLimit`, `removeWhiteOverprint` of `overprintBlack` op
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Drukinktcorrecties werken in CMYK-documenten: kies eerst Bestand › Documentkleurmodus › CMYK-kleur
|
||||
@msg `{key}` must be 0..{max} `{key}` moet 0..{max} zijn
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Tekst splitsen
|
||||
Combine Point Text Punttekst combineren
|
||||
Remove Breaks Einden verwijderen
|
||||
Split Text at Cursor Tekst splitsen bij cursor
|
||||
Set Alignment, Keep Position Uitlijning instellen, positie behouden
|
||||
Reset Text Transform Teksttransformatie herstellen
|
||||
Replace Missing Fonts… Ontbrekende lettertypen vervangen…
|
||||
Replace Missing Fonts Ontbrekende lettertypen vervangen
|
||||
Remove Line Breaks Regeleinden verwijderen
|
||||
Remove Paragraph Breaks Alinea-einden verwijderen
|
||||
Break Text into Lines Tekst splitsen in regels
|
||||
Break Text into Paragraphs Tekst splitsen in alinea's
|
||||
Break Text into Words Tekst splitsen in woorden
|
||||
Break Text into Glyphs Tekst splitsen in glyphs
|
||||
Reset Text Transform and Scale Teksttransformatie en schaal herstellen
|
||||
Set Alignment, Keep Position: Uitlijning instellen, positie behouden:
|
||||
Break Text into: Tekst splitsen in:
|
||||
Split at Cursor Splitsen bij cursor
|
||||
Reset Transform Transformatie herstellen
|
||||
Shift-click: break into paragraphs Shift-klik: splitsen in alinea's
|
||||
Alt-click: reset the horizontal scale too Alt-klik: ook de horizontale schaal herstellen
|
||||
breakText Lines Regels
|
||||
breakText Words Woorden
|
||||
breakText Glyphs Glyphs
|
||||
@msg Click in type with a Type tool to split it Klik met een Type-gereedschap in tekst om deze te splitsen
|
||||
@msg Too many type objects to change at once Te veel tekstobjecten om in één keer te wijzigen
|
||||
@msg Too many pieces to make at once Te veel stukken om in één keer te maken
|
||||
@msg Select horizontal point or area type whose text fits Selecteer horizontale punt- of vlaktekst waarvan de tekst past
|
||||
@msg Nothing to split at the cursor Niets te splitsen bij de cursor
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Selecteer twee of meer punttekstobjecten van één regel op één basislijn om ze te combineren
|
||||
@msg No line breaks to remove Geen regeleinden om te verwijderen
|
||||
@msg No paragraph breaks to remove Geen alinea-einden om te verwijderen
|
||||
@msg Too many breaks to remove at once Te veel einden om in één keer te verwijderen
|
||||
@msg Select point type Selecteer punttekst
|
||||
@msg The point type is aligned that way already De punttekst is al zo uitgelijnd
|
||||
@msg The point type has no transform to reset De punttekst heeft geen transformatie om te herstellen
|
||||
@msg No fonts are missing Er ontbreken geen lettertypen
|
||||
@msg the replacement font is not available het vervangende lettertype is niet beschikbaar
|
||||
@msg missing `align` `align` ontbreekt
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` moet lines, paragraphs, words of glyphs zijn, niet {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` moet "line" of "paragraph" zijn, niet {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` moet "left", "center" of "right" zijn, niet {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5737,3 +5737,47 @@ anchor Points: Punkty:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` podaj `inkLimit`, `removeWhiteOverprint` lub `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Poprawki farb drukarskich działają w dokumentach CMYK: najpierw wybierz Plik › Tryb koloru dokumentu › Kolor CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` musi wynosić 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Podziel tekst
|
||||
Combine Point Text Połącz tekst punktowy
|
||||
Remove Breaks Usuń podziały
|
||||
Split Text at Cursor Podziel tekst w miejscu kursora
|
||||
Set Alignment, Keep Position Ustaw wyrównanie, zachowaj położenie
|
||||
Reset Text Transform Resetuj przekształcenie tekstu
|
||||
Replace Missing Fonts… Zastąp brakujące czcionki…
|
||||
Replace Missing Fonts Zastąp brakujące czcionki
|
||||
Remove Line Breaks Usuń podziały wiersza
|
||||
Remove Paragraph Breaks Usuń podziały akapitu
|
||||
Break Text into Lines Podziel tekst na wiersze
|
||||
Break Text into Paragraphs Podziel tekst na akapity
|
||||
Break Text into Words Podziel tekst na słowa
|
||||
Break Text into Glyphs Podziel tekst na glify
|
||||
Reset Text Transform and Scale Resetuj przekształcenie i skalę tekstu
|
||||
Set Alignment, Keep Position: Ustaw wyrównanie, zachowaj położenie:
|
||||
Break Text into: Podziel tekst na:
|
||||
Split at Cursor Podziel w miejscu kursora
|
||||
Reset Transform Resetuj przekształcenie
|
||||
Shift-click: break into paragraphs Kliknięcie z Shift: podziel na akapity
|
||||
Alt-click: reset the horizontal scale too Kliknięcie z Alt: resetuj także skalę poziomą
|
||||
breakText Lines Wiersze
|
||||
breakText Words Słowa
|
||||
breakText Glyphs Glify
|
||||
@msg Click in type with a Type tool to split it Kliknij w tekst narzędziem Tekst, aby go podzielić
|
||||
@msg Too many type objects to change at once Zbyt wiele obiektów tekstowych do zmiany naraz
|
||||
@msg Too many pieces to make at once Zbyt wiele części do utworzenia naraz
|
||||
@msg Select horizontal point or area type whose text fits Zaznacz poziomy tekst punktowy lub akapitowy, którego tekst się mieści
|
||||
@msg Nothing to split at the cursor Nie ma nic do podzielenia w miejscu kursora
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Zaznacz co najmniej dwa jednowierszowe obiekty tekstu punktowego na jednej linii bazowej, aby je połączyć
|
||||
@msg No line breaks to remove Brak podziałów wiersza do usunięcia
|
||||
@msg No paragraph breaks to remove Brak podziałów akapitu do usunięcia
|
||||
@msg Too many breaks to remove at once Zbyt wiele podziałów do usunięcia naraz
|
||||
@msg Select point type Zaznacz tekst punktowy
|
||||
@msg The point type is aligned that way already Tekst punktowy jest już tak wyrównany
|
||||
@msg The point type has no transform to reset Tekst punktowy nie ma przekształcenia do zresetowania
|
||||
@msg No fonts are missing Nie brakuje żadnych czcionek
|
||||
@msg the replacement font is not available czcionka zastępcza jest niedostępna
|
||||
@msg missing `align` brak `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` musi mieć wartość lines, paragraphs, words lub glyphs, a nie {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` musi mieć wartość "line" lub "paragraph", a nie {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` musi mieć wartość "left", "center" lub "right", a nie {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5800,3 +5800,47 @@ anchor Points: Pontos:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` informe `inkLimit`, `removeWhiteOverprint` ou `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first As Correções de Tinta para Impressão funcionam em documentos CMYK: escolha antes Arquivo › Modo de Cor do Documento › Cor CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` deve ser 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Dividir Texto
|
||||
Combine Point Text Combinar Texto de Ponto
|
||||
Remove Breaks Remover Quebras
|
||||
Split Text at Cursor Dividir Texto no Cursor
|
||||
Set Alignment, Keep Position Definir Alinhamento, Manter Posição
|
||||
Reset Text Transform Redefinir Transformação do Texto
|
||||
Replace Missing Fonts… Substituir Fontes Ausentes…
|
||||
Replace Missing Fonts Substituir Fontes Ausentes
|
||||
Remove Line Breaks Remover Quebras de Linha
|
||||
Remove Paragraph Breaks Remover Quebras de Parágrafo
|
||||
Break Text into Lines Dividir Texto em Linhas
|
||||
Break Text into Paragraphs Dividir Texto em Parágrafos
|
||||
Break Text into Words Dividir Texto em Palavras
|
||||
Break Text into Glyphs Dividir Texto em Glifos
|
||||
Reset Text Transform and Scale Redefinir Transformação e Escala do Texto
|
||||
Set Alignment, Keep Position: Definir Alinhamento, Manter Posição:
|
||||
Break Text into: Dividir Texto em:
|
||||
Split at Cursor Dividir no Cursor
|
||||
Reset Transform Redefinir Transformação
|
||||
Shift-click: break into paragraphs Clique com Shift: dividir em parágrafos
|
||||
Alt-click: reset the horizontal scale too Alt-clique: redefinir também a escala horizontal
|
||||
breakText Lines Linhas
|
||||
breakText Words Palavras
|
||||
breakText Glyphs Glifos
|
||||
@msg Click in type with a Type tool to split it Clique em um texto com uma ferramenta Texto para dividi-lo
|
||||
@msg Too many type objects to change at once Objetos de texto demais para alterar de uma vez
|
||||
@msg Too many pieces to make at once Partes demais para criar de uma vez
|
||||
@msg Select horizontal point or area type whose text fits Selecione texto de ponto ou de área horizontal cujo texto caiba
|
||||
@msg Nothing to split at the cursor Nada a dividir no cursor
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Selecione dois ou mais objetos de texto de ponto de uma linha na mesma linha de base para combiná-los
|
||||
@msg No line breaks to remove Nenhuma quebra de linha a remover
|
||||
@msg No paragraph breaks to remove Nenhuma quebra de parágrafo a remover
|
||||
@msg Too many breaks to remove at once Quebras demais para remover de uma vez
|
||||
@msg Select point type Selecione texto de ponto
|
||||
@msg The point type is aligned that way already O texto de ponto já está alinhado assim
|
||||
@msg The point type has no transform to reset O texto de ponto não tem transformação a redefinir
|
||||
@msg No fonts are missing Nenhuma fonte está ausente
|
||||
@msg the replacement font is not available a fonte substituta não está disponível
|
||||
@msg missing `align` `align` ausente
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` deve ser lines, paragraphs, words ou glyphs, não {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` deve ser "line" ou "paragraph", não {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` deve ser "left", "center" ou "right", não {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -5860,3 +5860,47 @@ anchor Points: Точки:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` задайте `inkLimit`, `removeWhiteOverprint` или `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Исправления печатных красок работают в документах CMYK: сначала выберите Файл › Цветовой режим документа › Цвет CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` должен быть 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Разбить текст
|
||||
Combine Point Text Объединить текст из точки
|
||||
Remove Breaks Удалить разрывы
|
||||
Split Text at Cursor Разбить текст у курсора
|
||||
Set Alignment, Keep Position Задать выравнивание, сохранив положение
|
||||
Reset Text Transform Сбросить трансформацию текста
|
||||
Replace Missing Fonts… Заменить отсутствующие шрифты…
|
||||
Replace Missing Fonts Заменить отсутствующие шрифты
|
||||
Remove Line Breaks Удалить разрывы строк
|
||||
Remove Paragraph Breaks Удалить разрывы абзацев
|
||||
Break Text into Lines Разбить текст на строки
|
||||
Break Text into Paragraphs Разбить текст на абзацы
|
||||
Break Text into Words Разбить текст на слова
|
||||
Break Text into Glyphs Разбить текст на глифы
|
||||
Reset Text Transform and Scale Сбросить трансформацию и масштаб текста
|
||||
Set Alignment, Keep Position: Выравнивание с сохранением положения:
|
||||
Break Text into: Разбить текст на:
|
||||
Split at Cursor Разбить у курсора
|
||||
Reset Transform Сбросить трансформацию
|
||||
Shift-click: break into paragraphs Shift+щелчок: разбить на абзацы
|
||||
Alt-click: reset the horizontal scale too Alt+щелчок: сбросить и масштаб по горизонтали
|
||||
breakText Lines Строки
|
||||
breakText Words Слова
|
||||
breakText Glyphs Глифы
|
||||
@msg Click in type with a Type tool to split it Щёлкните в тексте инструментом «Текст», чтобы разбить его
|
||||
@msg Too many type objects to change at once Слишком много текстовых объектов для изменения за один раз
|
||||
@msg Too many pieces to make at once Слишком много частей для создания за один раз
|
||||
@msg Select horizontal point or area type whose text fits Выделите горизонтальный текст из точки или в области, текст которого помещается
|
||||
@msg Nothing to split at the cursor У курсора нечего разбивать
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Выделите два или более однострочных объекта текста из точки на одной базовой линии, чтобы объединить их
|
||||
@msg No line breaks to remove Нет разрывов строк для удаления
|
||||
@msg No paragraph breaks to remove Нет разрывов абзацев для удаления
|
||||
@msg Too many breaks to remove at once Слишком много разрывов для удаления за один раз
|
||||
@msg Select point type Выделите текст из точки
|
||||
@msg The point type is aligned that way already Текст из точки уже так выровнен
|
||||
@msg The point type has no transform to reset У текста из точки нет трансформации для сброса
|
||||
@msg No fonts are missing Отсутствующих шрифтов нет
|
||||
@msg the replacement font is not available шрифт для замены недоступен
|
||||
@msg missing `align` не указан `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` должен быть lines, paragraphs, words или glyphs, а не {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` должен быть "line" или "paragraph", а не {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` должен быть "left", "center" или "right", а не {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5938,3 +5938,47 @@ shape Open Öppen
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` ange `inkLimit`, `removeWhiteOverprint` eller `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Tryckfärgskorrigeringar fungerar i CMYK-dokument: välj först Fil › Dokumentets färgläge › CMYK-färg
|
||||
@msg `{key}` must be 0..{max} `{key}` måste vara 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Dela upp text
|
||||
Combine Point Text Kombinera punkttext
|
||||
Remove Breaks Ta bort brytningar
|
||||
Split Text at Cursor Dela text vid markören
|
||||
Set Alignment, Keep Position Ställ in justering, behåll position
|
||||
Reset Text Transform Återställ texttransformering
|
||||
Replace Missing Fonts… Ersätt saknade typsnitt…
|
||||
Replace Missing Fonts Ersätt saknade typsnitt
|
||||
Remove Line Breaks Ta bort radbrytningar
|
||||
Remove Paragraph Breaks Ta bort styckebrytningar
|
||||
Break Text into Lines Dela upp text i rader
|
||||
Break Text into Paragraphs Dela upp text i stycken
|
||||
Break Text into Words Dela upp text i ord
|
||||
Break Text into Glyphs Dela upp text i glyfer
|
||||
Reset Text Transform and Scale Återställ texttransformering och skala
|
||||
Set Alignment, Keep Position: Ställ in justering, behåll position:
|
||||
Break Text into: Dela upp text i:
|
||||
Split at Cursor Dela vid markören
|
||||
Reset Transform Återställ transformering
|
||||
Shift-click: break into paragraphs Shift-klicka: dela upp i stycken
|
||||
Alt-click: reset the horizontal scale too Alt-klick: återställ även den horisontella skalan
|
||||
breakText Lines Rader
|
||||
breakText Words Ord
|
||||
breakText Glyphs Glyfer
|
||||
@msg Click in type with a Type tool to split it Klicka i text med ett textverktyg för att dela den
|
||||
@msg Too many type objects to change at once För många textobjekt att ändra på en gång
|
||||
@msg Too many pieces to make at once För många delar att skapa på en gång
|
||||
@msg Select horizontal point or area type whose text fits Markera vågrät punkt- eller områdestext vars text får plats
|
||||
@msg Nothing to split at the cursor Inget att dela vid markören
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Markera två eller fler enradiga punkttextobjekt på samma baslinje för att kombinera dem
|
||||
@msg No line breaks to remove Inga radbrytningar att ta bort
|
||||
@msg No paragraph breaks to remove Inga styckebrytningar att ta bort
|
||||
@msg Too many breaks to remove at once För många brytningar att ta bort på en gång
|
||||
@msg Select point type Markera punkttext
|
||||
@msg The point type is aligned that way already Punkttexten är redan justerad så
|
||||
@msg The point type has no transform to reset Punkttexten har ingen transformering att återställa
|
||||
@msg No fonts are missing Inga typsnitt saknas
|
||||
@msg the replacement font is not available ersättningstypsnittet är inte tillgängligt
|
||||
@msg missing `align` `align` saknas
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` måste vara lines, paragraphs, words eller glyphs, inte {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` måste vara "line" eller "paragraph", inte {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` måste vara "left", "center" eller "right", inte {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -5840,3 +5840,47 @@ anchor Points: Noktalar:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` `inkLimit`, `removeWhiteOverprint` veya `overprintBlack` verin
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Baskı Mürekkebi Düzeltmeleri CMYK belgelerinde çalışır: önce Dosya › Belge Renk Modu › CMYK Rengi'ni seçin
|
||||
@msg `{key}` must be 0..{max} `{key}` 0..{max} olmalıdır
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Metni Böl
|
||||
Combine Point Text Nokta Metnini Birleştir
|
||||
Remove Breaks Kesmeleri Kaldır
|
||||
Split Text at Cursor Metni İmleçte Böl
|
||||
Set Alignment, Keep Position Hizalamayı Ayarla, Konumu Koru
|
||||
Reset Text Transform Metin Dönüşümünü Sıfırla
|
||||
Replace Missing Fonts… Eksik Yazı Tiplerini Değiştir…
|
||||
Replace Missing Fonts Eksik Yazı Tiplerini Değiştir
|
||||
Remove Line Breaks Satır Sonlarını Kaldır
|
||||
Remove Paragraph Breaks Paragraf Sonlarını Kaldır
|
||||
Break Text into Lines Metni Satırlara Böl
|
||||
Break Text into Paragraphs Metni Paragraflara Böl
|
||||
Break Text into Words Metni Sözcüklere Böl
|
||||
Break Text into Glyphs Metni Gliflere Böl
|
||||
Reset Text Transform and Scale Metin Dönüşümünü ve Ölçeğini Sıfırla
|
||||
Set Alignment, Keep Position: Hizalamayı Ayarla, Konumu Koru:
|
||||
Break Text into: Metni Böl:
|
||||
Split at Cursor İmleçte Böl
|
||||
Reset Transform Dönüşümü Sıfırla
|
||||
Shift-click: break into paragraphs Shift tuşuyla tıklayın: paragraflara böl
|
||||
Alt-click: reset the horizontal scale too Alt tuşuyla tıklayın: yatay ölçeği de sıfırla
|
||||
breakText Lines Satırlar
|
||||
breakText Words Sözcükler
|
||||
breakText Glyphs Glifler
|
||||
@msg Click in type with a Type tool to split it Bölmek için bir Yazım Aracıyla metnin içine tıklayın
|
||||
@msg Too many type objects to change at once Bir kerede değiştirilecek çok fazla metin nesnesi var
|
||||
@msg Too many pieces to make at once Bir kerede oluşturulacak çok fazla parça var
|
||||
@msg Select horizontal point or area type whose text fits Metni sığan yatay nokta veya alan metni seçin
|
||||
@msg Nothing to split at the cursor İmleçte bölünecek bir şey yok
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Birleştirmek için aynı taban çizgisinde iki veya daha fazla tek satırlı nokta metni nesnesi seçin
|
||||
@msg No line breaks to remove Kaldırılacak satır sonu yok
|
||||
@msg No paragraph breaks to remove Kaldırılacak paragraf sonu yok
|
||||
@msg Too many breaks to remove at once Bir kerede kaldırılacak çok fazla kesme var
|
||||
@msg Select point type Nokta metni seçin
|
||||
@msg The point type is aligned that way already Nokta metni zaten bu şekilde hizalı
|
||||
@msg The point type has no transform to reset Nokta metninin sıfırlanacak dönüşümü yok
|
||||
@msg No fonts are missing Eksik yazı tipi yok
|
||||
@msg the replacement font is not available yedek yazı tipi kullanılamıyor
|
||||
@msg missing `align` `align` eksik
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by`, lines, paragraphs, words veya glyphs olmalı, {other} değil
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind`, "line" veya "paragraph" olmalı, {other} değil
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align`, "left", "center" veya "right" olmalı, {other} değil
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -5481,3 +5481,47 @@ anchor Points: Точки:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` задайте `inkLimit`, `removeWhiteOverprint` або `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Виправлення друкарських фарб працюють у документах CMYK: спершу виберіть Файл › Колірний режим документа › Колір CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` має бути 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Розбити текст
|
||||
Combine Point Text Об’єднати текст із точки
|
||||
Remove Breaks Видалити розриви
|
||||
Split Text at Cursor Розбити текст біля курсора
|
||||
Set Alignment, Keep Position Задати вирівнювання, зберігши положення
|
||||
Reset Text Transform Скинути трансформацію тексту
|
||||
Replace Missing Fonts… Замінити відсутні шрифти…
|
||||
Replace Missing Fonts Замінити відсутні шрифти
|
||||
Remove Line Breaks Видалити розриви рядків
|
||||
Remove Paragraph Breaks Видалити розриви абзаців
|
||||
Break Text into Lines Розбити текст на рядки
|
||||
Break Text into Paragraphs Розбити текст на абзаци
|
||||
Break Text into Words Розбити текст на слова
|
||||
Break Text into Glyphs Розбити текст на гліфи
|
||||
Reset Text Transform and Scale Скинути трансформацію та масштаб тексту
|
||||
Set Alignment, Keep Position: Вирівнювання зі збереженням положення:
|
||||
Break Text into: Розбити текст на:
|
||||
Split at Cursor Розбити біля курсора
|
||||
Reset Transform Скинути трансформацію
|
||||
Shift-click: break into paragraphs Shift+клацання: розбити на абзаци
|
||||
Alt-click: reset the horizontal scale too Alt+клацання: скинути й горизонтальний масштаб
|
||||
breakText Lines Рядки
|
||||
breakText Words Слова
|
||||
breakText Glyphs Гліфи
|
||||
@msg Click in type with a Type tool to split it Клацніть у тексті інструментом «Текст», щоб розбити його
|
||||
@msg Too many type objects to change at once Забагато текстових об’єктів, щоб змінити їх за раз
|
||||
@msg Too many pieces to make at once Забагато частин, щоб створити їх за раз
|
||||
@msg Select horizontal point or area type whose text fits Виділіть горизонтальний текст із точки або в області, текст якого вміщується
|
||||
@msg Nothing to split at the cursor Біля курсора нічого розбивати
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Виділіть два або більше однорядкових об’єктів тексту з точки на одній базовій лінії, щоб об’єднати їх
|
||||
@msg No line breaks to remove Немає розривів рядків для видалення
|
||||
@msg No paragraph breaks to remove Немає розривів абзаців для видалення
|
||||
@msg Too many breaks to remove at once Забагато розривів, щоб видалити їх за раз
|
||||
@msg Select point type Виділіть текст із точки
|
||||
@msg The point type is aligned that way already Текст із точки вже так вирівняно
|
||||
@msg The point type has no transform to reset Текст із точки не має трансформації для скидання
|
||||
@msg No fonts are missing Відсутніх шрифтів немає
|
||||
@msg the replacement font is not available шрифт для заміни недоступний
|
||||
@msg missing `align` не вказано `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` має бути lines, paragraphs, words або glyphs, а не {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` має бути "line" або "paragraph", а не {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` має бути "left", "center" або "right", а не {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 178 and column 5.
|
@@ -5483,3 +5483,47 @@ anchor Points: Điểm:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` hãy cho `inkLimit`, `removeWhiteOverprint` hoặc `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first Sửa mực in hoạt động trên tài liệu CMYK: trước hết chọn Tệp › Chế độ màu tài liệu › Màu CMYK
|
||||
@msg `{key}` must be 0..{max} `{key}` phải là 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text Tách văn bản
|
||||
Combine Point Text Kết hợp chữ điểm
|
||||
Remove Breaks Xóa ngắt
|
||||
Split Text at Cursor Tách văn bản tại con trỏ
|
||||
Set Alignment, Keep Position Đặt căn lề, giữ vị trí
|
||||
Reset Text Transform Đặt lại biến đổi văn bản
|
||||
Replace Missing Fonts… Thay thế phông chữ thiếu…
|
||||
Replace Missing Fonts Thay thế phông chữ thiếu
|
||||
Remove Line Breaks Xóa xuống dòng
|
||||
Remove Paragraph Breaks Xóa ngắt đoạn
|
||||
Break Text into Lines Tách văn bản thành dòng
|
||||
Break Text into Paragraphs Tách văn bản thành đoạn
|
||||
Break Text into Words Tách văn bản thành từ
|
||||
Break Text into Glyphs Tách văn bản thành glyph
|
||||
Reset Text Transform and Scale Đặt lại biến đổi và tỷ lệ văn bản
|
||||
Set Alignment, Keep Position: Đặt căn lề, giữ vị trí:
|
||||
Break Text into: Tách văn bản thành:
|
||||
Split at Cursor Tách tại con trỏ
|
||||
Reset Transform Đặt lại biến đổi
|
||||
Shift-click: break into paragraphs Shift-bấm: tách thành đoạn
|
||||
Alt-click: reset the horizontal scale too Alt-bấm: đặt lại cả tỷ lệ ngang
|
||||
breakText Lines Dòng
|
||||
breakText Words Từ
|
||||
breakText Glyphs Glyph
|
||||
@msg Click in type with a Type tool to split it Nhấp vào văn bản bằng công cụ Chữ để tách văn bản
|
||||
@msg Too many type objects to change at once Quá nhiều đối tượng chữ để thay đổi cùng lúc
|
||||
@msg Too many pieces to make at once Quá nhiều phần để tạo cùng lúc
|
||||
@msg Select horizontal point or area type whose text fits Chọn chữ điểm hoặc chữ vùng nằm ngang có văn bản vừa khung
|
||||
@msg Nothing to split at the cursor Không có gì để tách tại con trỏ
|
||||
@msg Select two or more one-line point type objects on one baseline to combine Chọn hai đối tượng chữ điểm một dòng trở lên trên cùng một đường cơ sở để kết hợp
|
||||
@msg No line breaks to remove Không có xuống dòng nào để xóa
|
||||
@msg No paragraph breaks to remove Không có ngắt đoạn nào để xóa
|
||||
@msg Too many breaks to remove at once Quá nhiều ngắt để xóa cùng lúc
|
||||
@msg Select point type Chọn chữ điểm
|
||||
@msg The point type is aligned that way already Chữ điểm đã được căn như vậy
|
||||
@msg The point type has no transform to reset Chữ điểm không có biến đổi nào để đặt lại
|
||||
@msg No fonts are missing Không thiếu phông chữ nào
|
||||
@msg the replacement font is not available phông chữ thay thế không có sẵn
|
||||
@msg missing `align` thiếu `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` phải là lines, paragraphs, words hoặc glyphs, không phải {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` phải là "line" hoặc "paragraph", không phải {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` phải là "left", "center" hoặc "right", không phải {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 200 and column 5.
|
@@ -5724,3 +5724,47 @@ anchor Points: 点:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` 请指定 `inkLimit`、`removeWhiteOverprint` 或 `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first 印刷油墨修正适用于 CMYK 文档:请先选择 文件 › 文档颜色模式 › CMYK 颜色
|
||||
@msg `{key}` must be 0..{max} `{key}` 必须为 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text 拆分文本
|
||||
Combine Point Text 合并点文字
|
||||
Remove Breaks 删除换行
|
||||
Split Text at Cursor 在光标处拆分文本
|
||||
Set Alignment, Keep Position 设置对齐并保持位置
|
||||
Reset Text Transform 重置文本变换
|
||||
Replace Missing Fonts… 替换缺失的字体…
|
||||
Replace Missing Fonts 替换缺失的字体
|
||||
Remove Line Breaks 删除强制换行
|
||||
Remove Paragraph Breaks 删除段落换行
|
||||
Break Text into Lines 将文本拆分为行
|
||||
Break Text into Paragraphs 将文本拆分为段落
|
||||
Break Text into Words 将文本拆分为单词
|
||||
Break Text into Glyphs 将文本拆分为字形
|
||||
Reset Text Transform and Scale 重置文本变换和缩放
|
||||
Set Alignment, Keep Position: 设置对齐并保持位置:
|
||||
Break Text into: 将文本拆分为:
|
||||
Split at Cursor 在光标处拆分
|
||||
Reset Transform 重置变换
|
||||
Shift-click: break into paragraphs Shift+单击:拆分为段落
|
||||
Alt-click: reset the horizontal scale too Alt+点击:同时重置水平缩放
|
||||
breakText Lines 行
|
||||
breakText Words 单词
|
||||
breakText Glyphs 字形
|
||||
@msg Click in type with a Type tool to split it 请用文字工具在文字中单击以拆分
|
||||
@msg Too many type objects to change at once 一次要更改的文字对象过多
|
||||
@msg Too many pieces to make at once 一次要创建的部分过多
|
||||
@msg Select horizontal point or area type whose text fits 请选择文本能完全容纳的横排点文字或区域文字
|
||||
@msg Nothing to split at the cursor 光标处没有可拆分的内容
|
||||
@msg Select two or more one-line point type objects on one baseline to combine 请选择同一基线上两个或更多单行点文字对象以合并
|
||||
@msg No line breaks to remove 没有要删除的强制换行
|
||||
@msg No paragraph breaks to remove 没有要删除的段落换行
|
||||
@msg Too many breaks to remove at once 一次要删除的换行过多
|
||||
@msg Select point type 请选择点文字
|
||||
@msg The point type is aligned that way already 点文字已经是这种对齐方式
|
||||
@msg The point type has no transform to reset 点文字没有可重置的变换
|
||||
@msg No fonts are missing 没有缺失的字体
|
||||
@msg the replacement font is not available 替换字体不可用
|
||||
@msg missing `align` 缺少 `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` 必须是 lines、paragraphs、words 或 glyphs,而不是 {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` 必须是 "line" 或 "paragraph",而不是 {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` 必须是 "left"、"center" 或 "right",而不是 {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5520,3 +5520,47 @@ anchor Points: 點:
|
||||
@msg give `inkLimit`, `removeWhiteOverprint` or `overprintBlack` 請指定 `inkLimit`、`removeWhiteOverprint` 或 `overprintBlack`
|
||||
@msg Print Ink Fixes works on CMYK documents: choose File › Document Color Mode › CMYK Color first 印刷油墨修正適用於 CMYK 文件:請先選擇 檔案 › 文件色彩模式 › CMYK 色彩
|
||||
@msg `{key}` must be 0..{max} `{key}` 必須為 0..{max}
|
||||
|
||||
# Artwork Cleanup add-on: its text tools (Object › Plug-ins › Artwork Cleanup and the panel's Text row) and their messages.
|
||||
Break Text 分割文字
|
||||
Combine Point Text 合併點文字
|
||||
Remove Breaks 移除換行
|
||||
Split Text at Cursor 在游標處分割文字
|
||||
Set Alignment, Keep Position 設定對齊並保持位置
|
||||
Reset Text Transform 重設文字變形
|
||||
Replace Missing Fonts… 取代遺失的字體…
|
||||
Replace Missing Fonts 取代遺失的字體
|
||||
Remove Line Breaks 移除強制換行
|
||||
Remove Paragraph Breaks 移除段落換行
|
||||
Break Text into Lines 將文字分割為行
|
||||
Break Text into Paragraphs 將文字分割為段落
|
||||
Break Text into Words 將文字分割為單字
|
||||
Break Text into Glyphs 將文字分割為字符
|
||||
Reset Text Transform and Scale 重設文字變形與縮放
|
||||
Set Alignment, Keep Position: 設定對齊並保持位置:
|
||||
Break Text into: 將文字分割為:
|
||||
Split at Cursor 在游標處分割
|
||||
Reset Transform 重設變形
|
||||
Shift-click: break into paragraphs Shift-按一下:分割為段落
|
||||
Alt-click: reset the horizontal scale too Alt+點擊:一併重設水平縮放
|
||||
breakText Lines 行
|
||||
breakText Words 單字
|
||||
breakText Glyphs 字符
|
||||
@msg Click in type with a Type tool to split it 請用文字工具在文字中按一下以分割
|
||||
@msg Too many type objects to change at once 一次要變更的文字物件過多
|
||||
@msg Too many pieces to make at once 一次要建立的部分過多
|
||||
@msg Select horizontal point or area type whose text fits 請選取文字能完整容納的橫排點文字或區域文字
|
||||
@msg Nothing to split at the cursor 游標處沒有可分割的內容
|
||||
@msg Select two or more one-line point type objects on one baseline to combine 請選取同一基線上兩個或更多單行點文字物件以合併
|
||||
@msg No line breaks to remove 沒有要移除的強制換行
|
||||
@msg No paragraph breaks to remove 沒有要移除的段落換行
|
||||
@msg Too many breaks to remove at once 一次要移除的換行過多
|
||||
@msg Select point type 請選取點文字
|
||||
@msg The point type is aligned that way already 點文字已經是這種對齊方式
|
||||
@msg The point type has no transform to reset 點文字沒有可重設的變形
|
||||
@msg No fonts are missing 沒有遺失的字體
|
||||
@msg the replacement font is not available 替代字體無法使用
|
||||
@msg missing `align` 未提供 `align`
|
||||
@msg `by` must be lines, paragraphs, words or glyphs, not {other} `by` 必須是 lines、paragraphs、words 或 glyphs,而不是 {other}
|
||||
@msg `kind` must be "line" or "paragraph", not {other} `kind` 必須是 "line" 或 "paragraph",而不是 {other}
|
||||
@msg `align` must be "left", "center" or "right", not {other} `align` 必須是 "left"、"center" 或 "right",而不是 {other}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
+43
@@ -5731,6 +5731,49 @@ topmost piece.
|
||||
{"name":"run_command","arguments":{"command":"addon.cleanup.simplify","params":{"tolerance":40,"protectCorners":true}}}
|
||||
```
|
||||
|
||||
### Text tools
|
||||
|
||||
The add-on's text tools act on the selected type (or `ids`), each as one undo step, and refuse with an error when there
|
||||
is nothing for them to do. The pieces they make are point type that keeps its characters' styles, each placed so the
|
||||
glyph of its first character lands where it was drawn.
|
||||
|
||||
- `addon.cleanup.breakText {by?, ids?}` turns each horizontal point or area type object into point type objects, one
|
||||
per line (`by: "lines"`, the default), paragraph (`"paragraphs"`), word (`"words"`) or glyph (`"glyphs"`; a ligature
|
||||
stays one piece). Spaces between the pieces go. A paragraph keeps its lines: where the layout wrapped one, the piece
|
||||
has a forced line break. Justified lines close up, and a paragraph broken out whole keeps its bullet (not its
|
||||
number; the other pieces have no list markers). Type on a path, vertical type, threaded type and area type whose text doesn't fit stay as they are and are
|
||||
listed in `skipped`.
|
||||
- `addon.cleanup.combineText {ids?}` merges one-line horizontal point type into as few objects as it can, every glyph
|
||||
staying where it was (within 0.01 pt). Pieces turned and sheared alike whose baselines lie within 0.4 em of each
|
||||
other join left to right (a baseline a little off becomes baseline shift); a space goes between pieces at least half
|
||||
a space apart, and tracking on the character before each piece keeps its place. A gap wider than 10 em, an overlap of
|
||||
more than 1 em, another look (paint, opacity, effects) or a piece that can't keep its place once joined (a ligature
|
||||
forming across the join) starts another object. Each object made takes the place and paint of its leftmost piece. The
|
||||
main use is type from a PDF that arrives one glyph per object.
|
||||
- `addon.cleanup.removeBreaks {kind, ids?}` removes the forced line breaks (`kind: "line"`) or paragraph returns
|
||||
(`"paragraph"`) in the characters selected with a Type tool, else in all the text of the selected type. A break
|
||||
between two words becomes a space; merged paragraphs take the first one's paragraph style.
|
||||
- `addon.cleanup.splitText {}` works while a Type tool edits horizontal point or area type: the text before the
|
||||
selected characters, those characters and the text after them become point type objects (at a bare cursor, the text
|
||||
before and after it). Spaces at the ends of each piece go; a piece that starts inside a left-aligned line takes a
|
||||
first-line indent, so its later lines stay where they were. Editing ends with the pieces selected.
|
||||
- `addon.cleanup.alignInPlace {align, ids?}` aligns every paragraph of each horizontal point type object `left`,
|
||||
`center` or `right` and moves the object so its longest line stays where it is: a single line doesn't move at all.
|
||||
- `addon.cleanup.resetTextTransform {scale?, ids?}` takes the rotation, shear and reflection off point type, keeping its
|
||||
size and the centre of its text. With `scale: true` the horizontal scale goes too, the object's and each character's.
|
||||
- `addon.cleanup.replaceFonts {font?}` sets every character of the document's type whose font family isn't available
|
||||
in `font` (by default the default type font, Source Sans 3), in that family's style closest to the one it had.
|
||||
|
||||
In the panel, the Text row (which the panel can hide) runs them: Shift-click Lines to break into paragraphs, and
|
||||
Alt-click Reset Transform to reset the horizontal scale too. Recovering live text from outlines, combining vertical
|
||||
type and evening out horizontal scales are not there yet.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"addon.cleanup.breakText","params":{"by":"words"}}}
|
||||
{"name":"run_command","arguments":{"command":"addon.cleanup.combineText","params":{}}}
|
||||
{"name":"run_command","arguments":{"command":"addon.cleanup.removeBreaks","params":{"kind":"paragraph"}}}
|
||||
```
|
||||
|
||||
## Path Precision Tools add-on
|
||||
|
||||
Path Precision Tools is a built-in add-on for exact anchor and path work: its commands are `addon.pathtools.*`, and in
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Parity with Adobe Illustrator
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-30 · **Change:** minor (Color Effects add-on: Duotone and Print Ink Fixes; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (Artwork Cleanup add-on: text tools; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026)
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
@@ -1222,6 +1222,14 @@ Show, Fix Selected and Fix All (each one undo step), Deep Ungroup and Rejoin Pat
|
||||
alone; Fix All as one step; scopes; rejoin within the gap only) and `addons::cleanup::tests` in `vectorcraft-ui-egui`
|
||||
(the submenu opens the panel; Check lists what it finds). Commands: `docs/mcp.md` › Artwork Cleanup add-on.
|
||||
|
||||
The add-on's text tools (2026-10-31) work on the shared text layout: Break Text into lines, paragraphs, words or glyphs
|
||||
and Split Text at Cursor make point type pieces placed by the glyph of their first character, Combine Point Text merges
|
||||
one-line point type back with every glyph where it was (tracking and spaces, checked against the layout), and Remove
|
||||
Line / Paragraph Breaks, Set Alignment, Keep Position, Reset Text Transform and Replace Missing Fonts. Tests:
|
||||
`cmd::addons::cleanup::text::tests` in `vectorcraft-engine` (glyphs kept in place, styles kept, one undo step,
|
||||
refusals), `addons::cleanup::tests` in `vectorcraft-ui-egui` (the submenu and the panel's Text row run them) and
|
||||
`cleanup_text_tools_with_junk_editing_ranges` in the command sweep.
|
||||
|
||||
## Path Precision Tools add-on (2026-10-30)
|
||||
|
||||
A VectorCraft addition, not an Illustrator feature, so no area score moves. Object › Plug-ins › Path Precision Tools,
|
||||
@@ -1296,6 +1304,7 @@ add-on.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-31 | minor | Artwork Cleanup add-on (a VectorCraft addition): text tools; evidence added; scores unchanged. |
|
||||
| 2026-10-30 | minor | Color Effects add-on: live Duotone (one to four inks, spot tones kept) and Print Ink Fixes; scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | 3D Extrude & Bevel, Inflate and Rotate apply to type, which stays editable (#4715); scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Color Effects add-on: live Vector Halftone; scores and estimates unchanged |
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
# UI and interaction parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-30 · **Change:** minor (Color Effects add-on: Duotone and Print Ink Fixes; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (Artwork Cleanup add-on: text tools; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
@@ -330,6 +330,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
|
||||
| Smart Pen add-on (VectorCraft addition): Object › Plug-ins › Smart Pen selects the Smart Pen Tool, which the All Tools drawer lists under its own heading but neither toolbar shows as shipped (no shortcut), and opens the Smart Pen panel (next segment straight or curved; Remove Points Keep Shape, Make Smooth, Make Corner, Retract Handles, Close or Join). The tool draws (click: straight or curved segment, a curve after a straight one tangent; drag: smooth anchor, Alt breaks the handle, Shift 45°, Space moves it; Tab switches a segment; rubber band; close, join, continue) and edits without switching tools (click selects a point, drag moves it, Alt-click removes it keeping the shape, Shift+Alt-click deletes it, double-click toggles smooth/corner; handle drags with Shift and Alt; segment drags reshape, Alt-click adds a point); an Alt-drag away from paths selects the points inside a marquee | done | `addon.pen.*`, `crates/tools/src/addons/smart_pen.rs`, `crates/ui-egui/src/addons/pen.rs` and their tests; not an Illustrator feature, so it is not scored |
|
||||
| Path Precision Tools add-on (VectorCraft addition): Object › Plug-ins › Path Precision Tools selects its three tools (Anchor Eraser Brush, Extend Path, Measure & Inspect), which the All Tools drawer lists under their own heading but neither toolbar shows as shipped, opens the Anchor Inspector panel (the selected anchor's X/Y and handle lengths and angles as fields; Make Smooth, Make Corner, Equalize Handles, Remove Points Keep Shape, Add Points, the three ways to close) and runs Add Points at / Split at Crossings; a double-click on the brush or Extend Path tool opens its options | done | `addon.pathtools.*`, `crates/tools/src/addons/`, `crates/ui-egui/src/addons/pathtools.rs` and their tests; not an Illustrator feature, so it is not scored |
|
||||
| Artwork Cleanup add-on (VectorCraft addition): Object › Plug-ins › Artwork Cleanup opens its panel, which checks the selection or the document for 16 kinds of issue, lists them with counts, and shows or fixes the picked rows or all of them, each fix one undo step; Simplify Anchors (Keep Shape), Rejoin Path Pieces and Deep Ungroup open their options first | done | `addon.cleanup.*`, `crates/ui-egui/src/addons/cleanup.rs` and its tests; not an Illustrator feature, so it is not scored |
|
||||
| Artwork Cleanup add-on text tools (VectorCraft addition): the panel's Text row, which the panel can hide, and Object › Plug-ins › Artwork Cleanup set the alignment of point type keeping its place, break type into lines (Shift-click: paragraphs), words or glyphs, split type at the cursor, reset a text transform (Alt-click: and its horizontal scale), combine point type, remove line or paragraph breaks and replace missing fonts, each one undo step | done | `addon.cleanup.*` text commands, `crates/ui-egui/src/addons/cleanup.rs` and its tests; a VectorCraft addition, so it is not scored |
|
||||
| Color Effects add-on (VectorCraft addition): live Exposure, Desaturate and Invert Colors in Effect › Color Effects and Object › Plug-ins › Color Effects; its panel picks a colour adjustment and its values and adds it as a live effect or applies it as a filter, into the colours, as one undo step; Select by Color Kind selects the objects that use spot colours, carry colour effects, or are RGB, CMYK or grayscale images; Vector Halftone draws an object as halftone dots live (the dots Object › Vector Halftone makes), which Expand Appearance and the exporters write as paths; Duotone prints each colour's tone with one to four inks (a tint of a spot tone's swatch, or the CMYK mix of several), live or as a filter, its dialog a row per tone and the picked tone's curve; Print Ink Fixes (a CMYK document's ink limit, white overprint removed, black overprint set) opens its options from the submenu and the panel's Inks | done | `addon.color.*`, `crates/ui-egui/src/addons/color.rs` and its tests; not an Illustrator feature, so it is not scored |
|
||||
|
||||
## Look and feel
|
||||
@@ -371,6 +372,7 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-31 | minor | Artwork Cleanup add-on (a VectorCraft addition): its text tools in the panel and Object › Plug-ins › Artwork Cleanup; scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Color Effects add-on: live Duotone (one to four inks, spot tones kept) and Print Ink Fixes; scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Color Effects add-on: live Vector Halftone; scores and estimates unchanged |
|
||||
| 2026-10-30 | minor | Path Precision Tools add-on: the Parametric Shape Tool (ten re-editable shape kinds), its panel and Convert to Parametric Shape; scores and estimates unchanged |
|
||||
|
||||
Reference in New Issue
Block a user