diff --git a/crates/doc/src/orient.rs b/crates/doc/src/orient.rs index e524d6ca37..a2ff76d83f 100644 --- a/crates/doc/src/orient.rs +++ b/crates/doc/src/orient.rs @@ -3,6 +3,8 @@ //! square to it: scaling by a side handle stretches it along its own width or height. Path //! geometry is still baked; Object ▸ Transform ▸ Reset Bounding Box sets the angle back to 0. +use std::sync::Arc; + use vectorcraft_geom::{Affine, Point, Rect, Vec2, normalize_deg, union_opt}; use crate::{Document, Node, NodeId, NodeKind, SymbolBoxes}; @@ -84,7 +86,35 @@ pub fn transformed_angle(angle: f64, a: Affine) -> f64 { } } +/// The turn (counter-clockwise degrees) from the boxes of art placed by a symbol instance's +/// transform `xf` to the instance's own box at `angle`: 0 while the box turns with the transform, +/// otherwise the change Reset Bounding Box made to it. Under a mirroring `xf` the instance's box can +/// stand 180° from the one `xf` gives in one step ([`transformed_angle`] keeps the angle nearer the +/// one before at each step); the turn is then 180°, so the art's boxes match the instance's. +pub fn placed_turn(angle: f64, xf: Affine) -> f64 { + let turn = normalize_deg(angle - transformed_angle(0.0, xf)); + if turn.is_finite() && turn.abs() > EPS_DEG { turn } else { 0.0 } +} + impl Node { + /// Turns the box of this object, and of every object that turns with it ([`Node::transform`]: + /// its children and the art of a linked opacity mask), by `by` degrees counter-clockwise. + /// Layers have no box. + pub fn turn_boxes(&mut self, by: f64) { + if !self.is_layer() { + let a = normalize_deg(self.bbox_angle + by); + self.bbox_angle = if a.abs() <= EPS_DEG { 0.0 } else { a }; + } + for c in self.children_mut().into_iter().flatten() { + Arc::make_mut(c).turn_boxes(by); + } + if let Some(m) = self.extras_if_any().and_then(|e| e.mask.as_mut()) + && m.linked + { + Arc::make_mut(&mut m.art).turn_boxes(by); + } + } + /// Bounds of this object as `a` would place it (geometric, or `visual` with its strokes), /// without changing it, symbol instances measured by their art from `symbols` /// ([`Node::geometric_bounds_with`]). @@ -185,6 +215,44 @@ mod tests { assert_eq!(transformed_angle(30.0, Affine::scale(0.0)), 30.0); } + #[test] + fn placed_turn_is_what_reset_bounding_box_took_off_the_instance() { + let xf = Affine::translate((40.0, 10.0)) * rot(20.0) * Affine::scale_non_uniform(2.0, 0.5); + // The box turns with the transform: no turn. + assert_eq!(placed_turn(transformed_angle(0.0, xf), xf), 0.0); + assert_eq!(placed_turn(0.0, Affine::scale(3.0)), 0.0); + // Reset to 0: the placed art turns back by the 20°. + assert!(close(placed_turn(0.0, xf), -20.0)); + // Mirrored: turned 170° and then flipped, the instance's box stands 180° from the box the + // whole transform gives in one step, and the art turns the half turn to match it. + let flip = Affine::scale_non_uniform(1.0, -1.0); + let flipped = flip * rot(170.0); + let stepwise = transformed_angle(transformed_angle(0.0, rot(170.0)), flip); + assert!(close(stepwise, -170.0) && close(transformed_angle(0.0, flipped), 10.0)); + assert!(close(placed_turn(stepwise, flipped).abs(), 180.0)); + assert!(close(normalize_deg(placed_turn(0.0, flipped) + transformed_angle(0.0, flipped)), 0.0)); + // Degenerate and non-finite transforms turn nothing. + assert_eq!(placed_turn(0.0, Affine::scale(0.0)), 0.0); + assert_eq!(placed_turn(f64::NAN, xf), 0.0); + } + + #[test] + fn turn_boxes_turns_children_and_linked_mask_art_but_not_layers() { + let mut d = Document::new(500.0, 500.0); + let a = Node::path(d.alloc_id(), shapes::rectangle(Rect::new(0.0, 0.0, 10.0, 10.0)), Appearance::default_art()); + let mut g = Node::group(d.alloc_id(), vec![Arc::new(a.clone())]); + g.bbox_angle = 170.0; + g.extras_mut().mask = Some(Box::new(crate::OpacityMask::new(a.clone(), true))); + let mut layer = (*d.layers[0]).clone(); + layer.children_mut().unwrap().push(Arc::new(g)); + layer.turn_boxes(20.0); + assert_eq!(layer.bbox_angle, 0.0); + let g = &layer.children().unwrap()[0]; + assert!(close(g.bbox_angle, -170.0), "wraps to (-180, 180]"); + assert!(close(g.children().unwrap()[0].bbox_angle, 20.0)); + assert!(close(g.extras().mask.as_ref().unwrap().art.bbox_angle, 20.0)); + } + #[test] fn oriented_bounds_hug_a_rotated_rectangle() { let mut d = Document::new(500.0, 500.0); diff --git a/crates/doc/src/symbol_nine_slice.rs b/crates/doc/src/symbol_nine_slice.rs index 53f84e869c..3c8c1b324d 100644 --- a/crates/doc/src/symbol_nine_slice.rs +++ b/crates/doc/src/symbol_nine_slice.rs @@ -614,6 +614,8 @@ impl NineSliceMap { /// `n`, whose box at the natural size is `b`, drawn in each cell it reaches: a clip group of /// the cell around a copy placed by the cell's map, all in a group with `n`'s id. `n` placed /// by `center` when it draws symbol art ([`draws_symbol_art`]), and in [`Self::place_unclipped`]. + /// The clip groups and clip paths take the angle of the cell map that places them. The group + /// and each copy keep `n`'s box angle, turned by the map that places them. /// /// The drop shadows, outer glows and blurs ([`PAINTED_EFFECTS`]) at the end of `n`'s own /// effects, after its last other visible effect, go on that group with its opacity, blending @@ -647,11 +649,15 @@ impl NineSliceMap { area.transform(local); let mut clip = Node::new(NodeId(0), NodeKind::Path { path: area, rule: FillRule::NonZero, live: None, clipping: true, guide: false }); clip.appearance = Appearance::default().into(); + clip.bbox_angle = crate::orient::transformed_angle(0.0, local); let copy = transformed(n, local * self.natural); - cells.push(Arc::new(Node::new(NodeId(0), NodeKind::Group { children: vec![Arc::new(clip), Arc::new(copy)], clip: true }))); + let mut cell = Node::new(NodeId(0), NodeKind::Group { children: vec![Arc::new(clip), Arc::new(copy)], clip: true }); + cell.bbox_angle = crate::orient::transformed_angle(0.0, local); + cells.push(Arc::new(cell)); } } let mut out = Node::group(n.id, cells); + out.bbox_angle = crate::orient::transformed_angle(n.bbox_angle, center); out.visible = n.visible; out.locked = n.locked; out.name = n.name.clone(); diff --git a/crates/effects/src/live.rs b/crates/effects/src/live.rs index 2c02f886c0..5a878d42d3 100644 --- a/crates/effects/src/live.rs +++ b/crates/effects/src/live.rs @@ -23,15 +23,22 @@ pub fn text_outliner() -> Outliner<'static> { /// Type outlined, or a symbol instance as its symbol's art (from `doc`) placed by the instance, /// through the symbol's 9-slice guides when it has them ([`Document::place_symbol_art`], `None` /// past its object limit). As an [`OutlineHook`](crate::OutlineHook), it gives compound shapes and -/// Pathfinder operations the symbol instances among their members. +/// Pathfinder operations the symbol instances among their members. The group around the art takes +/// the instance's box angle, and the art's boxes turn with it, as Break Link turns them. pub fn outline_object(doc: Option<&Document>, n: &Node) -> Option { match &n.kind { NodeKind::SymbolInstance { symbol, xf } => { let doc = doc?; let sym = doc.symbols.iter().find(|s| s.name == *symbol)?; let art = vectorcraft_doc::symbol_overrides::dynamic_art(&sym.art, n); - let art = doc.place_symbol_art(symbol, &art, *xf)?; - Some(Node::group(n.id, vec![Arc::new(art)])) + let mut art = doc.place_symbol_art(symbol, &art, *xf)?; + let turn = vectorcraft_doc::orient::placed_turn(n.bbox_angle, *xf); + if turn != 0.0 { + art.turn_boxes(turn); + } + let mut out = Node::group(n.id, vec![Arc::new(art)]); + out.bbox_angle = n.bbox_angle; + Some(out) } _ => outline_text(n), } diff --git a/crates/effects/src/tests.rs b/crates/effects/src/tests.rs index 627cc1be03..0023fc5b16 100644 --- a/crates/effects/src/tests.rs +++ b/crates/effects/src/tests.rs @@ -1570,6 +1570,27 @@ fn outline_object_is_a_geometry_effect_that_keeps_the_path() { assert_eq!(apply_geometry(&[fx("path.outlineObject", json!({})), offset.clone()], &square(), b), apply_geometry(&[offset], &square(), b)); } +/// A symbol instance given to Pathfinder and compound shapes as its art: the group takes the +/// instance's box angle and the art turns with it, turned with the instance or reset to 0. +#[test] +fn outline_object_turns_an_instances_art_with_its_box() { + use std::sync::Arc; + + use vectorcraft_doc::orient::transformed_angle; + use vectorcraft_doc::{Appearance, Document, NodeId, Symbol}; + let mut d = Document::new(500.0, 500.0); + d.symbols.push(Symbol { dynamic: false, name: "s".into(), art: Arc::new(Node::path(NodeId(0), square(), Appearance::default())) }); + let xf = Affine::translate((200.0, 100.0)) * Affine::rotate(0.35); + for box_angle in [transformed_angle(0.0, xf), 0.0] { + let mut inst = Node::new(NodeId(3), NodeKind::SymbolInstance { symbol: "s".into(), xf }); + inst.bbox_angle = box_angle; + let out = outline_object(Some(&d), &inst).unwrap(); + let mut angles = vec![]; + out.walk(&mut |c| angles.push(c.bbox_angle)); + assert!(angles.len() == 2 && angles.iter().all(|a| close(*a, box_angle, 1e-9)), "{box_angle}: {angles:?}"); + } +} + #[test] fn convert_to_shape_sizes() { let r = run("convertToShape.rectangle", json!({"extraW": 20, "extraH": 10}), &square()).bounds().unwrap(); diff --git a/crates/engine/src/cmd/brushsym.rs b/crates/engine/src/cmd/brushsym.rs index 50c63b59cd..32b0f9fcd0 100644 --- a/crates/engine/src/cmd/brushsym.rs +++ b/crates/engine/src/cmd/brushsym.rs @@ -226,7 +226,7 @@ pub fn specs() -> Vec { "Break Link to Symbol", [], None, - "{ids?|id?} expand selected instances into plain art (with their appearance changes to a dynamic symbol), placed through the symbol's 9-slice guides when it has them, with the instance's opacity mask; a hidden or locked instance's art stays hidden or locked and is not selected → {ids}", + "{ids?|id?} expand selected instances into plain art (with their appearance changes to a dynamic symbol), placed through the symbol's 9-slice guides when it has them, with the instance's opacity mask and its own bounding box (square after Reset Bounding Box); a hidden or locked instance's art stays hidden or locked and is not selected → {ids}", has_selection, symbol_break_link ), diff --git a/crates/engine/src/cmd/brushsym/symbols.rs b/crates/engine/src/cmd/brushsym/symbols.rs index 2fb31c5f6b..1bfb8edea7 100644 --- a/crates/engine/src/cmd/brushsym/symbols.rs +++ b/crates/engine/src/cmd/brushsym/symbols.rs @@ -393,8 +393,10 @@ pub(super) fn symbol_place(s: &mut Session, p: &Value) -> Result { /// The plain art of instance `inst` in document space (fresh ids), with the instance's own /// appearance changes to a dynamic symbol's art when `own`, placed through its symbol's 9-slice -/// guides when it has them. The instance's opacity mask goes on the art, or on a group around it -/// when the art has a mask of its own. +/// guides when it has them. The art's bounding boxes turn with the instance's own box, so after +/// Reset Bounding Box they stand as the instance's box does. The instance's opacity mask goes on +/// the art, or on a group around it when the art has a mask of its own; a group added around the +/// art takes the instance's box angle. fn expanded_instance(d: &mut Document, inst: &Node, own: bool) -> Option { let NodeKind::SymbolInstance { symbol, xf } = &inst.kind else { return None }; let sym = d.symbols.iter().find(|s| &s.name == symbol)?; @@ -402,12 +404,17 @@ fn expanded_instance(d: &mut Document, inst: &Node, own: bool) -> Option { if let Some((color, amount)) = brush::stain(inst) { brush::tint_node(&mut art, &color, amount); } - let art = d.place_symbol_art(symbol, &art, *xf)?; + let mut art = d.place_symbol_art(symbol, &art, *xf)?; + let turn = vectorcraft_doc::orient::placed_turn(inst.bbox_angle, *xf); + if turn != 0.0 { + art.turn_boxes(turn); + } let mut art = d.reid(&art); if inst.opacity < 1.0 || inst.blend != vectorcraft_color::BlendMode::Normal { if !matches!(art.kind, NodeKind::Group { .. }) { let id = d.alloc_id(); art = Node::group(id, vec![Arc::new(art)]); + art.bbox_angle = inst.bbox_angle; } art.opacity *= inst.opacity; art.blend = inst.blend; @@ -416,6 +423,7 @@ fn expanded_instance(d: &mut Document, inst: &Node, own: bool) -> Option { if art.extras().mask.is_some() { let id = d.alloc_id(); art = Node::group(id, vec![Arc::new(art)]); + art.bbox_angle = inst.bbox_angle; } art.extras_mut().mask = Some(mask.clone()); } diff --git a/crates/engine/src/cmd/draw2/freehand.rs b/crates/engine/src/cmd/draw2/freehand.rs index 31e184e195..0439aaa081 100644 --- a/crates/engine/src/cmd/draw2/freehand.rs +++ b/crates/engine/src/cmd/draw2/freehand.rs @@ -11,7 +11,9 @@ use super::{ // ---------- Pencil / Paintbrush ---------- /// Fit a freehand polyline: drop jitter, build a spline through the samples (sharp turns stay -/// corners) and simplify it to `tol`. +/// corners) and simplify it to `tol`. A closed stroke is fitted as the open one is and closed by a +/// straight segment from its end back to its start: fitting round the gap would curve that segment +/// on from both ends, past them and back. fn fit_freehand(pts: &[Point], tol: f64, closed: bool) -> SubPath { let min = (tol * 0.3).max(vectorcraft_tools::draw2::MIN_FIT_TOLERANCE * 0.3); let (Some(&p0), Some(&pn)) = (pts.first(), pts.last()) else { return SubPath::new(vec![], closed) }; @@ -41,15 +43,26 @@ fn fit_freehand(pts: &[Point], tol: f64, closed: bool) -> SubPath { (kept[i], corner) }) .collect(); - let sp = vectorcraft_tools::draw2::catmull_rom(&marked, closed); + let sp = vectorcraft_tools::draw2::catmull_rom(&marked, false); if sp.anchors.len() < 3 { - return sp; + // Two anchors closed would run back over the line itself. + return SubPath::new(sp.anchors, closed && n > 2); } let fitted = po::simplify_with( &PathData::single(sp.clone()), &SimplifyOptions { tolerance: tol, corner_angle_deg: 60.0, straight_lines: false, ..Default::default() }, ); - fitted.subpaths.into_iter().next().filter(|s| s.anchors.len() >= 2).unwrap_or(sp) + let mut anchors = fitted.subpaths.into_iter().next().filter(|s| s.anchors.len() >= 2).unwrap_or(sp).anchors; + if closed { + // No handle on either side of the closing segment. + if let Some(l) = anchors.last_mut() { + l.h_out = l.p; + } + if let Some(f) = anchors.first_mut() { + f.h_in = f.p; + } + } + SubPath::new(anchors, closed) } /// The path of a freehand stroke: fitted at `tol` ([`fit_freehand`]), or with no `tol` the points diff --git a/crates/engine/src/cmd/recolor.rs b/crates/engine/src/cmd/recolor.rs index ede74545b6..07f1f4c46b 100644 --- a/crates/engine/src/cmd/recolor.rs +++ b/crates/engine/src/cmd/recolor.rs @@ -1724,7 +1724,7 @@ fn apply(s: &mut Session, p: &Value) -> Result { let mut out = json!({ "changed": changed, "swatches": added }); not_changed.report(&mut out); if let Some(e) = edit { - e.defaults(s); + e.defaults(s)?; out["relinked"] = json!(e.relinked()); } if converted { diff --git a/crates/engine/src/cmd/swatch.rs b/crates/engine/src/cmd/swatch.rs index d0713a243a..3b98cbd9a6 100644 --- a/crates/engine/src/cmd/swatch.rs +++ b/crates/engine/src/cmd/swatch.rs @@ -322,7 +322,7 @@ fn swatch_delete(s: &mut Session, p: &Value) -> Result { super::paint::check_colorized_kept(colorized_ok, d).map_err(|e| bad(C, e))?; Ok(unlinked) })?; - map_default_paints(s, &mut unlink); + map_default_paints(s, &mut unlink)?; Ok(json!({"deleted": names, "unlinked": unlinked})) } @@ -660,20 +660,41 @@ impl Relink { renamed || recolored } - fn defaults(&self, s: &mut Session) { - map_default_paints(s, &mut |c, l, t| self.apply(c, l, t)); + fn defaults(&self, s: &mut Session) -> Result<()> { + map_default_paints(s, &mut |c, l, t| self.apply(c, l, t)) } } -/// Apply a swatch-link rewrite to the default fill and stroke for new art, except during a live -/// preview (Cancel rolls the document back, not the session). -pub(super) fn map_default_paints(s: &mut Session, f: &mut LinkFn) { - if s.in_interaction() { - return; +/// Apply a swatch-link rewrite to the fill and stroke new art takes and to the paints of its +/// template appearance, except during a live preview (Cancel rolls the document back, not the +/// session). A `command.batch` step rewrites them as the command run on its own does: a failed +/// batch, and a canceled batch preview, put back the paints the batch started with. A change is +/// recorded with the step just made, so Undo and Redo put these paints back with the document. +pub(super) fn map_default_paints(s: &mut Session, f: &mut LinkFn) -> Result<()> { + if s.in_interaction() && s.batch_stash.is_none() { + return Ok(()); } - for p in [&mut s.paint.fill, &mut s.paint.stroke] { - p.map_links(f); + let start = super::colormgmt::new_art_colors_before(s)?; + let pd = &mut s.paint; + let template = pd.appearance.iter_mut().flat_map(|a| a.items.iter_mut()).map(|it| match it { + vectorcraft_doc::AppearanceItem::Fill(f) => &mut f.paint, + vectorcraft_doc::AppearanceItem::Stroke(s) => &mut s.paint, + }); + let mut changed = false; + for p in [&mut pd.fill, &mut pd.stroke].into_iter().chain(template) { + changed |= p.map_links(f); } + if changed { + super::colormgmt::record_new_art_colors(s, start)?; + // The step takes the paints the command finally leaves, after the selection's appearance + // is inherited. + let st = s.doc()?; + if st.interaction.is_none() { + let uid = st.uid; + s.batch_paint_docs.push(uid); + } + } + Ok(()) } /// Apply a swatch-link rewrite to the document ([`Document::map_solid_paints`]) and to the art of @@ -888,7 +909,7 @@ fn swatch_edit(s: &mut Session, p: &Value) -> Result { super::paint::check_colorized_kept(colorized_ok, d).map_err(|e| bad(C, e))?; Ok(relinked) })?; - relink.defaults(s); + relink.defaults(s)?; Ok(json!({"name": to, "relinked": relinked})) } @@ -1084,7 +1105,7 @@ fn swatch_merge(s: &mut Session, p: &Value) -> Result { super::paint::check_colorized_kept(colorized_ok, d).map_err(|e| bad(C, e))?; Ok(relinked) })?; - map_default_paints(s, &mut relink); + map_default_paints(s, &mut relink)?; Ok(json!({"name": keep, "merged": merged, "relinked": relinked})) } @@ -1141,7 +1162,7 @@ fn swatch_spot_options(s: &mut Session, p: &Value) -> Result { let relinked = map_swatch_links(d, &mut follow_bases(&bases)); Ok((relinked, bases)) })?; - map_default_paints(s, &mut follow_bases(&bases)); + map_default_paints(s, &mut follow_bases(&bases))?; Ok(json!({"useLab": use_lab, "relinked": relinked})) } @@ -1165,8 +1186,11 @@ pub(super) struct GroupEdit { impl GroupEdit { /// Apply the link changes to the default fill and stroke for new art. - pub(super) fn defaults(&self, s: &mut Session) { - self.relinks.iter().for_each(|r| r.defaults(s)); + pub(super) fn defaults(&self, s: &mut Session) -> Result<()> { + if self.relinks.is_empty() { + return Ok(()); + } + map_default_paints(s, &mut |c, l, t| self.relinks.iter().any(|r| r.apply(c, l, t))) } /// How many paints linked to the group's swatches the rewrite changed. @@ -1242,6 +1266,6 @@ fn swatch_edit_group(s: &mut Session, p: &Value) -> Result { colors.into_iter().enumerate().map(|(i, c)| if old.get(i) == Some(&Some(c)) { c } else { super::paint::new_color(s, p, c) }).collect(); let rename = str_param(p, "rename"); let e = s.edit("Edit Color Group", |d, _| rewrite_group(d, group, &colors, rename, C))?; - e.defaults(s); + e.defaults(s)?; Ok(json!({"name": e.name, "swatches": e.swatches, "relinked": e.relinked})) } diff --git a/crates/engine/src/cmd/swatchlib.rs b/crates/engine/src/cmd/swatchlib.rs index 8101cfff97..ed712d8509 100644 --- a/crates/engine/src/cmd/swatchlib.rs +++ b/crates/engine/src/cmd/swatchlib.rs @@ -980,7 +980,7 @@ fn reset_defaults(s: &mut Session, p: &Value) -> Result { Ok(added) })?; if replace { - map_default_paints(s, &mut |_, l, _| unlink_dead(&live, l)); + map_default_paints(s, &mut |_, l, _| unlink_dead(&live, l))?; } Ok(json!({ "added": added })) } diff --git a/crates/engine/src/cmd/typecmd/area_tests.rs b/crates/engine/src/cmd/typecmd/area_tests.rs index c68334e2c0..db1712a7f8 100644 --- a/crates/engine/src/cmd/typecmd/area_tests.rs +++ b/crates/engine/src/cmd/typecmd/area_tests.rs @@ -1688,10 +1688,9 @@ fn warichu_is_a_character_attribute_set_saved_and_exported() { assert!(["warichu", "warichuLines", "warichuGap", "warichuScale", "warichuAlign"].iter().all(|k| saved.get(*k).is_none()), "{saved}"); let plain_svg = vectorcraft_svg::export(&s.doc().unwrap().doc, &Default::default()); let plain_pdf = vectorcraft_pdf::export(&s.doc().unwrap().doc, &vectorcraft_pdf::PdfOptions::uncompressed()).unwrap(); - let text_ops = |pdf: &[u8]| { - let s = String::from_utf8_lossy(pdf); - s.contains("Tj") || s.contains("TJ") - }; + // Only text objects count: the file ID in the trailer and the XMP is base64 that changes each + // second and now and then spells `Tj` or `TJ`. + let text_ops = |pdf: &[u8]| String::from_utf8_lossy(pdf).lines().any(|l| l.starts_with("BT ") && (l.contains("Tj") || l.contains("TJ"))); assert!(plain_svg.contains(" bool { - self.any_art_to_fit_with(indices, (vectorcraft_plugins::registry::revision(), vectorcraft_text::FontDb::global().generation())) + self.any_art_to_fit_with(indices, (vectorcraft_plugins::registry::revision(), vectorcraft_text::layout_inputs())) } - /// [`Self::any_art_to_fit`], with `outside` the generations of the plug-ins and the fonts. + /// [`Self::any_art_to_fit`], with `outside` the generations of the plug-ins and the layout inputs + /// ([`vectorcraft_text::layout_inputs`]). pub(crate) fn any_art_to_fit_with(&self, indices: &[usize], outside: (u64, u64)) -> bool { // Measuring runs renderer and plug-in code; should it ever ask again while measuring, it // is measured without being kept rather than borrowed twice. diff --git a/crates/engine/src/session/documents.rs b/crates/engine/src/session/documents.rs index 5ceaf86aaf..a87b47be0e 100644 --- a/crates/engine/src/session/documents.rs +++ b/crates/engine/src/session/documents.rs @@ -25,9 +25,11 @@ impl Session { // Clicks find an image's own fills and strokes where their effects draw them. vectorcraft_doc::hit::set_image_paint(vectorcraft_render::effects::image_paint); // Clicks find a blend's steps and an envelope's distorted art where the canvas draws them, - // evaluated again when the fonts or the plug-ins change. + // evaluated again when the fonts, the hyphenation exceptions or the plug-ins change. vectorcraft_doc::hit::set_live_art(vectorcraft_render::effects::expand_live, || { - vectorcraft_text::FontDb::global().generation().rotate_left(32) ^ vectorcraft_render::effects::plugin_revision() + let mut h = std::hash::DefaultHasher::new(); + std::hash::Hash::hash(&(vectorcraft_text::layout_inputs(), vectorcraft_render::effects::plugin_revision()), &mut h); + std::hash::Hasher::finish(&h) }); // Envelopes map type from the bounds of its glyph outlines, underlines and strikethroughs. vectorcraft_text::register_envelope_ink(); diff --git a/crates/engine/src/tests/bboxrotate.rs b/crates/engine/src/tests/bboxrotate.rs index aa1c14885c..6dc1c9b410 100644 --- a/crates/engine/src/tests/bboxrotate.rs +++ b/crates/engine/src/tests/bboxrotate.rs @@ -560,6 +560,125 @@ fn reset_bounding_box_then_release_intertwine() { reset_then_release("object.intertwine.make", "object.intertwine.release"); } +/// A symbol of two rectangles, the first turned `inner` degrees before the symbol is made, placed +/// as an instance that is then turned 20°. +fn turned_instance(inner: f64) -> (Session, NodeId) { + let mut s = session(); + let a = rect(&mut s, 100.0, 100.0, 100.0, 50.0); + let b = rect(&mut s, 150.0, 220.0, 100.0, 50.0); + if inner != 0.0 { + sel(&mut s, &[a]); + s.execute("object.rotate", &json!({"angle": inner})).unwrap(); + } + sel(&mut s, &[a, b]); + let inst = id_of(&s.execute("symbol.new", &json!({"name": "Pair"})).unwrap()); + sel(&mut s, &[inst]); + s.execute("object.rotate", &json!({"angle": 20})).unwrap(); + assert!(near(angle(&s, inst), 20.0)); + (s, inst) +} + +/// Break Link and Expand with the parameters that turn instance `inst` into its art. +fn expand_instance(s: &mut Session, command: &str, inst: NodeId) { + sel(s, &[inst]); + let params = if command == "symbol.breakLink" { json!({"ids": [inst.0]}) } else { json!({"object": true, "fill": false, "stroke": false}) }; + s.execute(command, ¶ms).unwrap(); + assert!(s.doc().unwrap().doc.node(inst).is_none_or(|n| !matches!(n.kind, vectorcraft_doc::NodeKind::SymbolInstance { .. })), "{command}"); +} + +/// The angles of the objects inside the document's only top-level object, that object included. +fn art_angles(s: &Session) -> Vec { + let d = &s.doc().unwrap().doc; + let layer = d.layers.first().unwrap(); + let top = layer.children().unwrap(); + assert_eq!(top.len(), 1); + let mut out = vec![]; + subtree_angles(&top[0], &mut out); + out +} + +#[test] +fn reset_bounding_box_then_expand_symbol_instance() { + for command in ["symbol.breakLink", "object.expand"] { + let (mut s, inst) = turned_instance(0.0); + assert_eq!(s.execute("object.resetBoundingBox", &json!({})).unwrap()["changed"], 1); + assert_eq!(angle(&s, inst), 0.0); + expand_instance(&mut s, command, inst); + let angles = art_angles(&s); + assert!(angles.len() >= 2 && angles.iter().all(|a| near(*a, 0.0)), "{command}: {angles:?}"); + s.execute("select.all", &json!({})).unwrap(); + assert_eq!(selection_box(&s).angle, 0.0, "{command}"); + } +} + +#[test] +fn expanding_a_turned_symbol_instance_keeps_its_angle() { + for command in ["symbol.breakLink", "object.expand"] { + let (mut s, inst) = turned_instance(0.0); + expand_instance(&mut s, command, inst); + let angles = art_angles(&s); + assert!(angles.len() >= 2 && angles.iter().all(|a| near(*a, 20.0)), "{command}: {angles:?}"); + } +} + +#[test] +fn reset_bounding_box_then_expand_keeps_the_angles_inside_the_symbol() { + for command in ["symbol.breakLink", "object.expand"] { + let (mut s, inst) = turned_instance(30.0); + s.execute("object.resetBoundingBox", &json!({})).unwrap(); + expand_instance(&mut s, command, inst); + // The turned rectangle keeps the 30° it had in the symbol; the rest stand square. + let mut angles = art_angles(&s); + angles.sort_by(f64::total_cmp); + assert!(near(*angles.last().unwrap(), 30.0) && angles[..angles.len() - 1].iter().all(|a| near(*a, 0.0)), "{command}: {angles:?}"); + } +} + +/// The group that an instance's opacity adds around the art of a one-object symbol stands as the +/// instance's box does, turned or reset. +#[test] +fn expanding_a_faded_symbol_instance_gives_its_group_the_instance_box() { + for command in ["symbol.breakLink", "object.expand"] { + for reset in [false, true] { + let mut s = session(); + let a = rect(&mut s, 100.0, 100.0, 100.0, 50.0); + sel(&mut s, &[a]); + let inst = id_of(&s.execute("symbol.new", &json!({"name": "One"})).unwrap()); + sel(&mut s, &[inst]); + s.execute("object.rotate", &json!({"angle": 20})).unwrap(); + s.execute("object.setProps", &json!({"ids": [inst.0], "opacity": 50})).unwrap(); + if reset { + s.execute("object.resetBoundingBox", &json!({})).unwrap(); + } + expand_instance(&mut s, command, inst); + let want = if reset { 0.0 } else { 20.0 }; + let angles = art_angles(&s); + assert!(angles.len() == 2 && angles.iter().all(|a| near(*a, want)), "{command}, reset {reset}: {angles:?}"); + } + } +} + +/// A mirrored instance: turned 170° and then reflected, its box stands 180° from the box its +/// transform gives in one step. The art takes the instance's box, and stands square after a reset. +#[test] +fn expanding_a_reflected_symbol_instance_keeps_its_box() { + for command in ["symbol.breakLink", "object.expand"] { + for reset in [false, true] { + let (mut s, inst) = turned_instance(0.0); + s.execute("object.rotate", &json!({"angle": 150})).unwrap(); + s.execute("object.reflect", &json!({"axis": "horizontal"})).unwrap(); + assert!(near(angle(&s, inst), -170.0), "{}", angle(&s, inst)); + if reset { + s.execute("object.resetBoundingBox", &json!({})).unwrap(); + } + let want = angle(&s, inst); + expand_instance(&mut s, command, inst); + let angles = art_angles(&s); + assert!(angles.len() >= 2 && angles.iter().all(|a| near(*a, want)), "{command}, reset {reset}: {angles:?}"); + } + } +} + #[test] fn reset_bounding_box_then_release_linked_opacity_mask() { let mut s = session(); diff --git a/crates/engine/src/tests/draw2.rs b/crates/engine/src/tests/draw2.rs index 79dbd366f6..8936f8bc6f 100644 --- a/crates/engine/src/tests/draw2.rs +++ b/crates/engine/src/tests/draw2.rs @@ -184,6 +184,25 @@ fn pencil_alt_closes_path() { assert!(ps[0].1.is_closed()); } +/// A Pencil stroke drawn as a dome and closed with Alt at the release closes with a straight segment +/// across the bottom, from where the stroke ends to where it starts: the path stays within where the +/// pen went, rather than curving on past both ends and back like a hat's brim. +#[test] +fn pencil_alt_closes_a_stroke_straight_back_to_its_start() { + let mut s = session(); + let pts: Vec<(f64, f64)> = + (0..=60).map(|i| f64::from(i) * std::f64::consts::PI / 60.0).map(|a| (300.0 - 150.0 * a.cos(), 400.0 - 200.0 * a.sin())).collect(); + drag(&mut s, "pencil", &pts, Mods { alt: true, ..Default::default() }); + let ps = paths(&s); + let sp = &ps[0].1.subpaths[0]; + assert!(sp.closed); + let b = ps[0].1.bounds().unwrap(); + assert!(b.x0 > 149.5 && b.x1 < 450.5 && b.y1 < 400.5, "within the stroke: {b:?}"); + let (first, last) = (sp.anchors.first().unwrap(), sp.anchors.last().unwrap()); + assert!(first.p.distance(Point::new(150.0, 400.0)) < 1e-6 && last.p.distance(Point::new(450.0, 400.0)) < 1e-6, "{first:?} {last:?}"); + assert_eq!((last.h_out, first.h_in), (last.p, first.p), "a straight closing segment"); +} + /// #3799: with Shift held, a wavy Pencil drag draws one straight segment at 45° steps from the /// Constrain Angle (here 30°: a drag at about 60° comes out at 75°). #[test] diff --git a/crates/engine/src/tests/swatches.rs b/crates/engine/src/tests/swatches.rs index a80769dd98..8abaec348c 100644 --- a/crates/engine/src/tests/swatches.rs +++ b/crates/engine/src/tests/swatches.rs @@ -1075,6 +1075,146 @@ fn deleting_a_global_swatch_unlinks_art_that_keeps_its_colour() { assert_eq!(fill_of(&s, a), linked("#2a6fb0", "Brand")); } +/// A session whose default fill and stroke for new art are linked to the global swatch `Brand` +/// (`#2a6fb0`), in color group `G`, beside the global swatch `Other` (`#ff8800`). +fn brand_defaults_session() -> Session { + let mut s = session(); + run(&mut s, "swatch.new", json!({"name": "Brand", "color": "#2a6fb0", "global": true})); + run(&mut s, "swatch.newGroup", json!({"name": "G", "swatches": ["Brand"]})); + run(&mut s, "swatch.new", json!({"name": "Other", "color": "#ff8800", "global": true})); + run(&mut s, "select.set", json!({"ids": []})); + run(&mut s, "paint.setFill", json!({"swatch": "Brand"})); + run(&mut s, "paint.setStroke", json!({"swatch": "Brand"})); + assert_eq!(s.paint.fill, linked("#2a6fb0", "Brand")); + s +} + +fn fill_and_stroke(s: &Session, id: NodeId) -> (Paint, Paint) { + let a = &doc(s).node(id).unwrap().appearance; + (a.fill_paint(), a.stroke_paint()) +} + +/// Run `steps` and then draw a rectangle, once one command at a time and once as one +/// `command.batch`, and check that both leave the same default paints and give the rectangle drawn +/// in the batch, and one drawn after it, the same fill and stroke. Returns the batch's rectangle's +/// fill and stroke. +fn batch_matches_steps(steps: &[(&str, Value)]) -> (Paint, Paint) { + let shape = ("shape.rectangle", json!({"x": 0, "y": 0, "width": 10, "height": 10})); + let mut one_by_one = brand_defaults_session(); + for (id, p) in steps { + run(&mut one_by_one, id, p.clone()); + } + let single = rect(&mut one_by_one); + let mut batched = brand_defaults_session(); + let commands: Vec = steps.iter().chain([&shape]).map(|(id, p)| json!({"command": id, "params": p})).collect(); + let r = run(&mut batched, "command.batch", json!({ "commands": commands })); + let in_batch = NodeId(r["results"][steps.len()]["id"].as_u64().unwrap()); + assert_eq!(batched.paint.fill, one_by_one.paint.fill, "the default fill after {steps:?}"); + assert_eq!(batched.paint.stroke, one_by_one.paint.stroke, "the default stroke after {steps:?}"); + let expected = fill_and_stroke(&one_by_one, single); + assert_eq!(fill_and_stroke(&batched, in_batch), expected, "art drawn in the batch after {steps:?}"); + let later = rect(&mut batched); + assert_eq!(fill_and_stroke(&batched, later), expected, "art drawn after the batch after {steps:?}"); + expected +} + +#[test] +fn swatch_steps_in_a_batch_change_the_new_art_paints_as_commands_do() { + let blue = Paint::solid(Color::from_hex("#2a6fb0").unwrap()); + assert_eq!(batch_matches_steps(&[("swatch.delete", json!({"name": "Brand"}))]), (blue.clone(), blue)); + let link = linked("#2a6fb0", "Brand"); + assert_eq!(batch_matches_steps(&[("swatch.delete", json!({"name": "Brand", "unlink": false}))]), (link.clone(), link)); + let signal = linked("#00ff00", "Signal"); + let edit = ("swatch.edit", json!({"name": "Brand", "newName": "Signal", "color": "#00ff00"})); + assert_eq!(batch_matches_steps(&[edit]), (signal.clone(), signal)); + let other = linked("#ff8800", "Other"); + assert_eq!(batch_matches_steps(&[("swatch.merge", json!({"names": ["Other", "Brand"]}))]), (other.clone(), other)); + let gray = linked("#ababab", "Brand"); + assert_eq!(batch_matches_steps(&[("swatch.editGroup", json!({"group": "G", "colors": ["#ababab"]}))]), (gray.clone(), gray)); +} + +#[test] +fn undo_and_redo_of_a_swatch_edit_put_back_the_new_art_paints() { + let edit = json!({"name": "Brand", "newName": "Signal", "color": "#00ff00"}); + let delete = json!({"name": "Brand"}); + for (id, p, fill) in + [("swatch.edit", &edit, linked("#00ff00", "Signal")), ("swatch.delete", &delete, Paint::solid(Color::from_hex("#2a6fb0").unwrap()))] + { + for batch in [false, true] { + let mut s = brand_defaults_session(); + let before = s.paint.clone(); + if batch { + run(&mut s, "command.batch", json!({"commands": [{"command": id, "params": p}]})); + } else { + run(&mut s, id, p.clone()); + } + assert_eq!(s.paint.fill, fill, "{id}, batch: {batch}"); + let after = s.paint.clone(); + run(&mut s, "edit.undo", json!({})); + assert_eq!(s.paint, before, "Undo of {id}, batch: {batch}"); + run(&mut s, "edit.redo", json!({})); + assert_eq!(s.paint, after, "Redo of {id}, batch: {batch}"); + } + } +} + +#[test] +fn swatch_edits_reach_the_paints_of_the_new_art_template() { + let mut s = brand_defaults_session(); + s.paint.appearance = Some(vectorcraft_doc::Appearance::basic(linked("#2a6fb0", "Brand"), linked("#2a6fb0", "Brand"), 1.0)); + run(&mut s, "swatch.edit", json!({"name": "Brand", "newName": "Signal", "color": "#00ff00"})); + let template = |s: &Session| -> Vec { + s.paint + .appearance + .iter() + .flat_map(|a| a.items.iter()) + .map(|it| match it { + vectorcraft_doc::AppearanceItem::Fill(f) => f.paint.clone(), + vectorcraft_doc::AppearanceItem::Stroke(k) => k.paint.clone(), + }) + .collect() + }; + assert_eq!(template(&s), [linked("#00ff00", "Signal"), linked("#00ff00", "Signal")]); + run(&mut s, "swatch.delete", json!({"name": "Signal"})); + let green = Paint::solid(Color::from_hex("#00ff00").unwrap()); + assert_eq!(template(&s), [green.clone(), green]); +} + +#[test] +fn a_failed_batch_puts_back_the_new_art_paints_a_swatch_step_changed() { + let mut s = brand_defaults_session(); + let before = s.paint.clone(); + let steps = json!([ + {"command": "swatch.edit", "params": {"name": "Brand", "newName": "Signal", "color": "#00ff00"}}, + {"command": "no.such.command", "params": {}}, + ]); + assert!(s.execute("command.batch", &json!({ "commands": steps })).is_err()); + assert_eq!(s.paint, before); + assert_eq!(doc(&s).swatch("Brand").unwrap().paint.color(), Some(Color::from_hex("#2a6fb0").unwrap())); +} + +#[test] +fn canceling_a_swatch_options_preview_keeps_the_new_art_paints() { + let mut s = brand_defaults_session(); + let before = s.paint.clone(); + s.begin_interaction("Swatch Options").unwrap(); + s.preview("swatch.edit", &json!({"name": "Brand", "newName": "Signal", "color": "#00ff00"})).unwrap(); + s.cancel_interaction().unwrap(); + assert_eq!(s.paint, before); + assert!(doc(&s).swatch("Signal").is_none()); + // A previewed batch that is canceled puts them back too, and one that is accepted keeps them. + let steps = json!([{"command": "swatch.edit", "params": {"name": "Brand", "newName": "Signal", "color": "#00ff00"}}]); + s.begin_interaction("Batch Preview").unwrap(); + s.preview("command.batch", &json!({ "commands": steps })).unwrap(); + s.cancel_interaction().unwrap(); + assert_eq!(s.paint, before); + s.begin_interaction("Batch Preview").unwrap(); + s.preview("command.batch", &json!({ "commands": steps })).unwrap(); + s.commit_interaction().unwrap(); + assert_eq!(s.paint.fill, linked("#00ff00", "Signal")); + assert_eq!(s.paint.stroke, linked("#00ff00", "Signal")); +} + #[test] fn deleting_several_swatches_and_groups() { let mut s = session(); diff --git a/crates/engine/src/tests/symbol_nine_slice.rs b/crates/engine/src/tests/symbol_nine_slice.rs index b0689d1587..cba8b8c984 100644 --- a/crates/engine/src/tests/symbol_nine_slice.rs +++ b/crates/engine/src/tests/symbol_nine_slice.rs @@ -20,9 +20,18 @@ fn close(a: Rect, b: Rect) -> bool { /// A 100 × 100 frame with a 10 × 10 square in its top-left corner and one in its center, made /// into symbol "Panel" with 9-slice guides on, its instance selected at its natural size. fn panel_symbol() -> (Session, NodeId) { + panel_symbol_filled(None) +} + +/// [`panel_symbol`] with the frame filled with `fill` when there is one. +fn panel_symbol_filled(fill: Option) -> (Session, NodeId) { let mut s = Session::new(); s.execute("file.new", &json!({"width": 400, "height": 300})).unwrap(); let ids = [rect(&mut s, 50.0, 50.0, 100.0, 100.0), rect(&mut s, 50.0, 50.0, 10.0, 10.0), rect(&mut s, 95.0, 95.0, 10.0, 10.0)]; + if let Some(fill) = fill { + let doc = std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc); + doc.node_mut(ids[0]).unwrap().appearance = vectorcraft_doc::Appearance::basic(fill, vectorcraft_color::Paint::None, 0.0).into(); + } s.select(|_, sel| sel.set(ids)).unwrap(); let r = s.execute("symbol.new", &json!({"name": "Panel", "nineSlice": true})).unwrap(); assert_eq!(r["nineSlice"], json!([0.25, 0.25, 0.25, 0.25])); @@ -350,3 +359,39 @@ fn guides_outside_the_art_survive_saving_and_reopening_a_native_file() { assert!(back.symbol_slice_map(symbol, *xf).is_none(), "{bad}: scaled as a whole"); } } + +/// [`panel_symbol`] with a gradient on the frame, so that the frame is drawn in a clip group for +/// each cell, its instance resized to 200 × 150 and turned 20°. +fn turned_gradient_panel() -> (Session, NodeId) { + let gradient = vectorcraft_color::Paint::Gradient(Box::new(vectorcraft_color::GradientPaint::new(vectorcraft_color::Gradient::default()))); + let (mut s, id) = panel_symbol_filled(Some(gradient)); + s.execute("object.setBounds", &json!({"x": 50, "y": 50, "width": 200, "height": 150, "reference": 0})).unwrap(); + s.execute("object.rotate", &json!({"angle": 20})).unwrap(); + (s, id) +} + +/// The bounding box angles of the objects under the art that replaced an instance, and whether +/// that art holds a clip group. +fn expanded_angles(s: &Session, art: NodeId) -> (Vec, bool) { + let (mut angles, mut clips) = (vec![], false); + s.doc().unwrap().doc.node(art).unwrap().walk(&mut |c| { + angles.push(c.bbox_angle); + clips |= matches!(c.kind, NodeKind::Group { clip: true, .. }); + }); + (angles, clips) +} + +#[test] +fn break_link_turns_the_cells_of_a_sliced_instance_with_its_box() { + for reset in [false, true] { + let (mut s, _) = turned_gradient_panel(); + if reset { + assert_eq!(s.execute("object.resetBoundingBox", &json!({})).unwrap()["changed"], 1); + } + let r = s.execute("symbol.breakLink", &json!({})).unwrap(); + let (angles, clips) = expanded_angles(&s, NodeId(r["ids"][0].as_u64().unwrap())); + assert!(clips, "the frame is drawn in clip groups"); + let want = if reset { 0.0 } else { 20.0 }; + assert!(angles.iter().all(|a| (a - want).abs() < 1e-6), "reset {reset}: {angles:?}"); + } +} diff --git a/crates/render/src/frame.rs b/crates/render/src/frame.rs index e16f134aca..7d000aa64f 100644 --- a/crates/render/src/frame.rs +++ b/crates/render/src/frame.rs @@ -110,8 +110,8 @@ pub(crate) struct PlacedEntry { pub(crate) art: std::sync::Weak, /// The art placed, or `None` for art placed again in every frame ([`depends_on_document`]). pub(crate) placed: Option>, - /// The font generation ([`vectorcraft_text::FontDb::generation`]) the art was placed in, when - /// it holds type: the art is placed again when the fonts change. + /// The layout inputs ([`vectorcraft_text::layout_inputs`]) the art was placed with, when it + /// holds type: the art is placed again when the fonts or the hyphenation exceptions change. pub(crate) fonts: Option, /// The 9-slice map the art was placed through ([`Renderer::sliced_art`]), or `None` for art /// placed by the transform alone ([`Renderer::placed_art`]). An entry is used only by the diff --git a/crates/render/src/fx/pixels.rs b/crates/render/src/fx/pixels.rs index 72731f7330..cdf817f1e4 100644 --- a/crates/render/src/fx/pixels.rs +++ b/crates/render/src/fx/pixels.rs @@ -412,7 +412,7 @@ impl Renderer { /// brush library it reads; for images and placed documents their pixels and files, the /// layer's Dim Images and the options they are drawn with (with /// [`crate::RenderOptions::kept_images_only`], also which pixels and undecodable notes the - /// image store holds); for type the fonts, whether overprinting shows + /// image store holds); for type the fonts and the hyphenation exceptions, whether overprinting shows /// ([`crate::proof::overprints`]) and Document Setup's substitution highlights; and the /// plug-ins installed, with the names of the document's swatches and patterns and its pattern /// definitions (a plug-in's painted pieces can name them), when an object in it has a plug-in @@ -457,7 +457,7 @@ impl Renderer { f.doc.setup.highlight_substituted_glyphs, o.highlight_alternate_glyphs, )); - (vectorcraft_text::FontDb::global().generation(), crate::proof::overprints(f.opts), highlights).hash(&mut h); + (vectorcraft_text::layout_inputs(), crate::proof::overprints(f.opts), highlights).hash(&mut h); } if reads.plugins || (doc.plugins && (reads.symbols || reads.patterns)) { (effects::plugin_revision(), doc.names, doc.patterns).hash(&mut h); diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index 141c3524c5..6a92d91e8f 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -65,8 +65,8 @@ pub struct Renderer { /// The latest cached glyph geometry for each text object id. A move changes the node's Arc /// but not its glyphs in text space, so the old geometry can still be used after comparison. text_ids: PtrMap, - /// The [`vectorcraft_text::FontDb::generation`] `texts` was laid out with: type lays out - /// again when fonts are added or rescanned. + /// The [`vectorcraft_text::layout_inputs`] `texts` was laid out with: type lays out again + /// when fonts are added or rescanned and when the hyphenation exceptions change. text_fonts: u64, /// Clip regions per clipping path (see [`Self::clip_of`]). clips: FrameCache, diff --git a/crates/render/src/live.rs b/crates/render/src/live.rs index 4d41e16af8..3777c98948 100644 --- a/crates/render/src/live.rs +++ b/crates/render/src/live.rs @@ -127,8 +127,9 @@ struct Walked { } impl Walked { - /// The [`resources_key`] of the node walked: the walk's hash, the font generation when it found - /// type or a placed file, the plug-in revision and the hash of the document's swatch and pattern + /// The [`resources_key`] of the node walked: the walk's hash, the layout inputs (fonts and + /// hyphenation exceptions, [`vectorcraft_text::layout_inputs`]) when it found type or a placed + /// file, the plug-in revision and the hash of the document's swatch and pattern /// names (`names`) when it found a plug-in effect, and the color settings `cms`. Whether a /// plug-in paints its pieces depends on the plug-ins installed, so the names count for every /// plug-in effect. @@ -136,7 +137,7 @@ impl Walked { let mut h = DefaultHasher::new(); self.hash.hash(&mut h); if self.text { - vectorcraft_text::FontDb::global().generation().hash(&mut h); + vectorcraft_text::layout_inputs().hash(&mut h); } if self.plugins { crate::effects::plugin_revision().hash(&mut h); diff --git a/crates/render/src/pattern.rs b/crates/render/src/pattern.rs index 2372abdbf2..317a423681 100644 --- a/crates/render/src/pattern.rs +++ b/crates/render/src/pattern.rs @@ -39,7 +39,8 @@ type TileKey = (String, u64, Ink, bool); /// What a tile was drawn from besides its pattern's own art, for art that shows more than itself: /// the art of every pattern and symbol and the pixels of every image in the document, the -/// document's other data (which holds its brushes), and the fonts. Editing a symbol leaves the art +/// document's other data (which holds its brushes), and the fonts and hyphenation exceptions +/// ([`vectorcraft_text::layout_inputs`]). Editing a symbol leaves the art /// of a pattern that shows it as it was, so the art alone kept the tile from before (#1723). Held /// weakly: a weak reference keeps the allocation, so no other value gets one of these addresses /// while the tile is kept. @@ -66,13 +67,13 @@ impl Deps { art: Self::art(doc).map(Arc::downgrade).collect(), pixels: Self::pixels(doc).map(Arc::downgrade).collect(), unknown: vectorcraft_doc::Shared::downgrade(&doc.unknown), - fonts: vectorcraft_text::FontDb::global().generation(), + fonts: vectorcraft_text::layout_inputs(), } } /// Does `doc` hold what the tile was drawn from? fn current(&self, doc: &Document) -> bool { - self.fonts == vectorcraft_text::FontDb::global().generation() + self.fonts == vectorcraft_text::layout_inputs() && std::ptr::eq(self.unknown.as_ptr(), &*doc.unknown) && self.art.iter().map(Weak::as_ptr).eq(Self::art(doc).map(Arc::as_ptr)) && self.pixels.iter().map(Weak::as_ptr).eq(Self::pixels(doc).map(Arc::as_ptr)) diff --git a/crates/render/src/renderer/text.rs b/crates/render/src/renderer/text.rs index b4a0dd0d2e..945ce5303b 100644 --- a/crates/render/src/renderer/text.rs +++ b/crates/render/src/renderer/text.rs @@ -55,7 +55,7 @@ impl Renderer { /// objects) hit for them. Other art is placed again in every frame, and so is art that holds /// symbol instances, type with inline graphics, images, placed documents or raster effects /// ([`depends_on_document`]), and art that the cache has no room for. Art that holds type is - /// placed again when the fonts change. + /// placed again when the fonts or the hyphenation exceptions change. pub(super) fn placed_art(&mut self, art: &Arc, xf: Affine, scale_strokes: bool, inst: Option<&Node>) -> (Arc, bool) { let kept_kind = matches!(art.kind, NodeKind::Group { .. } | NodeKind::Layer { .. }) || vectorcraft_doc::live::is_live(art); // An instance with appearance changes of its own isn't kept: the key doesn't tell them apart. @@ -67,7 +67,7 @@ impl Renderer { let key = (Arc::as_ptr(art) as usize, xf.as_coeffs().map(f64::to_bits), scale_strokes, stain); if let Some(e) = self.placed_arts.get(&key, self.stamp) && std::ptr::eq(e.art.as_ptr(), Arc::as_ptr(art)) - && e.fonts.is_none_or(|g| g == vectorcraft_text::FontDb::global().generation()) + && e.fonts.is_none_or(|g| g == vectorcraft_text::layout_inputs()) && e.slice.is_none() { return match &e.placed { @@ -106,7 +106,7 @@ impl Renderer { if keeps && let Some(e) = self.placed_arts.get(&key, self.stamp) && std::ptr::eq(e.art.as_ptr(), Arc::as_ptr(art)) - && e.fonts.is_none_or(|g| g == vectorcraft_text::FontDb::global().generation()) + && e.fonts.is_none_or(|g| g == vectorcraft_text::layout_inputs()) && e.slice.as_ref() == Some(map) { match e.placed.clone() { @@ -134,7 +134,7 @@ impl Renderer { fn keep_placed(&mut self, key: PlacedKey, art: &Arc, placed: &Arc, slice: Option) -> bool { let kept = (!depends_on_document(art)).then(|| placed.clone()); let keeps = kept.is_some(); - let fonts = (keeps && holds_type(art)).then(|| vectorcraft_text::FontDb::global().generation()); + let fonts = (keeps && holds_type(art)).then(vectorcraft_text::layout_inputs); // The bytes count the key and the entry, the art's allocation that the weak reference // keeps, and the kept art. let bytes = size_of::<(PlacedKey, PlacedEntry, Node)>() + kept.as_deref().map_or(0, lru::node_bytes); @@ -150,7 +150,7 @@ impl Renderer { if !matches!(&a.kind, NodeKind::Text(own) if std::ptr::eq(&**own, t)) { return (Arc::new(text_geom(t)), false); } - let fonts = vectorcraft_text::FontDb::global().generation(); + let fonts = vectorcraft_text::layout_inputs(); if fonts != self.text_fonts { self.texts.clear(); self.text_ids.clear(); diff --git a/crates/render/src/tests/fontchange.rs b/crates/render/src/tests/fontchange.rs index bedffb6b4b..15389cd805 100644 --- a/crates/render/src/tests/fontchange.rs +++ b/crates/render/src/tests/fontchange.rs @@ -3,16 +3,16 @@ use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use vectorcraft_doc::text::{CharStyle, TextObject}; +use vectorcraft_doc::text::{CharStyle, TextKind, TextObject}; use vectorcraft_doc::{Node, NodeKind}; -use vectorcraft_geom::Point; +use vectorcraft_geom::{PathData, Point}; use crate::*; -/// Taken to add fonts, or to look up an installed one by name (`FontDb::face` loads it, which -/// changes the fonts too). Renderers lay type out again when the fonts change, so tests of what -/// they keep between frames hold it shared ([`fonts_steady`]) and the tests that change the fonts -/// hold it alone ([`adding_fonts`]). +/// Taken to add fonts, to look up an installed one by name (`FontDb::face` loads it, which +/// changes the fonts too) or to change the hyphenation exceptions. Renderers lay type out again +/// when the fonts or the exceptions change, so tests of what they keep between frames hold it +/// shared ([`fonts_steady`]) and the tests that change them hold it alone ([`adding_fonts`]). static FONTS: RwLock<()> = RwLock::new(()); /// No fonts are added by these tests until the guard is dropped. @@ -29,14 +29,12 @@ pub(crate) fn adding_fonts() -> RwLockWriteGuard<'static, ()> { /// What `step` returns from a run in which the fonts stayed the same. The fonts can change while /// [`fonts_steady`] is held: the first lookup by family name catalogs the installed fonts, and /// resolving a cataloged family, or a character no loaded font has, loads a face. `step` runs up -/// to 100 times, until [`vectorcraft_text::FontDb::generation`] is the same after a run as before -/// it. +/// to 100 times, until [`vectorcraft_text::layout_inputs`] is the same after a run as before it. pub(crate) fn with_fonts_unchanged(mut step: impl FnMut() -> T) -> T { - let db = vectorcraft_text::FontDb::global(); for _ in 0..100 { - let before = db.generation(); + let before = vectorcraft_text::layout_inputs(); let out = step(); - if db.generation() == before { + if vectorcraft_text::layout_inputs() == before { return out; } } @@ -466,6 +464,75 @@ fn enveloped_type_under_effects_redraws_when_its_font_becomes_available() { } } +/// Hyphenated area type redraws with its new line breaks when Preferences › Hyphenation › +/// Exceptions change: its glyph geometry, the pixels of its raster effects, the art drawn for +/// geometry effects, the art kept for a symbol instance and an envelope's evaluation are made +/// again. +#[test] +fn hyphenated_type_redraws_when_the_exceptions_change() { + let _adding = adding_fonts(); + struct Clear; + impl Drop for Clear { + fn drop(&mut self) { + vectorcraft_text::set_hyphenation_exceptions(""); + } + } + let _clear = Clear; + use vectorcraft_doc::Effect; + let moved = || Effect { id: "distort.transform".into(), params: serde_json::json!({"moveH": 0.0}), visible: true }; + const WORDS: &str = "Extraordinarily comprehensive typographical considerations notwithstanding everything."; + const NEVER: &str = "extraordinarily, comprehensive, typographical, considerations, notwithstanding"; + let cases = ["the area type", "the type with a drop shadow", "the group with a Transform effect", "the symbol instance", "the envelope"]; + for (i, what) in cases.into_iter().enumerate() { + vectorcraft_text::set_hyphenation_exceptions(""); + let mut d = Document::new(300.0, 150.0); + let mut t = TextObject::point(Point::ZERO, WORDS, CharStyle { size: 14.0, ..Default::default() }); + t.kind = TextKind::Area { frame: PathData::from_bezpath(&Rect::new(10.0, 10.0, 130.0, 145.0).to_path(0.1)) }; + t.xf = Affine::IDENTITY; + t.para.hyphenate = true; + let mut object = Node::new(d.alloc_id(), NodeKind::Text(Box::new(t))); + match i { + 0 => {} + 1 => { + let params = serde_json::json!({"x": 4, "y": 4, "blur": 1, "opacity": 100}); + object.appearance.effects.push(Effect { id: "stylize.dropShadow".into(), params, visible: true }); + } + 2 => { + object = Node::group(d.alloc_id(), vec![Arc::new(object)]); + object.appearance.effects.push(moved()); + } + 3 => { + object.appearance.effects.push(moved()); + let art = Node::group(d.alloc_id(), vec![Arc::new(object)]); + d.symbols.push(vectorcraft_doc::Symbol { dynamic: false, name: "Words".into(), art: Arc::new(art) }); + object = Node::new(d.alloc_id(), NodeKind::SymbolInstance { symbol: "Words".into(), xf: Affine::IDENTITY }); + } + _ => { + let kind = vectorcraft_doc::EnvelopeKind::Warp { style: "arc".into(), bend: 30.0, h: 0.0, v: 0.0, horizontal: true, version: 0 }; + let envelope = NodeKind::Envelope { + content: vec![Arc::new(object)], + kind: Box::new(kind), + fidelity: 50.0, + editing: false, + options: Default::default(), + frame: Box::new(Affine::IDENTITY), + }; + object = Node::new(d.alloc_id(), envelope); + } + } + let l = d.layers[0].id; + d.insert(Some(l), 0, object).unwrap(); + let opts = RenderOptions { background: Some([255, 255, 255, 255]), ..Default::default() }; + let mut r = Renderer::new(); + let before = r.render(&d, 300, 150, Affine::IDENTITY, &opts).pixels; + vectorcraft_text::set_hyphenation_exceptions(NEVER); + let after = r.render(&d, 300, 150, Affine::IDENTITY, &opts).pixels; + let fresh = Renderer::new().render(&d, 300, 150, Affine::IDENTITY, &opts).pixels; + assert_ne!(before, fresh, "{what}: the words in the list are not broken"); + assert!(after == fresh, "{what}: drawn as a new renderer draws it"); + } +} + /// Without an engine session, a renderer maps an envelope of type from its glyph outline bounds, /// and measures the type again when its font becomes available. #[test] diff --git a/crates/render/src/tests/memory.rs b/crates/render/src/tests/memory.rs index d286fa7e3c..1f7a49698c 100644 --- a/crates/render/src/tests/memory.rs +++ b/crates/render/src/tests/memory.rs @@ -320,13 +320,13 @@ fn kept_glyphs(r: &mut Renderer, d: &Document) -> Vec>> { .collect() } -/// `f`'s result from a run during which the fonts did not change: other tests add fonts, and the -/// renderer lays all type out again when the fonts change. +/// `f`'s result from a run during which the fonts and the hyphenation exceptions did not change: +/// other tests change them, and the renderer lays all type out again when they change. fn fonts_unchanged(mut f: impl FnMut() -> T) -> T { loop { - let fonts = vectorcraft_text::FontDb::global().generation(); + let inputs = vectorcraft_text::layout_inputs(); let t = f(); - if vectorcraft_text::FontDb::global().generation() == fonts { + if vectorcraft_text::layout_inputs() == inputs { return t; } } diff --git a/crates/render/src/tests/typeedges.rs b/crates/render/src/tests/typeedges.rs index fae0207d0d..3295342ce8 100644 --- a/crates/render/src/tests/typeedges.rs +++ b/crates/render/src/tests/typeedges.rs @@ -859,7 +859,7 @@ fn type_outside_its_frame_is_drawn() { fn a_pan_draws_the_type_from_the_kept_pixels() { let _fonts = crate::tests_fontchange::fonts_steady(); let opts = RenderOptions::default(); - let fonts = || vectorcraft_text::FontDb::global().generation(); + let fonts = vectorcraft_text::layout_inputs; // How many type objects a renderer drew offscreen for `b` in `second` after drawing `a` in // `first`. The second frame's pixels are a new renderer's, each channel within `near`. The // frames are drawn again while the fonts change between them (other tests load fonts, and the diff --git a/crates/svg/src/lib.rs b/crates/svg/src/lib.rs index 23cc07d3c1..b035e6cd10 100644 --- a/crates/svg/src/lib.rs +++ b/crates/svg/src/lib.rs @@ -491,16 +491,10 @@ pub(crate) fn text_within<'a>(bytes: &'a [u8], unpacked: &std::sync::atomic::Ato match craft_svg::svgz::inflate(bytes, most) { Ok(raw) => { unpacked.fetch_add(raw.len() as u64, Ordering::Relaxed); - craft_svg::svgz::decode(&raw) - .map(|t| std::borrow::Cow::Owned(t.into_owned())) - .map_err(|_| not_utf8()) - } - Err(craft_svg::svgz::Error::TooLarge(_)) => { - Err(SvgError::TooBig(format!("the SVGZ file unpacks to more than {} MB", most >> 20))) - } - Err(craft_svg::svgz::Error::Corrupt(e)) => { - Err(SvgError::Parse(format!("not a valid SVGZ file: {e}"))) + craft_svg::svgz::decode(&raw).map(|t| std::borrow::Cow::Owned(t.into_owned())).map_err(|_| not_utf8()) } + Err(craft_svg::svgz::Error::TooLarge(_)) => Err(SvgError::TooBig(format!("the SVGZ file unpacks to more than {} MB", most >> 20))), + Err(craft_svg::svgz::Error::Corrupt(e)) => Err(SvgError::Parse(format!("not a valid SVGZ file: {e}"))), Err(craft_svg::svgz::Error::Encoding) => Err(not_utf8()), Err(e) => Err(SvgError::Parse(e.to_string())), } diff --git a/crates/text/src/hyphen.rs b/crates/text/src/hyphen.rs index e293346279..c940ed85a4 100644 --- a/crates/text/src/hyphen.rs +++ b/crates/text/src/hyphen.rs @@ -502,16 +502,16 @@ mod tests { } /// Process-wide store used by `prefs.set` / restore. Each change makes envelopes measure type - /// again. + /// again, and caches of layouts lay type out again. #[test] fn set_hyphenation_exceptions_round_trips_the_source_string() { - let inputs = crate::layout::envelope_ink_inputs(); + let inputs = crate::layout_inputs(); set_hyphenation_exceptions("typography, hap-pen"); assert_eq!(hyphenation_exceptions(), "typography, hap-pen"); - let changed = crate::layout::envelope_ink_inputs(); - assert_ne!(changed, inputs, "the envelope inputs change with the exceptions"); + let changed = crate::layout_inputs(); + assert_ne!(changed, inputs, "the layout inputs change with the exceptions"); set_hyphenation_exceptions(""); assert!(hyphenation_exceptions().is_empty()); - assert_ne!(crate::layout::envelope_ink_inputs(), changed, "and again when they are cleared"); + assert_ne!(crate::layout_inputs(), changed, "and again when they are cleared"); } } diff --git a/crates/text/src/layout.rs b/crates/text/src/layout.rs index 82a849a3dc..a7d7d1d3f3 100644 --- a/crates/text/src/layout.rs +++ b/crates/text/src/layout.rs @@ -46,9 +46,7 @@ pub(crate) use driver::{fit_passes, layout_faces_per_call}; pub(crate) use on_path::{layout_trying_each_start, path_arrangements}; use vertical::{TcyStyle, stands_upright, tate_chu_yoko, upright_cell, upright_centre, upright_extent, whole_character_widths}; -#[cfg(test)] -pub(crate) use driver::envelope_ink_inputs; -pub use driver::{envelope_ink, register_envelope_ink}; +pub use driver::{envelope_ink, layout_inputs, register_envelope_ink}; const EPS: f64 = 1e-6; diff --git a/crates/text/src/layout/driver.rs b/crates/text/src/layout/driver.rs index 9108cc171d..59c6ac38bf 100644 --- a/crates/text/src/layout/driver.rs +++ b/crates/text/src/layout/driver.rs @@ -191,12 +191,13 @@ pub fn envelope_ink(t: &TextObject, m: Affine, projection: Option<(vectorcraft_g /// Make envelopes map type from [`envelope_ink`], measured again when the fonts or the hyphenation /// exceptions change (the first registration stays, see `vectorcraft_doc::live::set_type_ink`). pub fn register_envelope_ink() { - vectorcraft_doc::live::set_type_ink(envelope_ink, envelope_ink_inputs); + vectorcraft_doc::live::set_type_ink(envelope_ink, layout_inputs); } -/// A number that changes whenever what [`envelope_ink`] reads besides the type changes: the -/// installed fonts and the hyphenation exceptions. -pub(crate) fn envelope_ink_inputs() -> u64 { +/// A number that changes when the fonts ([`FontDb::generation`]) or the hyphenation exceptions +/// (Preferences › Hyphenation › Exceptions) change. Caches of layouts made with the global font +/// database, and of art made from them, key on it. +pub fn layout_inputs() -> u64 { FontDb::global().generation().rotate_left(32) ^ crate::hyphen::exceptions_generation() } diff --git a/crates/text/src/lib.rs b/crates/text/src/lib.rs index 3065b9a153..362a1c2408 100644 --- a/crates/text/src/lib.rs +++ b/crates/text/src/lib.rs @@ -47,7 +47,7 @@ pub use fontdb::{ user_font_dirs, }; pub use hyphen::{hyphenation_exceptions, set_hyphenation_exceptions}; -pub use layout::{envelope_ink, register_envelope_ink}; +pub use layout::{envelope_ink, layout_inputs, register_envelope_ink}; use std::sync::Arc; pub use svg_glyph::{SvgGlyphReader, set_svg_glyph_reader}; diff --git a/crates/tools/src/addons/parametric_shape.rs b/crates/tools/src/addons/parametric_shape.rs index d16cb63935..68a42a665f 100644 --- a/crates/tools/src/addons/parametric_shape.rs +++ b/crates/tools/src/addons/parametric_shape.rs @@ -4,7 +4,9 @@ //! dragging, ←/→ its second value or corner radius. A click selects a parametric shape and shows //! its handles (centre, size, rotation, corner radius and one of the kind's own), whose drags run //! `addon.pathtools.shape.set`; a double-click on the canvas places one with the last settings. -//! Each gesture is one undo step. +//! Each gesture is one undo step. A new shape's center (from a press or a double-click) and the +//! point dragged out from it snap as a drawing tool's points do ([`DrawSnap`]), hovering before +//! the press too. //! //! A parametric shape is an ordinary path that keeps its numbers in one entry of its object data //! ([`KEY`]) with a fingerprint of the outline they drew. Moved, turned or scaled by any tool it @@ -17,6 +19,7 @@ use vectorcraft_geom::{Affine, BezPath, PathData, Point, Vec2}; use vectorcraft_pathops::addons::pathtools::shapes::fingerprint; pub use vectorcraft_pathops::addons::pathtools::shapes::{MAX_COUNT, MAX_SIZE, MIN_COUNT, MIN_SIZE, ParametricShape, ShapeKind}; +use crate::guides::DrawSnap; use crate::{Action, Cursor, Mods, Overlay, PointerEvent, PointerKind, Tool, ToolContext, ToolKey}; /// The tool's id. @@ -209,7 +212,7 @@ fn angle(c: Point, p: Point, shift: bool) -> f64 { #[derive(Clone, Debug, PartialEq)] enum Drag { /// Drawing a shape out from its centre. - Create { center: Point }, + Create { center: Point, from: Point }, /// Dragging a handle of shape `id`, which was `shape` when the drag began at `from`. Edit { id: NodeId, shape: ParametricShape, grip: Grip, from: Point }, } @@ -221,11 +224,18 @@ pub struct ParametricShapeTool { drag: Option, /// Where the pointer last was during the drag, and the keys held. last: (Point, Mods), + /// Smart Guides for a new shape's center and the point dragged out from it. + snap: DrawSnap, } impl Default for ParametricShapeTool { fn default() -> Self { - Self { next: ParametricShape::new(ShapeKind::Polygon, Point::ZERO, 100.0, 100.0), drag: None, last: (Point::ZERO, Mods::default()) } + Self { + next: ParametricShape::new(ShapeKind::Polygon, Point::ZERO, 100.0, 100.0), + drag: None, + last: (Point::ZERO, Mods::default()), + snap: DrawSnap::default(), + } } } @@ -247,7 +257,7 @@ impl ParametricShapeTool { fn shaped(&self, drag: &Drag, p: Point, mods: Mods) -> (&'static str, ParametricShape, Option) { let fit = |v: f64| v.clamp(MIN_SIZE, MAX_SIZE); match *drag { - Drag::Create { center } => { + Drag::Create { center, .. } => { let r = center.distance(p); let aspect = self.next.width / self.next.height; let s = ParametricShape { @@ -288,6 +298,18 @@ impl ParametricShapeTool { } Some(Action::Preview(cmd.into(), p)) } + + /// Show the Smart Guides of a new shape's center at `p`, the pointer hovering; none over a + /// handle of the selected shape or over a parametric shape, where a press does not draw. + fn hover(&mut self, cx: &ToolContext, p: Point) { + let tol = cx.point_tol(); + let on_grip = selected(cx).is_some_and(|(_, s)| grips(cx, &s).iter().any(|(_, at)| at.distance(p) <= tol)); + if on_grip || shape_at(cx, p).is_some() { + self.snap.clear(); + } else { + self.snap.hover(cx, p, &[], None); + } + } } impl Tool for ParametricShapeTool { @@ -300,6 +322,9 @@ impl Tool for ParametricShapeTool { } fn pointer(&mut self, cx: &ToolContext, ev: &PointerEvent) -> Vec { + if ev.kind == PointerKind::Move && self.drag.is_none() { + self.hover(cx, ev.pos); + } match ev.kind { PointerKind::Move => vec![], PointerKind::Down => { @@ -309,15 +334,17 @@ impl Tool for ParametricShapeTool { near.min_by(|a, b| a.1.distance(ev.pos).total_cmp(&b.1.distance(ev.pos))).map(|(g, _)| (id, s, g)) }); if let Some((id, shape, grip)) = grip { + self.snap.clear(); self.drag = Some(Drag::Edit { id, shape, grip, from: ev.pos }); self.last = (ev.pos, ev.mods); return vec![Action::Begin(EDIT.into())]; } if let Some(id) = shape_at(cx, ev.pos) { + self.snap.clear(); return if cx.selection.objects == [id] { vec![] } else { vec![Action::Exec("select.set".into(), json!({ "ids": [id.0] }))] }; } - let (center, _) = crate::guides::snap_draw(cx, ev.pos, &[]); - self.drag = Some(Drag::Create { center }); + let center = self.snap.press(cx, ev.pos, &[], None); + self.drag = Some(Drag::Create { center, from: ev.pos }); self.last = (center, ev.mods); vec![Action::Begin(CREATE.into())] } @@ -325,15 +352,19 @@ impl Tool for ParametricShapeTool { if self.drag.is_none() { return vec![]; } - self.last = (ev.pos, ev.mods); + // The point a new shape is dragged out to snaps; a handle's drag does not. + let pos = if matches!(self.drag, Some(Drag::Create { .. })) { self.snap.drag(cx, ev.pos, None) } else { ev.pos }; + self.last = (pos, ev.mods); let Some(preview) = self.preview() else { return vec![] }; if ev.kind == PointerKind::Drag { return vec![preview]; } + self.snap.clear(); let Some(drag) = self.drag.take() else { return vec![] }; match drag { - // A click draws nothing (a double-click places a shape). - Drag::Create { center } if center.distance(ev.pos) <= cx.tol(2.0) => vec![Action::Cancel], + // A click draws nothing (a double-click places a shape), even when its center + // snapped a few pixels from where it was pressed. + Drag::Create { from, .. } if from.distance(ev.pos) <= cx.tol(2.0) => vec![Action::Cancel], Drag::Create { .. } => { if let Action::Preview(_, p) = &preview && let Ok(s) = apply(self.next, p) @@ -350,7 +381,8 @@ impl Tool for ParametricShapeTool { if self.drag.is_some() || shape_at(cx, ev.pos).is_some() { return vec![]; } - let s = ParametricShape { center: ev.pos, ..self.next }; + let s = ParametricShape { center: self.snap.press(cx, ev.pos, &[], None), ..self.next }; + self.snap.clear(); vec![Action::Exec("addon.pathtools.shape.create".into(), to_json(&s))] } } @@ -358,6 +390,7 @@ impl Tool for ParametricShapeTool { fn key(&mut self, cx: &ToolContext, key: ToolKey, _mods: Mods) -> Vec { if key == ToolKey::Escape && self.drag.take().is_some() { + self.snap.clear(); return vec![Action::Cancel]; } if !matches!(self.drag, Some(Drag::Create { .. })) { @@ -385,13 +418,16 @@ impl Tool for ParametricShapeTool { } fn overlays(&self, cx: &ToolContext) -> Vec { - if let Some(Drag::Create { center }) = &self.drag { - let (_, s, _) = self.shaped(&Drag::Create { center: *center }, self.last.0, self.last.1); + if let Some(drag @ Drag::Create { .. }) = &self.drag { + let (_, s, _) = self.shaped(drag, self.last.0, self.last.1); let text = format!("{}\nAngle: {:.1}°", cx.size_label(s.width, s.height), s.rotation); - return vec![Overlay::Measure { p: self.last.0 + Vec2::new(cx.tol(12.0), cx.tol(12.0)), text }]; + let mut out = self.snap.guides().to_vec(); + out.push(Overlay::Measure { p: self.last.0 + Vec2::new(cx.tol(12.0), cx.tol(12.0)), text }); + return out; } - let Some((_, s)) = selected(cx) else { return vec![] }; - // The shape's box, then its handles. + // The hovering pointer's Smart Guides, then the selected shape's box and handles. + let mut out = self.snap.guides().to_vec(); + let Some((_, s)) = selected(cx) else { return out }; let (rx, ry) = (s.width / 2.0, s.height / 2.0); let mut bp = BezPath::new(); let f: Affine = s.frame(); @@ -400,7 +436,7 @@ impl Tool for ParametricShapeTool { if i == 0 { bp.move_to(*p) } else { bp.line_to(*p) } } bp.close_path(); - let mut out = vec![Overlay::Path { path: bp, color: BLUE, width: 1.0, dashed: true }]; + out.push(Overlay::Path { path: bp, color: BLUE, width: 1.0, dashed: true }); for (grip, p) in grips(cx, &s) { if grip == Grip::Rotate { out.push(Overlay::Line { a: f * Point::new(0.0, -ry), b: p, color: BLUE, dashed: false }); @@ -418,6 +454,11 @@ impl Tool for ParametricShapeTool { Cursor::ParametricShape } + fn deactivate(&mut self, _cx: &ToolContext) -> Vec { + self.snap.clear(); + vec![] + } + /// The next shape's numbers (its size and rotation are a double-click's). fn options(&self) -> Value { let mut v = to_json(&self.next); diff --git a/crates/tools/src/guides/tests.rs b/crates/tools/src/guides/tests.rs index 1b6ddbaa12..602242d1cd 100644 --- a/crates/tools/src/guides/tests.rs +++ b/crates/tools/src/guides/tests.rs @@ -714,6 +714,81 @@ fn pen_click_near_a_glyph_anchor_lands_on_it() { assert!(q.distance(anchor) > 1e-3, "{q:?} landed on the glyph anchor with Smart Guides off"); } +/// Snap to Glyph: the Parametric Shape tool's center (a drag and a double-click) and the point +/// dragged out from it, and the Slice tool's corners, land on a glyph's anchor point as a Pen +/// click does, with the guides shown while hovering, and not with Snap to Glyph off. +#[test] +fn parametric_shape_and_slice_points_land_on_a_glyph_anchor() { + use crate::addons::parametric_shape::ParametricShapeTool; + use crate::slice::SliceTool; + use crate::{Action, PointerEvent, PointerKind, Tool}; + let (d, t) = glyph_doc("H", 0.0); + let lay = layout_text(FontDb::global(), &t); + let g = lay.glyphs.iter().find(|g| !g.outline.elements().is_empty()).expect("a glyph with an outline"); + // An anchor inside the glyph's bounds, which no glyph bounds line passes through. + let bb = g.outline.bounding_box(); + let inside = |p: Point| p.x > bb.x0 + 1.0 && p.x < bb.x1 - 1.0 && p.y > bb.y0 + 1.0 && p.y < bb.y1 - 1.0; + let anchor = t.xf * g.outline.segments().map(|s| s.start()).find(|p| inside(*p)).expect("an anchor inside the glyph"); + let (s, p) = (Selection::default(), paint()); + let click = anchor + Vec2::new(1.5, -1.0); + let ev = |kind, q: Point| PointerEvent::new(kind, q.x, q.y); + let center = |v: &serde_json::Value| Point::new(v["center"][0].as_f64().unwrap(), v["center"][1].as_f64().unwrap()); + // A press away from the type, for drags that end at the click. + let away = anchor + Vec2::new(-83.3, -61.7); + for glyphs in [true, false] { + let c = ToolContext { snap_to_glyph: glyphs, ..cx(&d, &s, &p) }; + let lands = |q: Point| q.distance(anchor) < 1e-9; + // A Parametric Shape drawn out from the click. + let mut tool = ParametricShapeTool::default(); + tool.pointer(&c, &ev(PointerKind::Down, click)); + let acts = tool.pointer(&c, &ev(PointerKind::Drag, click + Vec2::new(80.0, 60.0))); + let Some(Action::Preview(_, v)) = acts.first() else { panic!("{acts:?}") }; + assert_eq!(lands(center(v)), glyphs, "drag, Snap to Glyph {glyphs}: {:?} vs {anchor:?}", center(v)); + // A Parametric Shape dragged out to the click is sized and turned as one dragged out to + // the anchor itself. + let drawn_to = |q: Point| { + let mut tool = ParametricShapeTool::default(); + tool.pointer(&c, &ev(PointerKind::Down, away)); + tool.pointer(&c, &ev(PointerKind::Drag, q)) + }; + assert_eq!(drawn_to(click) == drawn_to(anchor), glyphs, "dragged point, Snap to Glyph {glyphs}"); + // A click 3 px from the anchor draws nothing, though its center snaps onto the anchor. + let near = anchor + Vec2::new(2.5, -1.5); + let mut tool = ParametricShapeTool::default(); + tool.pointer(&c, &ev(PointerKind::Down, near)); + let acts = tool.pointer(&c, &ev(PointerKind::Drag, near)); + let Some(Action::Preview(_, v)) = acts.first() else { panic!("{acts:?}") }; + assert_eq!(lands(center(v)), glyphs, "click, Snap to Glyph {glyphs}: {:?} vs {anchor:?}", center(v)); + assert_eq!(tool.pointer(&c, &ev(PointerKind::Up, near)), vec![Action::Cancel], "click, Snap to Glyph {glyphs}"); + // One placed with a double-click. + let mut tool = ParametricShapeTool::default(); + let acts = tool.pointer(&c, &ev(PointerKind::DoubleClick, click)); + let Some(Action::Exec(_, v)) = acts.first() else { panic!("{acts:?}") }; + assert_eq!(lands(center(v)), glyphs, "double-click, Snap to Glyph {glyphs}: {:?} vs {anchor:?}", center(v)); + // The pointer hovering at the click shows the guides of the anchor it would land on. + let mut tool = ParametricShapeTool::default(); + tool.pointer(&c, &ev(PointerKind::Move, click)); + assert_eq!(!tool.overlays(&c).is_empty(), glyphs, "hover, Snap to Glyph {glyphs}"); + // A slice dragged from the click down and to the right starts at its top-left corner. + let mut tool = SliceTool::default(); + tool.pointer(&c, &ev(PointerKind::Move, click)); + assert_eq!(!tool.overlays(&c).is_empty(), glyphs, "slice hover, Snap to Glyph {glyphs}"); + tool.pointer(&c, &ev(PointerKind::Down, click)); + let acts = tool.pointer(&c, &ev(PointerKind::Drag, click + Vec2::new(80.0, 60.0))); + let Some(Action::Preview(_, v)) = acts.get(1) else { panic!("{acts:?}") }; + let corner = Point::new(v["x"].as_f64().unwrap(), v["y"].as_f64().unwrap()); + assert_eq!(lands(corner), glyphs, "slice, Snap to Glyph {glyphs}: {corner:?} vs {anchor:?}"); + // One dragged from up and to the left ends at its bottom-right corner. + let mut tool = SliceTool::default(); + tool.pointer(&c, &ev(PointerKind::Down, away)); + let acts = tool.pointer(&c, &ev(PointerKind::Drag, click)); + let Some(Action::Preview(_, v)) = acts.get(1) else { panic!("{acts:?}") }; + let f = |k: &str| v[k].as_f64().unwrap(); + let end = Point::new(f("x") + f("width"), f("y") + f("height")); + assert_eq!(end.distance(anchor) < 1e-6, glyphs, "slice end, Snap to Glyph {glyphs}: {end:?} vs {anchor:?}"); + } +} + /// Snap to Glyph: a single line of type has an x-height guide; a paragraph shows glyph bounds only. #[test] fn drawn_points_line_up_with_the_x_height_of_a_single_line() { diff --git a/crates/tools/src/slice.rs b/crates/tools/src/slice.rs index 0f804a8ef6..c4062123e8 100644 --- a/crates/tools/src/slice.rs +++ b/crates/tools/src/slice.rs @@ -14,7 +14,7 @@ use vectorcraft_doc::{NodeId, OrientedBox, SliceSource}; use vectorcraft_geom::{Affine, Point, Rect, Vec2}; use crate::bbox::{Handle, hit_handle, move_delta, scale_for_drag}; -use crate::guides::{PointSnap, Targets}; +use crate::guides::{DrawSnap, PointSnap, Targets}; use crate::shape::drag_rect; use crate::xform::{BLUE, polygon, rect_corners}; use crate::{Action, Cursor, Mods, Overlay, PointerEvent, PointerKind, Tool, ToolContext, ToolKey, json_ids}; @@ -37,9 +37,26 @@ fn has_area(r: Rect) -> bool { r.width() > 1e-6 && r.height() > 1e-6 } -/// Snap `p` as the drawing tools do, then to the nearest ruler guide within reach (guides win). -fn snap(cx: &ToolContext, p: Point) -> (Point, Vec) { - let (mut q, ov) = crate::guides::snap_draw(cx, p, &[]); +/// When the Slice tool snaps a point. +#[derive(Clone, Copy, PartialEq)] +enum Phase { + /// The pointer hovers before a press. + Hover, + /// The first corner is pressed: the targets are gathered afresh. + Press, + /// The other corner is dragged: the press's targets are kept. + Drag, +} + +/// Snap `p` as the drawing tools do ([`DrawSnap`]), then to the nearest ruler guide within reach +/// (guides win, and the Smart Guides are then not shown). +fn snap(draw: &mut DrawSnap, cx: &ToolContext, p: Point, phase: Phase) -> (Point, Vec) { + let mut q = match phase { + Phase::Hover => draw.hover(cx, p, &[], None), + Phase::Press => draw.press(cx, p, &[], None), + Phase::Drag => draw.drag(cx, p, None), + }; + let mut ov = draw.guides().to_vec(); let tol = cx.tol(5.0); let guides = cx.doc.ruler_guides(); let nearest = |vertical: bool, v: f64| { @@ -50,9 +67,11 @@ fn snap(cx: &ToolContext, p: Point) -> (Point, Vec) { }; if let Some(g) = nearest(true, p.x) { q.x = g.pos; + ov.clear(); } if let Some(g) = nearest(false, p.y) { q.y = g.pos; + ov.clear(); } (q, ov) } @@ -64,6 +83,8 @@ pub struct SliceTool { last: Point, began: bool, guides: Vec, + /// Smart Guides for the slice's corners, and for the pointer hovering before a press. + snap: DrawSnap, } impl Tool for SliceTool { @@ -77,14 +98,20 @@ impl Tool for SliceTool { fn pointer(&mut self, cx: &ToolContext, ev: &PointerEvent) -> Vec { match ev.kind { + PointerKind::Move => { + if self.start.is_none() { + self.guides = snap(&mut self.snap, cx, ev.pos, Phase::Hover).1; + } + vec![] + } PointerKind::Down => { - let (p, _) = snap(cx, ev.pos); - (self.start, self.last, self.began) = (Some(p), p, false); + let (p, guides) = snap(&mut self.snap, cx, ev.pos, Phase::Press); + (self.start, self.last, self.began, self.guides) = (Some(p), p, false, guides); vec![] } PointerKind::Drag => { let Some(start) = self.start else { return vec![] }; - let (p, guides) = snap(cx, ev.pos); + let (p, guides) = snap(&mut self.snap, cx, ev.pos, Phase::Drag); (self.last, self.guides) = (p, guides); let mut out = vec![]; if !self.began { @@ -102,6 +129,7 @@ impl Tool for SliceTool { } PointerKind::Up => { self.guides.clear(); + self.snap.clear(); let began = std::mem::take(&mut self.began); if self.start.take().is_some() && began { vec![Action::Commit] } else { vec![] } } @@ -123,6 +151,8 @@ impl Tool for SliceTool { } o } + // The hovering pointer's Smart Guides. + None => self.guides.clone(), _ => vec![], } } @@ -134,6 +164,7 @@ impl Tool for SliceTool { fn deactivate(&mut self, _cx: &ToolContext) -> Vec { self.start = None; self.guides.clear(); + self.snap.clear(); if std::mem::take(&mut self.began) { vec![Action::Cancel] } else { vec![] } } } @@ -152,8 +183,8 @@ impl Drag { } } -/// What a user slice's handle snaps to, gathered when it is pressed: what the Slice tool's drag -/// snaps to ([`snap`]), the art through [`PointSnap`] and the ruler guides on their own. +/// What a user slice's handle snaps to, gathered when it is pressed: the art's bounds through +/// [`PointSnap`], as a bounding-box handle snaps, and the ruler guides on their own. struct ResizeSnap { art: PointSnap, rulers: Targets, @@ -164,10 +195,10 @@ impl ResizeSnap { Self { art: PointSnap::scaling(cx, || Targets::collect(cx.doc, &[], None)), rulers: Targets::rulers(cx) } } - /// Snap the resize `a` ([`scale_for_drag`]) of the slice `rect` by `handle` as [`snap`] snaps - /// a drawn slice's corner: the handle snaps as a bounding-box handle does - /// ([`PointSnap::snap_scale`]), then a ruler guide within 5 px of where that leaves it takes - /// what the handle moves on its axis. Returns the scale and the guides showing why. + /// Snap the resize `a` ([`scale_for_drag`]) of the slice `rect` by `handle`: the handle snaps + /// as a bounding-box handle does ([`PointSnap::snap_scale`]), then a ruler guide within 5 px of + /// where that leaves it takes what the handle moves on its axis, as [`snap`] does for a drawn + /// slice's corner. Returns the scale and the guides showing why. fn scale(&self, cx: &ToolContext, rect: Rect, handle: Handle, a: Affine, m: Mods) -> (Affine, Vec) { let bx = OrientedBox::aligned(rect); let (a, ov) = self.art.snap_scale(cx, &bx, handle, a, m.shift, m.alt); diff --git a/crates/tools/src/text.rs b/crates/tools/src/text.rs index bd0c229ddf..763325f90e 100644 --- a/crates/tools/src/text.rs +++ b/crates/tools/src/text.rs @@ -134,7 +134,7 @@ fn text_hash(s: &str) -> u64 { h.finish() } -/// The edited text's layout, keyed by the font database's generation and the text. +/// The edited text's layout, keyed by [`vectorcraft_text::layout_inputs`] and the text. type CachedLayout = ((u64, TextObject), Arc); /// Process-global Type-tool edit-session counter: the IME target's replacement epoch. @@ -281,9 +281,9 @@ impl TypeTool { } /// Layout of `t`, cached by content (overlays run every frame) and by the fonts available (the - /// web build adds fonts after startup). + /// web build adds fonts after startup) and the hyphenation exceptions. fn layout(&self, t: &TextObject) -> Arc { - let fonts = FontDb::global().generation(); + let fonts = vectorcraft_text::layout_inputs(); let mut c = self.cache.lock().unwrap_or_else(|e| e.into_inner()); if let Some(((g, k), l)) = c.as_ref() && *g == fonts diff --git a/crates/tools/src/text/ports.rs b/crates/tools/src/text/ports.rs index 554a1cd611..6928fbe6f0 100644 --- a/crates/tools/src/text/ports.rs +++ b/crates/tools/src/text/ports.rs @@ -167,7 +167,8 @@ pub(crate) fn port_near(cx: &ToolContext, p: Point) -> Option<(NodeId, Port, f64 } /// Which selected text overflows, for [`thread_ports`]: each text object's layout verdict kept -/// with the object and the fonts it was made from, as overlays run every frame. +/// with the object and the layout inputs it was made with (fonts and hyphenation exceptions, +/// [`vectorcraft_text::layout_inputs`]), as overlays run every frame. #[derive(Default)] pub struct PortMarks { seen: std::collections::HashMap, @@ -178,7 +179,7 @@ pub struct PortMarks { /// port whether text is hidden by the size of its frame, whatever tool is active. None when more /// than [`PORTS_MAX`] of them are selected. pub fn thread_ports(marks: &mut PortMarks, cx: &ToolContext) -> Vec { - let fonts = FontDb::global().generation(); + let fonts = vectorcraft_text::layout_inputs(); let mut o = Vec::new(); let mut kept = std::collections::HashMap::new(); if !ports_shown(cx.doc, &cx.selection.objects) { diff --git a/crates/tools/src/text/tests.rs b/crates/tools/src/text/tests.rs index a7f302db65..94063166bc 100644 --- a/crates/tools/src/text/tests.rs +++ b/crates/tools/src/text/tests.rs @@ -1538,6 +1538,36 @@ fn selected_type_shows_its_ports_in_each_state() { assert!(thread_ports(&mut marks, &cx(&d, &sel, &p)).is_empty(), "only selected type shows them"); } +/// The out port shows whether the text fits as the hyphenation exceptions lay it out now: when +/// Preferences › Hyphenation › Exceptions change, the selected type is laid out again. +#[test] +fn the_out_port_follows_the_hyphenation_exceptions() { + struct Clear; + impl Drop for Clear { + fn drop(&mut self) { + vectorcraft_text::set_hyphenation_exceptions(""); + } + } + let _clear = Clear; + const WORDS: &str = "Extraordinarily comprehensive typographical considerations notwithstanding everything."; + const NEVER: &str = "extraordinarily, comprehensive, typographical, considerations, notwithstanding"; + let (mut d, id) = crate::testutil::doc_with_area_type(); + // A 70 by 170 pt frame holds the hyphenated text, and the text without those breaks overflows + // it. + let Some(NodeKind::Text(t)) = d.node_mut(id).map(|n| &mut n.kind) else { panic!("not text") }; + t.runs = vec![TextRun::new(WORDS, CharStyle { size: 14.0, ..Default::default() })]; + t.para.hyphenate = true; + t.kind = TextKind::Area { frame: vectorcraft_geom::PathData::from_bezpath(&Rect::new(0.0, 0.0, 70.0, 170.0).to_path(0.1)) }; + let (mut sel, p) = (Selection::default(), paint()); + sel.set([id]); + let mut marks = PortMarks::default(); + let red = |ov: &[Overlay]| ov.iter().filter(|o| matches!(o, Overlay::Path { color: [230, 30, 30], .. })).count(); + vectorcraft_text::set_hyphenation_exceptions(""); + assert_eq!(red(&thread_ports(&mut marks, &cx(&d, &sel, &p))), 0, "the hyphenated text fits"); + vectorcraft_text::set_hyphenation_exceptions(NEVER); + assert_eq!(red(&thread_ports(&mut marks, &cx(&d, &sel, &p))), 1, "the text without those breaks does not"); +} + /// Past [`PORTS_MAX`] selected frames (select all of an opened PDF) no ports are drawn or clicked: /// they would bury the canvas in boxes; up to it every frame has its two. #[test] diff --git a/crates/tools/src/touchtype.rs b/crates/tools/src/touchtype.rs index 172487c197..018a65aefc 100644 --- a/crates/tools/src/touchtype.rs +++ b/crates/tools/src/touchtype.rs @@ -99,7 +99,7 @@ struct Drag { began: bool, } -/// The type object's layout, keyed by the font database's generation and the object. +/// The type object's layout, keyed by [`vectorcraft_text::layout_inputs`] and the object. type CachedLayout = ((u64, TextObject), Arc); #[derive(Default)] @@ -196,9 +196,10 @@ fn char_box(t: &TextObject, lay: &TextLayout, gi: usize) -> Option { } impl TouchTypeTool { - /// Layout of `t`, cached by content (overlays run every frame) and by the fonts available. + /// Layout of `t`, cached by content (overlays run every frame), by the fonts available and by + /// the hyphenation exceptions. fn layout(&self, t: &TextObject) -> Arc { - let fonts = FontDb::global().generation(); + let fonts = vectorcraft_text::layout_inputs(); let mut c = self.cache.lock().unwrap_or_else(|e| e.into_inner()); if let Some(((g, k), l)) = c.as_ref() && *g == fonts diff --git a/crates/ui-egui/src/font_menu.rs b/crates/ui-egui/src/font_menu.rs index 554eb9229f..9b829114c2 100644 --- a/crates/ui-egui/src/font_menu.rs +++ b/crates/ui-egui/src/font_menu.rs @@ -1691,7 +1691,7 @@ pub(crate) fn end_stale_preview(app: &mut VectorcraftApp, ctx: &egui::Context) { } /// What the font menus preview on and apply to: the Type tool's selected range while it edits -/// text (the whole text when nothing is selected), else the selected text objects. +/// text (the whole text when nothing is selected), else every frame of each selected story. pub(crate) fn apply(app: &mut VectorcraftApp, ctx: &egui::Context, pick: FontPick) { let previewing = crate::panels::pstate::(ctx, PREVIEWING); match pick { @@ -1791,7 +1791,11 @@ fn font_command(app: &VectorcraftApp, family: &str, style: Option<&str>) -> (&'s } ("text.setRangeStyle", p) } - None => ("text.setStyle", p), + None => { + // With the Selection tool: every frame of each selected story. + crate::panels::character::target_selected_stories(app, &mut p); + ("text.setStyle", p) + } } } diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 7178be3143..ce0e6cde2d 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -7492,3 +7492,1816 @@ breakText Glyphs Glyfy Grommets Průchodky Grommet Inset Odstup průchodek od okraje Diameter Průměr +@msg 'caller', 'callee' and 'arguments' cannot be used on strict mode functions 'caller', 'callee' a 'arguments' nelze použít u funkcí ve striktním režimu +@msg A profile supports one Revolve effect. Edit the existing effect's options instead. Profil podporuje jeden efekt Rotační těleso. Upravte místo toho volby stávajícího efektu. +@msg Add Points at Crossings: a path went missing Přidat body v křížení: jedna cesta se ztratila +@msg Alignment must be one of the choices Zarovnání musí být jedna z nabízených voleb +@msg Boolean.prototype.{name} was called on a value that is not a Boolean Boolean.prototype.{name} byla zavolána na hodnotě, která není Boolean +@msg CMYK images whose samples couldn't be read in CMYK were imported in RGB Obrazy CMYK, jejichž vzorky nešlo přečíst v CMYK, byly importovány v RGB +@msg CSS options: {e} Volby CSS: {e} +@msg CSV has a header but no data rows CSV má záhlaví, ale žádné řádky dat +@msg CSV holds NUL bytes: save it as UTF-8, or as UTF-16 with a byte-order mark CSV obsahuje bajty NUL: uložte ho jako UTF-8, nebo jako UTF-16 se značkou pořadí bajtů +@msg CSV is empty CSV je prázdné +@msg CSV is larger than {MAX_CSV_BYTES} bytes CSV je větší než {MAX_CSV_BYTES} bajtů +@msg CSV is not UTF-16 CSV není v UTF-16 +@msg CSV is not UTF-8 CSV není v UTF-8 +@msg CSV would be larger than {MAX_CSV_BYTES} bytes CSV by bylo větší než {MAX_CSV_BYTES} bajtů +@msg Cannot write to the location of “{name}”; choose where to save it Do umístění souboru „{name}“ nelze zapisovat; zvolte, kam ho uložit +@msg Choose original artwork, not a dimension's generated paths Zvolte původní kresbu, ne cesty vytvořené kótou +@msg Contour: select paths or shapes Obrys: vyberte cesty nebo tvary +@msg Contour: the Offset Path effect is not available Obrys: efekt Odsadit cestu není dostupný +@msg Create needs fills, strokes or both Vytvořit vyžaduje výplně, tahy nebo obojí +@msg DCS files can only be placed linked: use File › Place with Link on Soubory DCS lze umístit jen jako propojené: použijte Soubor › Umístit se zapnutou volbou Propojení +@msg DXF options: {e} Volby DXF: {e} +@msg DXF scale must be a positive number up to {_1}, not {scale} Měřítko DXF musí být kladné číslo nejvýše {_1}, ne {scale} +@msg DXF {field} `{s}`: {allowed} DXF {field} `{s}`: {allowed} +@msg Date.prototype method called on a value that is not a Date object Metoda Date.prototype byla zavolána na hodnotě, která není objekt Date +@msg Dimension is locked or hidden Kóta je zamknutá nebo skrytá +@msg Dimension mode does not match its source Režim kóty neodpovídá jejímu zdroji +@msg Draw Inside needs exactly one selected path, compound path or text Kreslit dovnitř vyžaduje právě jednu vybranou cestu, složenou cestu nebo text +@msg EPS Save writes all artwork: use document.export for selected-only EPS Uložení EPS zapisuje celou kresbu: pro EPS jen z výběru použijte document.export +@msg EPS flattener: {e} Sloučení průhlednosti EPS: {e} +@msg EPS options: {e} Volby EPS: {e} +@msg EPS {field} `{s}`: {allowed} EPS {field} `{s}`: {allowed} +@msg Error.prototype.toString was called on a value that is not an object Error.prototype.toString byla zavolána na hodnotě, která není objekt +@msg Export for Screens writes png, png8, jpg, webp, gif, tiff, bmp, tga, psd, svg, svgz, pdf, eps, ai or vectorcraft Exportovat pro obrazovky zapisuje png, png8, jpg, webp, gif, tiff, bmp, tga, psd, svg, svgz, pdf, eps, ai nebo vectorcraft +@msg Flare click coordinates must be finite numbers Souřadnice kliknutí pro Odlesk musí být konečná čísla +@msg Function.prototype.toString was called on a value that is not a function Function.prototype.toString byla zavolána na hodnotě, která není funkce +@msg HTML Text applies to object slices of type only Text HTML se týká jen řezů objektů s textem +@msg Identify Objects By is XML ID: the name must be a valid XML ID (start with a letter, underscore or colon; no spaces) Identifikovat objekty podle je nastaveno na XML ID: název musí být platné XML ID (začíná písmenem, podtržítkem nebo dvojtečkou; bez mezer) +@msg Image Trace failed: internal error: its thread stopped (please report this bug) Vektorizace obrazu selhala: vnitřní chyba: její vlákno se zastavilo (nahlaste prosím tuto chybu) +@msg Image Trace failed: {e} Vektorizace obrazu selhala: {e} +@msg Image Trace finished, but its document was closed Vektorizace obrazu skončila, ale její dokument byl zavřen +@msg Image Trace finished, but the image or its settings changed meanwhile: trace it again Vektorizace obrazu skončila, ale obraz nebo jeho nastavení se mezitím změnily: vektorizujte ho znovu +@msg Import SVG Filter reads SVG files, not SVGZ Importovat filtr SVG čte soubory SVG, ne SVGZ +@msg Invalid dimension offset Neplatné odsazení kóty +@msg Invalid point Neplatný bod +@msg JSON.parse: {why} (at offset {at}) JSON.parse: {why} (na pozici {at}) +@msg JSON.stringify cannot write a structure that contains itself JSON.stringify nemůže zapsat strukturu, která obsahuje sama sebe +@msg Join: a subpath went missing Spojit: jedna dílčí cesta se ztratila +@msg Line Gap must be a number Mezera řádků musí být číslo +@msg Lock Workspace is not available in VectorCraft Zamknout pracovní prostor není ve VectorCraft dostupné +@msg Move Panel to New Window is not available: floating panels stay in the main window Přesunout panel do nového okna není dostupné: plovoucí panely zůstávají v hlavním okně +@msg Namespace.prototype.toString needs a Namespace Namespace.prototype.toString vyžaduje Namespace +@msg New Document profiles need the preferences folder, which this run doesn't have Profily nového dokumentu vyžadují složku předvoleb, kterou toto spuštění nemá +@msg Number.prototype.{name} was called on a value that is not a number Number.prototype.{name} byla zavolána na hodnotě, která není číslo +@msg Object.create's prototype must be an object or null Prototyp pro Object.create musí být objekt nebo null +@msg Object.{function} was given a value that is not an object Object.{function} dostala hodnotu, která není objekt +@msg Offset Path: the path is too complex to offset Odsadit cestu: cesta je příliš složitá na odsazení +@msg Offset Path: {e} Odsadit cestu: {e} +@msg PDF content is incomplete or exceeds the reader's limits; no document was imported Obsah PDF je neúplný nebo překračuje limity čtení; žádný dokument nebyl importován +@msg PDF flattener: {e} Sloučení průhlednosti PDF: {e} +@msg PDF options: {e} Volby PDF: {e} +@msg QName.prototype.toString needs a QName QName.prototype.toString vyžaduje QName +@msg Recolor Artwork is no longer open Přebarvit kresbu už není otevřené +@msg RegExp.prototype.{name} was called on a value that is not a RegExp object RegExp.prototype.{name} byla zavolána na hodnotě, která není objekt RegExp +@msg SVG is not UTF-8, UTF-16 or ISO 8859-1 SVG není v UTF-8, UTF-16 ani ISO 8859-1 +@msg Save writes one artboard: name one, or export several with document.export Uložit zapisuje jednu pracovní plochu: uveďte jednu, nebo jich několik exportujte pomocí document.export +@msg Select a dimension first Nejprve vyberte kótu +@msg Select dimensions to update Vyberte kóty k aktualizaci +@msg Select only dimensions Vyberte jen kóty +@msg Select two or more objects, or a group Vyberte dva nebo více objektů, nebo skupinu +@msg Shaper needs 1–64 source paths Shaper vyžaduje 1–64 zdrojových cest +@msg Stencil Bridges: the selected art is too large or too detailed to bridge Můstky šablony: vybraná kresba je příliš velká nebo příliš podrobná na přemostění +@msg String.prototype.toString was called on a value that is not a string String.prototype.toString byla zavolána na hodnotě, která není řetězec +@msg Switch x/y is for scatter graphs Prohodit x/y je určeno pro bodové grafy +@msg Text options: {e} Volby textu: {e} +@msg The {name} profile could not be read, so the new document has the default settings: {reason} Profil {name} nešlo přečíst, takže nový dokument má výchozí nastavení: {reason} +@msg Trap: more than {_1} pairs of objects lie close enough to trap, or too many objects share a horizontal range; trap fewer objects at a time Přesah barev: více než {_1} dvojic objektů leží dost blízko pro přesah, nebo příliš mnoho objektů sdílí vodorovný rozsah; zpracujte najednou méně objektů +@msg Weed Box and Lines: no weeding line fits outside the art, and the weed box is off Rámeček a linie pro vybírání: mimo kresbu se nevejde žádná linie pro vybírání a rámeček je vypnutý +@msg \ at end of pattern \ na konci vzoru +@msg `alignOn` cannot be empty `alignOn` nesmí být prázdné +@msg `alignOn` must be a string `alignOn` musí být řetězec +@msg `align` is start, center or end `align` je start, center nebo end +@msg `align` must be a string `align` musí být řetězec +@msg `anchors` must be an array of [subpath, anchor] pairs `anchors` musí být pole dvojic [dílčí cesta, kotevní bod] +@msg `anchors` must list anchor indices (0, 1, 2…), not {k} `anchors` musí uvádět indexy kotevních bodů (0, 1, 2…), ne {k} +@msg `anchors` must list anchor indices (0, 1, 2…), not {v} `anchors` musí uvádět indexy kotevních bodů (0, 1, 2…), ne {v} +@msg `answer` for this {kind} dialog must be one of: {_1} `answer` pro tento dialog {kind} musí být jedna z hodnot: {_1} +@msg `answers` has more than {MAX_ANSWERS} answers `answers` má více než {MAX_ANSWERS} odpovědí +@msg `answers` is larger than 1 MiB `answers` je větší než 1 MiB +@msg `answers` must be a list of answers `answers` musí být seznam odpovědí +@msg `artboard` must be the index of an artboard of the document `artboard` musí být index pracovní plochy dokumentu +@msg `artboardsAt` must be [x, y] `artboardsAt` musí být [x, y] +@msg `artboards` must be a list of artboard indices `artboards` musí být seznam indexů pracovních ploch +@msg `artboards` names an artboard the document does not have `artboards` uvádí pracovní plochu, kterou dokument nemá +@msg `artboards` names an artboard twice `artboards` uvádí některou pracovní plochu dvakrát +@msg `asset` is the asset id (see assets.list) `asset` je ID prvku (viz assets.list) +@msg `at` must be [x, y] (got {at}) `at` musí být [x, y] (zadáno {at}) +@msg `at` must be a byte offset `at` musí být bajtový posun +@msg `at` must be a point [x, y] `at` musí být bod [x, y] +@msg `autoLeading` must be a number `autoLeading` musí být číslo +@msg `background` must be "", "matte" or #rrggbb `background` musí být "", "matte" nebo #rrggbb +@msg `beside` needs `side` `beside` vyžaduje `side` +@msg `burasagari` must be "none", "standard" or "forced" `burasagari` musí být "none", "standard" nebo "forced" +@msg `center` must be [x, y] `center` musí být [x, y] +@msg `charAlign` must be "romanBaseline", "emBoxTop", "emBoxCenter", "emBoxBottom", "icfTop" or "icfBottom" `charAlign` musí být "romanBaseline", "emBoxTop", "emBoxCenter", "emBoxBottom", "icfTop" nebo "icfBottom" +@msg `charDirection` must be "default", "leftToRight" or "rightToLeft" `charDirection` musí být "default", "leftToRight" nebo "rightToLeft" +@msg `clearStroke` requires `stroke: false`, `ids: []` and no `stop` `clearStroke` vyžaduje `stroke: false`, `ids: []` a žádné `stop` +@msg `clear` must be a list of type object ids, not {v} `clear` musí být seznam ID textových objektů, ne {v} +@msg `clear` must list type objects; {_1} is not one `clear` musí uvádět textové objekty; {_1} jím není +@msg `clear` must not list `id` `clear` nesmí uvádět `id` +@msg `code` must be a whole number `code` musí být celé číslo +@msg `colorMode` must be one of rgb, cmyk `colorMode` musí být jedna z hodnot rgb, cmyk +@msg `color` needs a `rule` to make the theme from `color` vyžaduje `rule`, podle kterého se motiv vytvoří +@msg `colors` does not apply to the {name} reduction `colors` se netýká redukce {name} +@msg `colors` is empty `colors` je prázdné +@msg `colors` must be a whole number from 2 to 256 `colors` musí být celé číslo od 2 do 256 +@msg `colors` must be at least 9 for the uniform reduction `colors` musí být pro rovnoměrnou redukci nejméně 9 +@msg `colors` must be between 1 and {MAX_THEME_COLORS} (got {n}) `colors` musí být mezi 1 a {MAX_THEME_COLORS} (zadáno {n}) +@msg `columnType` is vertical, uniform, repeating or sliding `columnType` je vertical, uniform, repeating nebo sliding +@msg `columns` must be a whole number 1..50 `columns` musí být celé číslo 1..50 +@msg `commands` must not be empty `commands` nesmí být prázdné +@msg `contents` goes with `to` `contents` patří k `to` +@msg `corners` must be sharp, round or square, not `{other}` `corners` musí být sharp, round nebo square, ne `{other}` +@msg `corners` must list anchor indices (0, 1, 2…), not {v} `corners` musí uvádět indexy kotevních bodů (0, 1, 2…), ne {v} +@msg `count` must be a whole number from 0 to {MAX_COUNT} `count` musí být celé číslo od 0 do {MAX_COUNT} +@msg `count` must be a whole number from 1 to 100 `count` musí být celé číslo od 1 do 100 +@msg `dataBase64` is larger than the module limit `dataBase64` je větší než limit modulu +@msg `dataBase64` is not valid base64 `dataBase64` není platný base64 +@msg `defaultsOnly` cannot be combined with `ids`, `reverse` or `append` `defaultsOnly` nelze kombinovat s `ids`, `reverse` ani `append` +@msg `depth` and `childLimit` slice the summary: pass `summary: true` `depth` a `childLimit` omezují souhrn: předejte `summary: true` +@msg `design` is a design name, or null for plain columns `design` je název návrhu, nebo null pro obyčejné sloupce +@msg `design` is a design name, or null for the default marker `design` je název návrhu, nebo null pro výchozí značku +@msg `destinationFolder` is required when destination is `folder` `destinationFolder` je povinné, když je cíl `folder` +@msg `destination` must be `none`, `saveAndClose` or `folder` `destination` musí být `none`, `saveAndClose` nebo `folder` +@msg `diameter` must be from 0.1 to 2500 pt `diameter` musí být od 0.1 do 2500 pt +@msg `digits` must be one of {_1} `digits` musí být jedna z hodnot {_1} +@msg `dimImages` is a percentage or false `dimImages` je procento nebo false +@msg `direction` must be "auto", "leftToRight" or "rightToLeft" `direction` musí být "auto", "leftToRight" nebo "rightToLeft" +@msg `ditherAmount` must be a number from 0 to 100 `ditherAmount` musí být číslo od 0 do 100 +@msg `each` is the value one design stands for, more than 0 `each` je hodnota, kterou představuje jeden návrh, větší než 0 +@msg `end` must be "start" or "end" `end` musí být "start" nebo "end" +@msg `ends` applies to joining exactly two paths `ends` se týká spojení právě dvou cest +@msg `event` must be one of {_1} `event` musí být jedna z hodnot {_1} +@msg `every` must be "all", "odd" or "even", not {v} `every` musí být "all", "odd" nebo "even", ne {v} +@msg `expand` must be true or false `expand` musí být true nebo false +@msg `fidelity` must be from {lo} to {hi} pt `fidelity` musí být od {lo} do {hi} pt +@msg `files` must be 1 to 1000 paths of font files the last text.findFontFiles search found `files` musí být 1 až 1000 cest k souborům písem, které našlo poslední hledání text.findFontFiles +@msg `focal` and `radius` cannot be used together `focal` a `radius` nelze použít společně +@msg `focal` must be an array of [subpath, anchor] pairs `focal` musí být pole dvojic [dílčí cesta, kotevní bod] +@msg `focal` names [{si}, {ai}], which is not an anchor of the path `focal` uvádí [{si}, {ai}], což není kotevní bod cesty +@msg `folder` must be an absolute folder path `folder` musí být absolutní cesta ke složce +@msg `fontAxes` must be an object of axis tags and values, such as {"wght"} `fontAxes` musí být objekt se značkami os a hodnotami, například {"wght"} +@msg `format` must be a string `format` musí být řetězec +@msg `format` must be one of {_1} `format` musí být jedna z hodnot {_1} +@msg `fractions` is chop or scale `fractions` je chop nebo scale +@msg `from` and `to` must differ `from` a `to` se musí lišit +@msg `from` has an empty frame `from` má prázdný rámec +@msg `from` must be a non-negative integer `from` musí být nezáporné celé číslo +@msg `from` must be area type or type on a path `from` musí být text v oblasti nebo text na cestě +@msg `gid` must be a glyph id, not {v} `gid` musí být ID glyfu, ne {v} +@msg `glyphAlternate` belongs to one character, not to a character style (text.setGlyphAlternate sets it) `glyphAlternate` patří jednomu znaku, ne stylu znaků (nastavuje ho text.setGlyphAlternate) +@msg `glyphAlternate` takes only null, which takes a glyph choice away (text.setGlyphAlternate makes one) `glyphAlternate` přijímá jen null, které volbu glyfu odebere (volbu nastavuje text.setGlyphAlternate) +@msg `group` must be one of {_1} `group` musí být jedna z hodnot {_1} +@msg `group` must be the Objects on Path group of `member` and `target` `group` musí být skupina Objekty na cestě, do které patří `member` a `target` +@msg `guide` must be a guide index (guide.list) `guide` musí být index vodítka (guide.list) +@msg `hAlign` must be default, left, center or right `hAlign` musí být default, left, center nebo right +@msg `id` is an object id, not {v} `id` je ID objektu, ne {v} +@msg `id` must be a node id `id` musí být ID uzlu +@msg `id` must be an object id, not {v} `id` musí být ID objektu, ne {v} +@msg `ids` must name Objects on Path groups or objects in them `ids` musí uvádět skupiny Objekty na cestě nebo objekty v nich +@msg `ids` takes at most {MAX_INSPECT_IDS} ids `ids` přijímá nejvýše {MAX_INSPECT_IDS} ID +@msg `imageMap` must be none, rectangle or polygon `imageMap` musí být none, rectangle nebo polygon +@msg `includeArtboardFill` must be true or false `includeArtboardFill` musí být true nebo false +@msg `includeSubdirs` must be true or false `includeSubdirs` musí být true nebo false +@msg `index` must be a point index `index` musí být index bodu +@msg `index` must be a whole number or null `index` musí být celé číslo nebo null +@msg `indices` must be a non-empty array of item indices `indices` musí být neprázdné pole indexů položek +@msg `item` needs `index` `item` vyžaduje `index` +@msg `items` is a list of {kind, item} `items` je seznam {kind, item} +@msg `items` is empty `items` je prázdné +@msg `items` must be a list of {id, points} `items` musí být seznam {id, points} +@msg `items` must be a list of {{id, anchors?}}, not {v} `items` musí být seznam {{id, anchors?}}, ne {v} +@msg `items` must be an array of {id, anchors} `items` musí být pole {id, anchors} +@msg `items` must be an array of {{id, corners?}}, not {v} `items` musí být pole {{id, corners?}}, ne {v} +@msg `kashida` must be "none", "short", "medium", "long" or "stylistic" `kashida` musí být "none", "short", "medium", "long" nebo "stylistic" +@msg `kerningBefore` belongs to a line's first character, not to a character style (text.setRangeStyle sets it) `kerningBefore` patří prvnímu znaku řádku, ne stylu znaků (nastavuje ho text.setRangeStyle) +@msg `kind` is one of {_1} `kind` je jedna z hodnot {_1} +@msg `kind` must be "round", "invertedRound" or "chamfer", not {v} `kind` musí být "round", "invertedRound" nebo "chamfer", ne {v} +@msg `kind` must be `text`, `visibility`, `image` or `graph` `kind` musí být `text`, `visibility`, `image` nebo `graph` +@msg `kind` must be a string `kind` musí být řetězec +@msg `kind` must be image, noImage or htmlText `kind` musí být image, noImage nebo htmlText +@msg `kinsokuType` must be "pushInFirst", "pushOutFirst" or "pushOutOnly" `kinsokuType` musí být "pushInFirst", "pushOutFirst" nebo "pushOutOnly" +@msg `kinsoku` must be "none", "hard" or "soft" `kinsoku` musí být "none", "hard" nebo "soft" +@msg `label` must be a non-empty name of at most 200 characters `label` musí být neprázdný název o nejvýše 200 znacích +@msg `language` must be a language name or tag, such as "Turkish" or "tr" `language` musí být název nebo značka jazyka, například "Turkish" nebo "tr" +@msg `leader` must be a string `leader` musí být řetězec +@msg `leadingModel` must be "romanBaseline" or "emBoxTop" `leadingModel` musí být "romanBaseline" nebo "emBoxTop" +@msg `leading` must be from 0.1 to 5000, or null for Auto `leading` musí být od 0.1 do 5000, nebo null pro Automaticky +@msg `length` must be a number of at most 1000000 pt either way `length` musí být číslo nejvýše 1000000 pt v obou směrech +@msg `line` must be true or false `line` musí být true nebo false +@msg `max` must be 1 to {MAX_SUGGESTIONS} `max` musí být 1 až {MAX_SUGGESTIONS} +@msg `minAngle` ({min_angle}°) can't be more than `maxAngle` ({max_angle}°) `minAngle` ({min_angle}°) nemůže být větší než `maxAngle` ({max_angle}°) +@msg `mode` must be "handles", "straight" or "smooth" `mode` musí být "handles", "straight" nebo "smooth" +@msg `mode` must be "straight", "bezier" or "arc" `mode` musí být "straight", "bezier" nebo "arc" +@msg `mode` must be one of {_1} `mode` musí být jedna z hodnot {_1} +@msg `mojikumi` must be "none", "yakumonoHankaku", "gyomatsuYakumonoHankaku", "gyomatsuYakumonoZenkaku", "yakumonoZenkaku" or "lineEndHalf" `mojikumi` musí být "none", "yakumonoHankaku", "gyomatsuYakumonoHankaku", "gyomatsuYakumonoZenkaku", "yakumonoZenkaku" nebo "lineEndHalf" +@msg `name` must be a name that is not empty `name` musí být název, který není prázdný +@msg `name` must not be empty `name` nesmí být prázdné +@msg `names` is a list of preset names `names` je seznam názvů přednastavení +@msg `names` lists preset names `names` uvádí názvy přednastavení +@msg `names` must be a list of names `names` musí být seznam názvů +@msg `names` must be a list of swatch names `names` musí být seznam názvů položek vzorníku +@msg `names` must be an array of style names `names` musí být pole názvů stylů +@msg `new` is a design name, or true `new` je název návrhu, nebo true +@msg `origin` must be [x, y] in points `origin` musí být [x, y] v bodech +@msg `path` must be a folder `path` musí být složka +@msg `path` must be a path object `path` musí být objekt cesty +@msg `picks` must be an array (got {v}) `picks` musí být pole (zadáno {v}) +@msg `picks` must hold 1 to {MAX_PICKS} picks (got {_1}) `picks` musí obsahovat 1 až {MAX_PICKS} voleb (zadáno {_1}) +@msg `pivot` must be a whole number from 0 to 8 `pivot` musí být celé číslo od 0 do 8 +@msg `points` must be a list of [x, y] points `points` musí být seznam bodů [x, y] +@msg `points` must be a list of point indexes `points` musí být seznam indexů bodů +@msg `points` must be an array of point indices `points` musí být pole indexů bodů +@msg `points` must be point indexes `points` musí být indexy bodů +@msg `points` must hold from 2 to 100000 points `points` musí obsahovat 2 až 100000 bodů +@msg `port` must be "in" or "out" `port` musí být "in" nebo "out" +@msg `position` is above or below `position` je above nebo below +@msg `preset` must be a string `preset` musí být řetězec +@msg `radius` must be 0 or more `radius` musí být 0 nebo více +@msg `ratio` must be from 0.1 to 0.5 `ratio` musí být od 0.1 do 0.5 +@msg `rect` must be [x, y, width, height] `rect` musí být [x, y, width, height] +@msg `rect` must be [x, y, width, height] with a positive size `rect` musí být [x, y, width, height] s kladnou velikostí +@msg `rect` must be [x0, y0, x1, y1] (got {r}) `rect` musí být [x0, y0, x1, y1] (zadáno {r}) +@msg `relation` must be overlap, inside or outside `relation` musí být overlap, inside nebo outside +@msg `replace` must be a string `replace` musí být řetězec +@msg `reversed` must be true or false `reversed` musí být true nebo false +@msg `rotate` must be a finite number `rotate` musí být konečné číslo +@msg `rows` must be lists of numbers or nulls, not {r} `rows` musí být seznamy čísel nebo hodnot null, ne {r} +@msg `rule` must be nonZero or evenOdd `rule` musí být nonZero nebo evenOdd +@msg `scale` must be a number from 0.001 to 1000 `scale` musí být číslo od 0.001 do 1000 +@msg `scale` must be a number in (0, 100] `scale` musí být číslo v rozsahu (0, 100] +@msg `scope.{key}` must be a non-empty array `scope.{key}` musí být neprázdné pole +@msg `scope` must be "document", {artboards} or {layers} `scope` musí být "document", {artboards} nebo {layers} +@msg `scope` must be "selection" or "document", not {other} `scope` musí být "selection" nebo "document", ne {other} +@msg `script` must be a string `script` musí být řetězec +@msg `seriesIndexes` is a non-empty list of series indexes `seriesIndexes` je neprázdný seznam indexů řad +@msg `seriesIndexes` needs a `type` or a `valueAxis` `seriesIndexes` vyžaduje `type` nebo `valueAxis` +@msg `shift` must be a number of points `shift` musí být počet bodů +@msg `showCenter` must be true or false `showCenter` musí být true nebo false +@msg `side` must be "left", "right", "top" or "bottom" `side` musí být "left", "right", "top" nebo "bottom" +@msg `side` places the artboard: leave out x, y, width and height `side` umísťuje pracovní plochu: vynechte x, y, width a height +@msg `singleWordJustification` must be "fullJustify", "alignLeft", "alignCenter" or "alignRight" `singleWordJustification` musí být "fullJustify", "alignLeft", "alignCenter" nebo "alignRight" +@msg `size` is a percentage of the base text's size, 1 to 100 `size` je procento velikosti základního textu, 1 až 100 +@msg `source` and `target` are the same object `source` a `target` jsou tentýž objekt +@msg `source` is the only path in series group `target` `source` je jediná cesta ve skupině řady `target` +@msg `source` must be `folder` or `datasets` `source` musí být `folder` nebo `datasets` +@msg `spacing` makes more than {MAX_COUNT} lines across the box `spacing` vytvoří napříč rámečkem více než {MAX_COUNT} linií +@msg `spacing` must be a number `spacing` musí být číslo +@msg `spacing` must be a number of points, 0 or more, or "auto" `spacing` musí být počet bodů, 0 nebo více, nebo "auto" +@msg `spacing` must be more than 0 and at most {MAX_DISTANCE} pt `spacing` musí být více než 0 a nejvýše {MAX_DISTANCE} pt +@msg `start` must be a finite number `start` musí být konečné číslo +@msg `starts` must be an array of anchor indices (or nulls) `starts` musí být pole indexů kotevních bodů (nebo hodnot null) +@msg `status` must be linked, embedded, missing or modified, or a list of them `status` musí být linked, embedded, missing nebo modified, nebo jejich seznam +@msg `stop` must be a stop index `stop` musí být index zarážky +@msg `story` styles the whole story: give no `start` or `end` `story` nastavuje styl celého článku: nezadávejte `start` ani `end` +@msg `story` takes the whole story: give no `start` or `end` `story` zahrnuje celý článek: nezadávejte `start` ani `end` +@msg `strokeMode` applies to strokes (stroke: true) `strokeMode` platí pro tahy (stroke: true) +@msg `style` must be roman or japanese `style` musí být roman nebo japanese +@msg `subpaths` must be two integer indices `subpaths` musí být dva celočíselné indexy +@msg `symbol` must be a symbol name `symbol` musí být název symbolu +@msg `target` must be "object" or "contents", not {v} `target` musí být "object" nebo "contents", ne {v} +@msg `target` must be an object of the same Objects on Path group as `member` `target` musí být objekt ze stejné skupiny Objekty na cestě jako `member` +@msg `tint` applies to global and spot colours `tint` platí pro globální a přímé barvy +@msg `tint` goes with a global or spot `swatch` `tint` patří ke globální nebo přímé barvě v `swatch` +@msg `tint` must be a number (%) `tint` musí být číslo (%) +@msg `tint` needs a global or spot colour `tint` vyžaduje globální nebo přímou barvu +@msg `to` is already threaded `to` je už zřetězené +@msg `to` is the design's new name `to` je nový název návrhu +@msg `to` must be [x, y] `to` musí být [x, y] +@msg `to` must be a closed path, area type or type on a path other than `from` `to` musí být uzavřená cesta, text v oblasti nebo text na cestě jiný než `from` +@msg `to` must be a whole number `to` musí být celé číslo +@msg `to` takes the rows of one object's stack, not aligned rows `to` přijímá řádky zásobníku jednoho objektu, ne zarovnané řádky +@msg `tolerance` must be from 0 to 100 pt `tolerance` musí být od 0 do 100 pt +@msg `useLab` must be true or false `useLab` musí být true nebo false +@msg `vAlign` must be default, top, middle, baseline or bottom `vAlign` musí být default, top, middle, baseline nebo bottom +@msg `values` must be a list `values` musí být seznam +@msg `values` must be an object `values` musí být objekt +@msg `values` must name hex, rgb, cmyk, lab or gray `values` musí uvádět hex, rgb, cmyk, lab nebo gray +@msg `values` names a kind twice `values` uvádí některý druh dvakrát +@msg `version` must be 0 or {_1} `version` musí být 0 nebo {_1} +@msg `version` must be 0 or {newest} `version` musí být 0 nebo {newest} +@msg `warichuAlign` must be one of {_1} `warichuAlign` musí být jedna z hodnot {_1} +@msg `warichuLines` must be a whole number from {_1} to {_2} `warichuLines` musí být celé číslo od {_1} do {_2} +@msg `weight` must be from 0.01 to 1000 pt `weight` musí být od 0.01 do 1000 pt +@msg `weights` must be a list of {_1} numbers, one per row (got {v}) `weights` musí být seznam {_1} čísel, jedno na řádek (zadáno {v}) +@msg `xml` must be a string `xml` musí být řetězec +@msg `{KEY}` entry {n} gives the paragraph at byte {start} of {_1} other indents than an entry before it položka {n} v `{KEY}` dává odstavci na bajtu {start} objektu {_1} jiná odsazení než některá položka před ní +@msg `{KEY}` entry {n} must be an object položka {n} v `{KEY}` musí být objekt +@msg `{KEY}` entry {n} sets neither `leftIndent` nor `firstLineIndent` položka {n} v `{KEY}` nenastavuje `leftIndent` ani `firstLineIndent` +@msg `{KEY}` entry {n}: `id` must be an object id položka {n} v `{KEY}`: `id` musí být ID objektu +@msg `{KEY}` entry {n}: `start` must be a byte offset položka {n} v `{KEY}`: `start` musí být bajtový posun +@msg `{KEY}` entry {n}: `{k}` must be a number from -{MAX_PARA} to {MAX_PARA} pt položka {n} v `{KEY}`: `{k}` musí být číslo od -{MAX_PARA} do {MAX_PARA} pt +@msg `{KEY}` entry {n}: no paragraph of {_1} starts at byte {start} položka {n} v `{KEY}`: žádný odstavec objektu {_1} nezačíná na bajtu {start} +@msg `{KEY}` entry {n}: unknown key `{k}` položka {n} v `{KEY}`: neznámý klíč `{k}` +@msg `{KEY}` entry {n}: {_1} is not a type object položka {n} v `{KEY}`: {_1} není textový objekt +@msg `{KEY}` is empty `{KEY}` je prázdné +@msg `{KEY}` must be a list `{KEY}` musí být seznam +@msg `{KEY}` takes at most {MAX_PARAGRAPH_INDENTS} entries (got {_1}) `{KEY}` přijímá nejvýše {MAX_PARAGRAPH_INDENTS} položek (zadáno {_1}) +@msg `{KEY}` takes no `{other}` beside it `{KEY}` vedle sebe nepřijímá `{other}` +@msg `{_1}` can't be edited or removed `{_1}` nelze upravit ani odebrat +@msg `{_1}` is built in and always listed `{_1}` je vestavěné a je uvedeno vždy +@msg `{_1}` is not a font file the last text.findFontFiles search found `{_1}` není soubor písma, který našlo poslední hledání text.findFontFiles +@msg `{_1}` would be overwritten by the package: choose a different folder or name `{_1}` by balíček přepsal: zvolte jinou složku nebo název +@msg `{base}` is larger than {_1} MB `{base}` je větší než {_1} MB +@msg `{base}` is not in the DCS file's folder `{base}` není ve složce souboru DCS +@msg `{file}` has no art to place `{file}` nemá žádnou kresbu k umístění +@msg `{file}` is over {_1} MB `{file}` má více než {_1} MB +@msg `{f}` belongs to a VectorCraft that is running `{f}` patří běžící aplikaci VectorCraft +@msg `{f}` is the copy of a document open now `{f}` je kopie právě otevřeného dokumentu +@msg `{id}` is no writable format (see document.formats) `{id}` není formát, který lze zapisovat (viz document.formats) +@msg `{id}` isn't a loaded library `{id}` není načtená knihovna +@msg `{key}` has no colours `{key}` neobsahuje žádné barvy +@msg `{key}` holds more than {MAX_EDIT_WORDS} words `{key}` obsahuje více než {MAX_EDIT_WORDS} slov +@msg `{key}` is a design name `{key}` je název návrhu +@msg `{key}` is a design name or a list of them `{key}` je název návrhu nebo jejich seznam +@msg `{key}` is longer than {MAX_NAME} characters `{key}` je delší než {MAX_NAME} znaků +@msg `{key}` is out of range `{key}` je mimo rozsah +@msg `{key}` must be 0 or more `{key}` musí být 0 nebo více +@msg `{key}` must be [min, desired, max] or {{min?, desired?, max?}}, in percent `{key}` musí být [min, desired, max] nebo {{min?, desired?, max?}}, v procentech +@msg `{key}` must be [x, y] numbers `{key}` musí být čísla [x, y] +@msg `{key}` must be a list of words `{key}` musí být seznam slov +@msg `{key}` must be a list, not {v} `{key}` musí být seznam, ne {v} +@msg `{key}` must be a non-negative integer `{key}` musí být nezáporné celé číslo +@msg `{key}` must be a number or null, not {v} `{key}` musí být číslo nebo null, ne {v} +@msg `{key}` must be a number {_1}..{_2} `{key}` musí být číslo {_1}..{_2} +@msg `{key}` must be a whole number of 0 or more `{key}` musí být celé číslo 0 nebo větší +@msg `{key}` must be a whole number of at least 0, not {n} `{key}` musí být celé číslo nejméně 0, ne {n} +@msg `{key}` must be an appearance item index (paint order) or null `{key}` musí být index položky vzhledu (pořadí vykreslení) nebo null +@msg `{key}` must be an array of asset ids (see assets.list) `{key}` musí být pole ID prvků (viz assets.list) +@msg `{key}` must be from 0 to 180 degrees, not {a} `{key}` musí být od 0 do 180 stupňů, ne {a} +@msg `{key}` must be from 0 to {MAX_DISTANCE} pt `{key}` musí být od 0 do {MAX_DISTANCE} pt +@msg `{key}` must be from {_1} to {shift_max} `{key}` musí být od {_1} do {shift_max} +@msg `{key}` must be from {lo} to {hi}, not {v} `{key}` musí být od {lo} do {hi}, ne {v} +@msg `{key}` must be one of auto, always, never `{key}` musí být jedna z hodnot auto, always, never +@msg `{key}` must be one of miter, round, bevel `{key}` musí být jedna z hodnot miter, round, bevel +@msg `{key}` must be one word of at most {_1} characters `{key}` musí být jedno slovo o nejvýše {_1} znacích +@msg `{key}` must hold single words of at most {_1} characters `{key}` musí obsahovat jednotlivá slova o nejvýše {_1} znacích +@msg `{key}` must name an object attached to the path of an Objects on Path group `{key}` musí uvádět objekt připojený k cestě skupiny Objekty na cestě +@msg `{key}` names an object that is hidden or locked `{key}` uvádí objekt, který je skrytý nebo zamknutý +@msg `{key}`: not a colour: {v} `{key}`: není barva: {v} +@msg `{k}.family` is required `{k}.family` je povinné +@msg `{k}` is a number 0..1 `{k}` je číslo 0..1 +@msg `{k}` is true or false `{k}` je true nebo false +@msg `{k}` isn't an export setting: {_1} `{k}` není nastavení exportu: {_1} +@msg `{k}` must be a byte offset `{k}` musí být bajtový posun +@msg `{k}` must be a number `{k}` musí být číslo +@msg `{k}` must be a number of points `{k}` musí být počet bodů +@msg `{k}` must be a string `{k}` musí být řetězec +@msg `{k}` must be a whole number `{k}` musí být celé číslo +@msg `{k}` must be from {lo} to {hi} for {key} `{k}` musí být pro {key} od {lo} do {hi} +@msg `{k}` must be {what}, not {v} `{k}` musí být {what}, ne {v} +@msg `{l}` isn't a global or spot colour `{l}` není globální ani přímá barva +@msg `{m}` isn't a bitmap: use clipboard.importSvg, importPdf or importText `{m}` není bitmapa: použijte clipboard.importSvg, importPdf nebo importText +@msg `{name}` can't be deleted `{name}` nelze odstranit +@msg `{name}` can't be duplicated `{name}` nelze duplikovat +@msg `{name}` can't be edited `{name}` nelze upravit +@msg `{name}` can't be edited this way `{name}` nelze tímto způsobem upravit +@msg `{name}` can't be renamed `{name}` nelze přejmenovat +@msg `{name}` can't name a folder `{name}` nemůže být názvem složky +@msg `{name}` has no art to place `{name}` nemá žádnou kresbu k umístění +@msg `{name}` has no text to place `{name}` nemá žádný text k umístění +@msg `{name}` in the Word document is not UTF-8 or UTF-16 text `{name}` v dokumentu Word není text v UTF-8 ani UTF-16 +@msg `{name}` in the Word document is not well-formed XML: {e} `{name}` v dokumentu Word není správně utvořené XML: {e} +@msg `{name}` in the Word document nests elements more than {MAX_NESTING} deep `{name}` v dokumentu Word vnořuje prvky hlouběji než {MAX_NESTING} úrovní +@msg `{name}` is a built-in preset and is read-only: save it under another name `{name}` je vestavěné přednastavení jen pro čtení: uložte ho pod jiným názvem +@msg `{name}` is a built-in preset: save under another name `{name}` je vestavěné přednastavení: uložte ho pod jiným názvem +@msg `{name}` is a built-in profile and stays `{name}` je vestavěný profil a zůstává +@msg `{name}` is a file of its own, which can only be found next to the DCS file's path `{name}` je samostatný soubor, který lze najít jen vedle cesty souboru DCS +@msg `{name}` is a tint of `{base}`: edit `{base}` (a tint swatch only takes a new name) `{name}` je tón barvy `{base}`: upravte `{base}` (položce vzorníku s tónem lze dát jen nový název) +@msg `{name}` is a working space: choose another with edit.colorSettings first `{name}` je pracovní barevný prostor: nejprve zvolte jiný pomocí edit.colorSettings +@msg `{name}` is built in and stays `{name}` je vestavěné a zůstává +@msg `{name}` takes a paint of its own kind (colour, gradient or pattern) `{name}` přijímá nátěr svého druhu (barvu, přechod nebo vzorek) +@msg `{name}`: {_1}: {e} `{name}`: {_1}: {e} +@msg `{n}` can't be deleted `{n}` nelze odstranit +@msg `{n}` can't be merged `{n}` nelze sloučit +@msg `{n}` can't be moved `{n}` nelze přesunout +@msg `{n}` is not a colour swatch `{n}` není barevná položka vzorníku +@msg `{n}` isn't a solid colour `{n}` není plná barva +@msg `{n}`: colour groups hold solid colours only `{n}`: skupiny barev obsahují jen plné barvy +@msg `{other}` doesn't trace an image `{other}` nevektorizuje obraz +@msg `{s}`: the step's references copy in more than {_1} MB of values `{s}`: odkazy kroku by zkopírovaly více než {_1} MB hodnot +@msg `{tag}` is not an axis tag: a tag is four characters, such as "wght" `{tag}` není značka osy: značka má čtyři znaky, například "wght" +@msg `{to}` is empty or already used `{to}` je prázdné nebo už použité +@msg `{u}` is no Unicode character `{u}` není znak Unicode +@msg `{what}` is longer than {MAX_TEXT} bytes `{what}` je delší než {MAX_TEXT} bajtů +@msg `{what}` must be text `{what}` musí být text +@msg `{word}` isn't in the custom dictionary `{word}` není ve vlastním slovníku +@msg a CMap has too many mappings CMap má příliš mnoho mapování +@msg a DXF drawing has one origin: pass useArtboards: true for one drawing per artboard výkres DXF má jeden počátek: předejte useArtboards: true pro jeden výkres na každou pracovní plochu +@msg a PDF presets file with over {_1} presets soubor přednastavení PDF s více než {_1} přednastaveními +@msg a \u escape needs four hexadecimal digits sekvence \u vyžaduje čtyři šestnáctkové číslice +@msg a batch preview cannot switch documents náhled dávky nemůže přepínat dokumenty +@msg a brush named `{nn}` exists štětec s názvem `{nn}` už existuje +@msg a comma in an XPath expression must separate function arguments čárka ve výrazu XPath musí oddělovat argumenty funkce +@msg a container of the listed objects is gone kontejner uvedených objektů už neexistuje +@msg a content stream can't be read proud obsahu nelze přečíst +@msg a content stream isn't a stream proud obsahu není proud +@msg a design holds at most {_1} objects návrh obsahuje nejvýše {_1} objektů +@msg a design needs a name návrh potřebuje název +@msg a dictionary grew too large slovník se příliš zvětšil +@msg a document holds at most {_1} SVG filters dokument obsahuje nejvýše {_1} filtrů SVG +@msg a document keeps at most {_1} graph designs dokument uchovává nejvýše {_1} návrhů grafu +@msg a document keeps at most {_1} saved selections dokument uchovává nejvýše {_1} uložených výběrů +@msg a document keeps at most {_1} views dokument uchovává nejvýše {_1} zobrazení +@msg a document links at most {MAX_SVG_SCRIPTS} JavaScript files dokument odkazuje na nejvýše {MAX_SVG_SCRIPTS} souborů JavaScript +@msg a document with unsaved changes has no recovery copy dokument s neuloženými změnami nemá záložní kopii +@msg a feConvolveMatrix filter's order is {x}×{y}, which overflows the kernel-size multiply usvg makes řád filtru feConvolveMatrix je {x}×{y}, což přeteče při násobení velikosti jádra, které provádí usvg +@msg a font's data is too large data písma jsou příliš velká +@msg a font's subroutines are too large podprogramy písma jsou příliš velké +@msg a function declaration without a name deklarace funkce bez názvu +@msg a gradient preset is already called {n} některé přednastavení přechodu se už jmenuje {n} +@msg a graph has at most {_1} series, so it transposes with at most that many categories graf má nejvýše {_1} řad, takže ho lze transponovat nejvýše s tolika kategoriemi +@msg a host value has too many entries hodnota hostitele má příliš mnoho položek +@msg a host value is nested too deep hodnota hostitele je vnořena příliš hluboko +@msg a layer can't be merged into its own sublayer vrstvu nelze sloučit do její vlastní podvrstvy +@msg a layer's form box isn't an array rámeček formuláře vrstvy není pole +@msg a layer's form can't be read formulář vrstvy nelze přečíst +@msg a layer's form has no box formulář vrstvy nemá rámeček +@msg a layer's form has no dictionary formulář vrstvy nemá slovník +@msg a legend draws at most {MAX_CHIPS} swatches legenda vykreslí nejvýše {MAX_CHIPS} barevných políček +@msg a name names one asset: give multiple: false, or one object název určuje jeden prvek: zadejte multiple: false, nebo jeden objekt +@msg a namespace declaration uses a reserved prefix or URI deklarace jmenného prostoru používá vyhrazenou předponu nebo URI +@msg a namespace qualifier is undefined kvalifikátor jmenného prostoru není definován +@msg a namespace with an empty URI cannot have a prefix jmenný prostor s prázdným URI nemůže mít předponu +@msg a number has no digits číslo nemá žádné číslice +@msg a number's exponent has no digits exponent čísla nemá žádné číslice +@msg a number's fraction has no digits zlomková část čísla nemá žádné číslice +@msg a page can't be read stránku nelze přečíst +@msg a page object is used by something else objekt stránky používá něco jiného +@msg a page thumbnail must be RGB pixels, 1 to {THUMBNAIL_SIZE} a side (got {w} × {h}) miniatura stránky musí být z obrazových bodů RGB, 1 až {THUMBNAIL_SIZE} na stranu (zadáno {w} × {h}) +@msg a pattern layer doesn't end what it starts vrstva vzorku neukončuje to, co začíná +@msg a pattern layer's colors hold something else barvy vrstvy vzorku obsahují něco jiného +@msg a pattern named `{n}` exists vzorek s názvem `{n}` už existuje +@msg a plug-in with id {_1} is already installed zásuvný modul s ID {_1} je už nainstalován +@msg a preset named `{n}` exists přednastavení s názvem `{n}` už existuje +@msg a print presets file with over {_1} presets soubor přednastavení tisku s více než {_1} přednastaveními +@msg a profile is already called {n} některý profil se už jmenuje {n} +@msg a property descriptor cannot have both a value or writable and a get or set popisovač vlastnosti nemůže mít zároveň value nebo writable a get nebo set +@msg a property descriptor must be an object popisovač vlastnosti musí být objekt +@msg a property's {name} must be a function or undefined {name} vlastnosti musí být funkce nebo undefined +@msg a row can't go into itself řádek nelze vložit do sebe samého +@msg a series goes on the left or the right value axis řada patří na levou nebo pravou osu hodnot +@msg a start must be an anchor index ≥ 0 or null začátek musí být index kotevního bodu ≥ 0 nebo null +@msg a stream in it would decode to more than 256 MB, or its decode parameters can't be applied některý proud v něm by se dekódoval na více než 256 MB, nebo nelze použít jeho parametry dekódování +@msg a string holds a control character řetězec obsahuje řídicí znak +@msg a string holds an escape sequence JSON does not have řetězec obsahuje řídicí sekvenci, kterou JSON nezná +@msg a string is not closed řetězec není uzavřen +@msg a style named `{name}` already exists styl s názvem `{name}` už existuje +@msg a style named `{to}` already exists styl s názvem `{to}` už existuje +@msg a swatch needs a colour, gradient or pattern položka vzorníku potřebuje barvu, přechod nebo vzorek +@msg a symbol named `{n}` already exists symbol s názvem `{n}` už existuje +@msg a theme has 1 to {THEME_SIZE} colours motiv má 1 až {THEME_SIZE} barev +@msg a theme is already called {name} (replace: "{name}" overwrites it) některý motiv se už jmenuje {name} (replace: "{name}" ho přepíše) +@msg a toolbar name has at most {MAX_NAME} characters název panelu nástrojů má nejvýše {MAX_NAME} znaků +@msg a view named `{_1}` exists zobrazení s názvem `{_1}` už existuje +@msg a view named `{name}` exists zobrazení s názvem `{name}` už existuje +@msg a workspace keeps at most {MAX} toolbars pracovní prostor uchovává nejvýše {MAX} panelů nástrojů +@msg a {_1} series can't go in a {_2} graph řadu typu {_1} nelze vložit do grafu typu {_2} +@msg aiVersion {v}: "pdf" (PDF-compatible, the default) or "7" (legacy .ai, version 7) aiVersion {v}: "pdf" (kompatibilní s PDF, výchozí) nebo "7" (starší .ai, verze 7) +@msg already editing an opacity mask maska krytí se už upravuje +@msg already editing another object's opacity mask už se upravuje maska krytí jiného objektu +@msg already in pattern editing mode režim úprav vzorku je už aktivní +@msg an SVG filter is named by its id: give `xml` with `name` filtr SVG je pojmenován svým ID: zadejte `xml` spolu s `name` +@msg an XML element has two attributes with the same name prvek XML má dva atributy se stejným názvem +@msg an XML value cannot be inserted into itself or its descendants hodnotu XML nelze vložit do sebe samé ani do jejích potomků +@msg an XML value's children cannot be assigned by position potomky hodnoty XML nelze přiřazovat podle pozice +@msg an XML value's children cannot be deleted by position potomky hodnoty XML nelze odstraňovat podle pozice +@msg an XMLList converts to XML only when it has one item XMLList se převede na XML, jen když má jednu položku +@msg an XPath node test is missing chybí test uzlu XPath +@msg an XPath operand is missing chybí operand XPath +@msg an XPath operator is missing chybí operátor XPath +@msg an XPath predicate or step cannot follow here predikát ani krok XPath zde nemůže následovat +@msg an XPath predicate or step follows a value that is not a node-set predikát nebo krok XPath následuje za hodnotou, která není množina uzlů +@msg an XPath step is missing chybí krok XPath +@msg an artboard is listed twice některá pracovní plocha je uvedena dvakrát +@msg an empty artboard has no width or height to scale to prázdná pracovní plocha nemá šířku ani výšku, na kterou by šlo měnit velikost +@msg an image couldn't be decoded and is missing from the picture obraz nešlo dekódovat a v obrázku chybí +@msg an image is too large for DXF and was left out obraz je pro DXF příliš velký a byl vynechán +@msg an image of {_1} MB, at most {_2} MB obraz o velikosti {_1} MB, nejvýše {_2} MB +@msg an image of {declared_w} × {declared_h} pixels is too large to draw obraz o rozměrech {declared_w} × {declared_h} obrazových bodů je příliš velký na vykreslení +@msg an image of {width} × {height} pixels is too large to draw obraz o rozměrech {width} × {height} obrazových bodů je příliš velký na vykreslení +@msg an image of {w} × {h} pixels is too large to convert (at most {_1} pixels) obraz o rozměrech {w} × {h} obrazových bodů je příliš velký na převod (nejvýše {_1} obrazových bodů) +@msg an index must be a whole number index musí být celé číslo +@msg an inline graphic has no glyphs vložená grafika v textu nemá žádné glyfy +@msg an invisible text form can't be read formulář neviditelného textu nelze přečíst +@msg an object is missing chybí objekt +@msg an object's header is missing chybí záhlaví objektu +@msg an overprinting form can't be read formulář s přetiskem nelze přečíst +@msg an unread object has no readable bounds nepřečtený objekt nemá čitelné hranice +@msg an unread object holds a frame of threaded type nepřečtený objekt obsahuje rámec zřetězeného textu +@msg an unread object is missing from its layer nepřečtený objekt chybí ve své vrstvě +@msg anchor `smooth` must be true or false `smooth` kotevního bodu musí být true nebo false +@msg anchor `{key}` must be [x, y] `{key}` kotevního bodu musí být [x, y] +@msg anchor `{key}` must be a number `{key}` kotevního bodu musí být číslo +@msg angle and roundness must be finite úhel a zaoblení musí být konečné +@msg angles must be a list as long as pins (degrees or null) angles musí být seznam stejně dlouhý jako pins (stupně nebo null) +@msg appearance must be flat|center|edge appearance musí být flat|center|edge +@msg apply is "fill" or "stroke", not `{other}` apply je "fill" nebo "stroke", ne `{other}` +@msg apply was called on a value that is not a function apply byla zavolána na hodnotě, která není funkce +@msg area must be a closed polygon of 3 to 100000 [x, y] points area musí být uzavřený mnohoúhelník o 3 až 100000 bodech [x, y] +@msg area type in a thread cannot use Dynamic Text: {frames} text v oblasti ve zřetězeném textu nemůže používat dynamický text: {frames} +@msg area type needs a path that encloses an area text v oblasti vyžaduje cestu, která uzavírá plochu +@msg area type {_1} is named twice text v oblasti {_1} je uveden dvakrát +@msg array literal too long literál pole je příliš dlouhý +@msg arrowAlign must be extend|tip, got {o} arrowAlign musí být extend|tip, zadáno {o} +@msg arrowScale must be [start, end] arrowScale musí být [start, end] +@msg artboard is a 0-based index artboard je index počítaný od 0 +@msg artboard must be a 0-based index artboard musí být index počítaný od 0 +@msg artboard {i} doesn't print pracovní plocha {i} se netiskne +@msg artboardLayout must be {layout?, columns?, spacing?, rightToLeft?} artboardLayout musí být {layout?, columns?, spacing?, rightToLeft?} +@msg artboardLayout.columns must be 1 or more artboardLayout.columns musí být 1 nebo více +@msg artboardLayout.layout must be gridByRow, gridByColumn, row or column artboardLayout.layout musí být gridByRow, gridByColumn, row nebo column +@msg artboardLayout.rightToLeft must be true or false artboardLayout.rightToLeft musí být true nebo false +@msg artboardLayout.spacing must be 0–{MAX_SPACING} pt artboardLayout.spacing musí být 0–{MAX_SPACING} pt +@msg artboards must be a non-empty list artboards musí být neprázdný seznam +@msg artboards must be a number artboards musí být číslo +@msg asset `{_1}` has no art to export prvek `{_1}` nemá žádnou kresbu k exportu +@msg assignment to a constant binding přiřazení do konstantní vazby +@msg at least one row that isn't excluded needs a weight above 0 alespoň jeden nevyloučený řádek potřebuje váhu větší než 0 +@msg at most {MAX_KEYWORDS} keywords nejvýše {MAX_KEYWORDS} klíčových slov +@msg at most {MAX_MATCHES} matches are kept uchovává se nejvýše {MAX_MATCHES} shod +@msg at most {MAX_POINTS} points nejvýše {MAX_POINTS} bodů +@msg at most {MAX_QUEUE} files nejvýše {MAX_QUEUE} souborů +@msg at must be [x, y] at musí být [x, y] +@msg at/rect lie outside the canvas at/rect leží mimo plátno +@msg attribute must be size|leading|tracking|kerning|baselineShift attribute musí být size|leading|tracking|kerning|baselineShift +@msg attrs must be an object attrs musí být objekt +@msg automation path rejected: the folder's name isn't valid text cesta automatizace byla odmítnuta: název složky není platný text +@msg automation path rejected: {_1} isn't valid text cesta automatizace byla odmítnuta: {_1} není platný text +@msg automation path rejected: {why}: {path} cesta automatizace byla odmítnuta: {why}: {path} +@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{given}` axis musí být "vertical", "horizontal" nebo úhel ve stupních, ne `{given}` +@msg backgroundContents must be transparent or white backgroundContents musí být transparent nebo white +@msg bad AES key chybný klíč AES +@msg bad `runs`: {e} chybné `runs`: {e} +@msg bad arrowScale chybné arrowScale +@msg bad base64 chybný base64 +@msg bad color {c} chybná barva {c} +@msg bad colour chybná barva +@msg bad colour in `colors` chybná barva v `colors` +@msg bad colour {v} chybná barva {v} +@msg bad colour {v} in groupColors chybná barva {v} v groupColors +@msg bad cross-reference entry chybná položka křížových odkazů +@msg bad cross-reference table chybná tabulka křížových odkazů +@msg bad current colour {v} chybná aktuální barva {v} +@msg bad dataBase64 chybné dataBase64 +@msg bad edit chybná úprava +@msg bad fill {v} chybná výplň {v} +@msg bad fit: {e} chybné přizpůsobení: {e} +@msg bad model {other} (keep, new or document) chybný model {other} (keep, new nebo document) +@msg bad new colour {v} chybná nová barva {v} +@msg bad object chybný objekt +@msg bad object number chybné číslo objektu +@msg bad offset chybný posun +@msg bad path data: {e} chybná data cesty: {e} +@msg bad point {v}: expected [x, y] chybný bod {v}: očekáváno [x, y] +@msg bad point {v}: expected [x, y] or [x, y, pressure] chybný bod {v}: očekáváno [x, y] nebo [x, y, pressure] +@msg bad reference chybný odkaz +@msg bad trailer size chybná velikost v zakončení +@msg bad {k} colour chybná barva {k} +@msg batches cannot nest dávky nelze vnořovat +@msg bind something to a variable first nejprve něco svažte s proměnnou +@msg bleed must be 0–{MAX_BLEED} pt: a number, [top, bottom, left, right] or {{top, bottom, left, right}} bleed musí být 0–{MAX_BLEED} pt: číslo, [top, bottom, left, right] nebo {{top, bottom, left, right}} +@msg blend must be a mode name blend musí být název režimu +@msg both sides of an XPath | must select nodes obě strany operátoru | v XPath musí vybírat uzly +@msg brush must be a name or null brush musí být název nebo null +@msg by must be a number by musí být číslo +@msg can't add page thumbnails: {why} miniatury stránek nelze přidat: {why} +@msg can't add the editing data for other apps: {why} data pro úpravy v jiných aplikacích nelze přidat: {why} +@msg can't edit the written PDF: {why} zapsané PDF nelze upravit: {why} +@msg can't encrypt the PDF: {why} PDF nelze zašifrovat: {why} +@msg can't linearise the PDF: {why} PDF nelze linearizovat: {why} +@msg can't open `{_1}`: {_2} `{_1}` nelze otevřít: {_2} +@msg can't open `{_1}`: {e} `{_1}` nelze otevřít: {e} +@msg can't open `{name}`: not a format VectorCraft reads (see document.formats) `{name}` nelze otevřít: nejde o formát, který VectorCraft čte (viz document.formats) +@msg can't place `{name}`: not a format VectorCraft reads (see document.formats) `{name}` nelze umístit: nejde o formát, který VectorCraft čte (viz document.formats) +@msg can't read back the written PDF: {e} zapsané PDF nelze znovu načíst: {e} +@msg can't read this Word document: {why} tento dokument Word nelze přečíst: {why} +@msg can't write .{e} images: use .png, .jpg, .gif, .webp, .tif or .bmp obrázky .{e} nelze zapisovat: použijte .png, .jpg, .gif, .webp, .tif nebo .bmp +@msg can't write PDF layers, overprint or invisible text: {why} vrstvy PDF, přetisk ani neviditelný text nelze zapsat: {why} +@msg can't write the file's copyright: {why} údaj o autorských právech souboru nelze zapsat: {why} +@msg can't write the file's modification date: {why} datum změny souboru nelze zapsat: {why} +@msg can't write the pages' user units: {why} uživatelské jednotky stránek nelze zapsat: {why} +@msg canceled zrušeno +@msg cannot convert the object to a primitive value objekt nelze převést na primitivní hodnotu +@msg cannot convert undefined or null to an object undefined ani null nelze převést na objekt +@msg cannot distort a zero-size or non-finite bounding box ohraničovací rámeček s nulovou nebo nekonečnou velikostí nelze deformovat +@msg cannot move an object into itself objekt nelze přesunout do sebe samého +@msg case must be upper|lower|title|sentence case musí být upper|lower|title|sentence +@msg category `{c}`: one of {_1} kategorie `{c}`: jedna z hodnot {_1} +@msg center must be [x, y] center musí být [x, y] +@msg character dimensions cannot be represented with the source text transform rozměry znaků nelze vyjádřit transformací zdrojového textu +@msg character dimensions cannot be represented with the target text transform rozměry znaků nelze vyjádřit transformací cílového textu +@msg choose at least one artboard zvolte alespoň jednu pracovní plochu +@msg choose at least one status zvolte alespoň jeden stav +@msg clip must be true or false clip musí být true nebo false +@msg clippingMask must be true or false clippingMask musí být true nebo false +@msg closed must be a boolean closed musí být logická hodnota +@msg collapsed must be true or false collapsed musí být true nebo false +@msg color.profile: no RGB or CMYK profile is called “{profile}” color.profile: žádný profil RGB ani CMYK se nejmenuje „{profile}“ +@msg colorMode must be rgb or cmyk, not `{m}` colorMode musí být rgb nebo cmyk, ne `{m}` +@msg colorModel must be {own} (the document's mode), grayscale or bitmap colorModel musí být {own} (režim dokumentu), grayscale nebo bitmap +@msg colour groups can't go into colour groups skupiny barev nelze vkládat do skupin barev +@msg colour, mode and spot apply to solid-colour swatches only colour, mode a spot platí jen pro položky vzorníku s plnou barvou +@msg column {column}: `{cell}` is a `%` column of graph data files, which are not read sloupec {column}: `{cell}` je sloupec `%` pro soubory dat grafu, které se nečtou +@msg column {column}: `{cell}` names `{name}`, which is a {_1} variable sloupec {column}: `{cell}` uvádí `{name}`, což je proměnná typu {_1} +@msg column {column}: `{cell}` names no variable sloupec {column}: `{cell}` neuvádí žádnou proměnnou +@msg column {column}: the variable name is longer than {MAX_NAME} characters sloupec {column}: název proměnné je delší než {MAX_NAME} znaků +@msg column: true floats the whole column and takes no onto, above or below column: true uvolní celý sloupec jako plovoucí a nepřijímá onto, above ani below +@msg command must be a shape.* command command musí být příkaz shape.* +@msg commands[{i}]: missing `command` commands[{i}]: chybí `command` +@msg composer must be "singleLine" or "everyLine" composer musí být "singleLine" nebo "everyLine" +@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes složené tvary přijímají cesty, složené cesty, skupiny, složené tvary, text, prolnutí a obálky +@msg compound {_1} must contain exactly one open path to join složený objekt {_1} musí ke spojení obsahovat právě jednu otevřenou cestu +@msg connect needs a path other than the one extended connect vyžaduje jinou cestu než tu prodlužovanou +@msg connect needs id connect vyžaduje id +@msg connect path has no open end cesta v connect nemá žádný otevřený konec +@msg continuation must be an array of path chunks continuation musí být pole úseků cesty +@msg continuation requires points continuation vyžaduje points +@msg copy needs path: the file to copy into the document's folder copy vyžaduje path: soubor, který se má zkopírovat do složky dokumentu +@msg copy takes images only: relink placed documents where their files are copy přijímá jen obrázky: umístěné dokumenty znovu propojte tam, kde jsou jejich soubory +@msg copying a file isn't available on the web kopírování souboru není na webu dostupné +@msg copyrightStatus must be unknown, copyrighted or publicDomain copyrightStatus musí být unknown, copyrighted nebo publicDomain +@msg copyrightUrl must be a URL (no spaces, at most 2048 characters) copyrightUrl musí být adresa URL (bez mezer, nejvýše 2048 znaků) +@msg corners must be 4 [x, y] points (TL, TR, BR, BL) corners musí být 4 body [x, y] (TL, TR, BR, BL) +@msg counterPer `{c}`: item or file counterPer `{c}`: item nebo file +@msg crop `{_1}`: only PDF pages have art, trim, bleed and media boxes; use "crop" or "bounding" crop `{_1}`: rámečky art, trim, bleed a media mají jen stránky PDF; použijte "crop" nebo "bounding" +@msg crop rectangle doesn't overlap the image ořezový obdélník se nepřekrývá s obrazem +@msg cross-reference and object streams aren't supported proudy křížových odkazů a proudy objektů nejsou podporovány +@msg damaged compressed data: {e} poškozená komprimovaná data: {e} +@msg dash lengths must be numbers, got {v} délky čárek musí být čísla, zadáno {v} +@msg dash must be a list of lengths or null, got {v} dash musí být seznam délek nebo null, zadáno {v} +@msg data key `{k}`: letters, digits, -, _ and . (not name or vc-…) klíč dat `{k}`: písmena, číslice, -, _ a . (ne name ani vc-…) +@msg data must be an object of key: value, not {v} data musí být objekt ve tvaru klíč: hodnota, ne {v} +@msg data set `{name}` holds a value for `{var}`, which the library doesn't declare sada dat `{name}` obsahuje hodnotu pro `{var}`, kterou knihovna nedeklaruje +@msg data set `{name}` holds two values for `{var}` sada dat `{name}` obsahuje dvě hodnoty pro `{var}` +@msg data set `{name}` is declared twice sada dat `{name}` je deklarována dvakrát +@msg data takes at most {MAX_DATA} keys at once data přijímá najednou nejvýše {MAX_DATA} klíčů +@msg dataset `{name}` already exists sada dat `{name}` už existuje +@msg dataset `{to}` already exists sada dat `{to}` už existuje +@msg date `{d}`: YYYY-MM-DD datum `{d}`: YYYY-MM-DD +@msg decoded data is too large dekódovaná data jsou příliš velká +@msg define a variable first nejprve definujte proměnnou +@msg detect must be true or false detect musí být true nebo false +@msg direct-select anchor points of a path vyberte kotevní body cesty přímým výběrem +@msg distance must be > 0 distance musí být > 0 +@msg dx and dy give the arrow's direction dx a dy udávají směr šipky +@msg dx and dy must be numbers dx a dy musí být čísla +@msg dxf fitTo must be [width, height], positive dxf fitTo musí být [width, height], kladné +@msg dxf must be an object of DXF import options dxf musí být objekt s volbami importu DXF +@msg dxf scale must be a positive number up to {_1}, not {s} dxf scale musí být kladné číslo nejvýše {_1}, ne {s} +@msg dxf unit `{u}`: a unit such as mm, cm, in or pt dxf unit `{u}`: jednotka jako mm, cm, in nebo pt +@msg dxf: {e} dxf: {e} +@msg each format is an object {format, scale?, suffix?} každý formát je objekt {format, scale?, suffix?} +@msg each item needs an id každá položka potřebuje id +@msg each match needs `kind` každá shoda potřebuje `kind` +@msg each match needs a `name` každá shoda potřebuje `name` +@msg each of `fonts` is {family, style?}; 1 to 1000 of them každá položka `fonts` je {family, style?}; 1 až 1000 položek +@msg each of `items` is {kind, item} každá položka `items` je {kind, item} +@msg each of `items` is {{id, corners?}} with an object id, not {it} každá položka `items` je {{id, corners?}} s ID objektu, ne {it} +@msg each path chunk must contain 1 to 4096 points každý úsek cesty musí obsahovat 1 až 4096 bodů +@msg each pick is {{at: [x, y]}} or {{rect: [x0, y0, x1, y1]}} (got {v}) každá volba je {{at: [x, y]}} nebo {{rect: [x0, y0, x1, y1]}} (zadáno {v}) +@msg each row needs `from` každý řádek potřebuje `from` +@msg each stop needs a position každá zarážka potřebuje pozici +@msg each subpath needs an anchors array každá dílčí cesta potřebuje pole anchors +@msg each weight must be a number of 0 or more (got {v}) každá váha musí být číslo 0 nebo větší (zadáno {v}) +@msg easingType must be easeIn, easeOut, easeInOut or easeOutIn easingType musí být easeIn, easeOut, easeInOut nebo easeOutIn +@msg editingData must be true or false editingData musí být true nebo false +@msg editingData must be true, false or "always" editingData musí být true, false nebo "always" +@msg edits overlap úpravy se překrývají +@msg effects of objects whose appearances differ can't be moved together efekty objektů s odlišným vzhledem nelze přesouvat společně +@msg empty header in column {_1} prázdné záhlaví ve sloupci {_1} +@msg encoding `{_1}`: utf8 or utf16 kódování `{_1}`: utf8 nebo utf16 +@msg ends must be two of "first" and "last" ends musí být dvě z hodnot "first" a "last" +@msg every numbered name for the result is taken každý číslovaný název pro výsledek je už obsazen +@msg expanded SVG styles exceed the import size limit rozvinuté styly SVG překračují limit velikosti importu +@msg export presets file is larger than {MAX_PRESET_FILE_BYTES} bytes soubor přednastavení exportu je větší než {MAX_PRESET_FILE_BYTES} bajtů +@msg exportText must be editable or appearance exportText musí být editable nebo appearance +@msg exportType must be movieClip or graphic, not `{s}` exportType musí být movieClip nebo graphic, ne `{s}` +@msg extend needs id extend vyžaduje id +@msg featureChanges lists at most {MAX_FEATURE_CHANGES} tags featureChanges uvádí nejvýše {MAX_FEATURE_CHANGES} značek +@msg featureChanges must be a list of tags featureChanges musí být seznam značek +@msg features must be a list of tags features musí být seznam značek +@msg fidelity must be 0..100 fidelity musí být 0..100 +@msg files must be {name, dataBase64} files musí být {name, dataBase64} +@msg finally table {t} out of range tabulka finally {t} je mimo rozsah +@msg fit must be none|autoHeight|shrinkText|block, got {id} fit musí být none|autoHeight|shrinkText|block, zadáno {id} +@msg flags cannot be given with a RegExp object příznaky nelze zadat spolu s objektem RegExp +@msg flattener: {e} sloučení průhlednosti: {e} +@msg flattenerPreset `{name}`: high, medium, low or a saved one (see flattener.presets.list) flattenerPreset `{name}`: high, medium, low nebo uložené přednastavení (viz flattener.presets.list) +@msg flipProfile must be along|across, got {o} flipProfile musí být along|across, zadáno {o} +@msg folders `{f}`: none, rows, format, item or itemFormat folders `{f}`: none, rows, format, item nebo itemFormat +@msg folders deeper than {MAX_BATCH_DEPTH} levels složky hlubší než {MAX_BATCH_DEPTH} úrovní +@msg folders deeper than {MAX_DEPTH} levels složky hlubší než {MAX_DEPTH} úrovní +@msg font family `{family}` is not available rodina písma `{family}` není dostupná +@msg font family `{tf}` is not available rodina písma `{tf}` není dostupná +@msg format `{f}`: pdf or postscript formát `{f}`: pdf nebo postscript +@msg format `{f}`: text or json formát `{f}`: text nebo json +@msg format is `{format}` formát je `{format}` +@msg formats must be an array of rows, not {v} formats musí být pole řádků, ne {v} +@msg frequency must be between 1 and 300 lines per inch frequency musí být mezi 1 a 300 linkami na palec +@msg from and to must be finite from a to musí být konečné +@msg from must be [x0, y0, x1, y1] from musí být [x0, y0, x1, y1] +@msg function declaration index out of range index deklarace funkce je mimo rozsah +@msg give `before` or `after`, not both zadejte `before` nebo `after`, ne obojí +@msg give `char`, `text`, `code` or `unicode` zadejte `char`, `text`, `code` nebo `unicode` +@msg give `colors`, or `color` and `rule` zadejte `colors`, nebo `color` a `rule` +@msg give `count` or `spacing`, not both zadejte `count` nebo `spacing`, ne obojí +@msg give `event`, such as onclick zadejte `event`, například onclick +@msg give `file`, the JavaScript file's path or URL zadejte `file`, cestu nebo adresu URL souboru JavaScript +@msg give `fill` and/or `stroke` zadejte `fill` a/nebo `stroke` +@msg give `fill`, `stroke` or both zadejte `fill`, `stroke` nebo obojí +@msg give `folder` zadejte `folder` +@msg give `fonts`, or open a document zadejte `fonts`, nebo otevřete dokument +@msg give `from` or `indices`, not both zadejte `from` nebo `indices`, ne obojí +@msg give `id` (no text is being edited) zadejte `id` (žádný text se právě neupravuje) +@msg give `id` and `anchors`, or `items`, not both zadejte `id` a `anchors`, nebo `items`, ne obojí +@msg give `id` or `guide`, not both zadejte `id` nebo `guide`, ne obojí +@msg give `length` or `to` zadejte `length` nebo `to` +@msg give `matches`: [{kind, name, target}] zadejte `matches`: [{kind, name, target}] +@msg give `name` (or edit a pattern) zadejte `name` (nebo upravujte vzorek) +@msg give `name` or `names` zadejte `name` nebo `names` +@msg give `name`, an SVG filter's name zadejte `name`, název filtru SVG +@msg give `path` (a .wasm file) or `dataBase64` (the module) zadejte `path` (soubor .wasm) nebo `dataBase64` (modul) +@msg give `path`, `data` or `dataBase64` zadejte `path`, `data` nebo `dataBase64` +@msg give `path`, `data`, `dataBase64` or `csv` zadejte `path`, `data`, `dataBase64` nebo `csv` +@msg give `path`, `xml` or `dataBase64` zadejte `path`, `xml` nebo `dataBase64` +@msg give `path`, an SVG file, or `svg`, SVG text zadejte `path`, soubor SVG, nebo `svg`, text SVG +@msg give `script`, the JavaScript the event runs ("" removes the event) zadejte `script`, JavaScript, který událost spustí ("" událost odebere) +@msg give `text` (the reading) or `remove` zadejte `text` (čtení) nebo `remove` +@msg give `x` and `y` (and a `tolerance` of 0 or more) zadejte `x` a `y` (a `tolerance` 0 nebo více) +@msg give `xml`, one SVG element zadejte `xml`, jeden prvek SVG +@msg give a mode or r/g/b, c/m/y/k, gray or tint adjustments zadejte režim nebo úpravy r/g/b, c/m/y/k, gray či tint +@msg give a name, or paint the active proxy with a saved preset zadejte název, nebo aktivní výplň či tah nastavte uloženým přednastavením +@msg give a name, or select a stroke with a saved profile zadejte název, nebo vyberte tah s uloženým profilem +@msg give a pattern name or select an object painted with a pattern zadejte název vzorku nebo vyberte objekt vybarvený vzorkem +@msg give at least one of clip, invert, disabled, linked zadejte alespoň jedno z clip, invert, disabled, linked +@msg give color, none, swatch or gradient zadejte color, none, swatch nebo gradient +@msg give dataBase64 zadejte dataBase64 +@msg give either at (a click) or area (a path drawn around the overlaps) zadejte buď at (kliknutí), nebo area (cestu nakreslenou kolem překryvů) +@msg give exactly one of `at`, `rect` and `points` zadejte právě jedno z `at`, `rect` a `points` +@msg give exactly one of `path`, `data` and `dataBase64` zadejte právě jedno z `path`, `data` a `dataBase64` +@msg give formats or a preset, not both zadejte formats nebo přednastavení, ne obojí +@msg give index or indexes, not both zadejte index nebo indexes, ne obojí +@msg give newName or delete zadejte newName nebo delete +@msg give offset or by zadejte offset nebo by +@msg give one element zadejte jeden prvek +@msg give one of `to`, `rect` or `at` zadejte jedno z `to`, `rect` nebo `at` +@msg give one of assets, layers, selection or fullDocument zadejte jedno z assets, layers, selection nebo fullDocument +@msg give only one of onto, above, below, icon and a column place zadejte jen jedno z onto, above, below, icon a umístění ve sloupci +@msg give opacity or blend zadejte opacity nebo blend +@msg give origin: [x, y], or reset: true zadejte origin: [x, y], nebo reset: true +@msg give overprintFill, overprintStroke, showCenter, imageMap, url or note zadejte overprintFill, overprintStroke, showCenter, imageMap, url nebo note +@msg give path (a file) or folder zadejte path (soubor) nebo folder +@msg give path, or name and dataBase64 zadejte path, nebo name a dataBase64 +@msg give paths or files zadejte paths nebo files +@msg give rows, rowHeight, columns or columnWidth zadejte rows, rowHeight, columns nebo columnWidth +@msg give svg, or dataBase64 of an SVG or SVGZ file zadejte svg, nebo dataBase64 souboru SVG či SVGZ +@msg give text zadejte text +@msg give the asset a name pojmenujte prvek +@msg give the preset a `name` zadejte pro přednastavení `name` +@msg give the preset a name pojmenujte přednastavení +@msg give the preset a name (1–64 characters) pojmenujte přednastavení (1–64 znaků) +@msg give the settings to change, e.g. {"formats"}]} zadejte nastavení, která se mají změnit, např. {"formats"}]} +@msg give the style a name pojmenujte styl +@msg give two or more style `names` zadejte v `names` dva nebo více stylů +@msg give two or more swatches zadejte dvě nebo více položek vzorníku +@msg give x, y, or a handle's length or angle zadejte x, y, nebo délku či úhel úchytu +@msg give {key, value} or {values} zadejte {key, value} nebo {values} +@msg global must be true or false global musí být true nebo false +@msg glyph {_1} is not drawn for {ch} with the character's style (such as All Caps, Small Caps or a numeral system) glyf {_1} se pro {ch} se stylem znaku nevykresluje (například Verzálky, Kapitálky nebo číselná soustava) +@msg glyph {g} is not an alternate of {ch} in {_1} {_2} glyf {g} není alternativou znaku {ch} v písmu {_1} {_2} +@msg gradient must be "objects" or "mesh" gradient musí být "objects" nebo "mesh" +@msg grays must be "profile" or "black", not `{g}` grays musí být "profile" nebo "black", ne `{g}` +@msg gridColors must be a preset name or two colours gridColors musí být název přednastavení nebo dvě barvy +@msg gridSize must be small, medium or large gridSize musí být small, medium nebo large +@msg guide {g} is not selected vodítko {g} není vybráno +@msg handle must be 0..3 handle musí být 0..3 +@msg handler at {_1} expects {_2} values but its range starts with {d} obslužná rutina na pozici {_1} očekává {_2} hodnot, ale její rozsah začíná s {d} +@msg handler depth too large hloubka obslužné rutiny je příliš velká +@msg handler range {_1}..{_2} out of range rozsah obslužné rutiny {_1}..{_2} je mimo rozsah +@msg hiddenLayers must be true or false hiddenLayers musí být true nebo false +@msg hiddenObjects {v}: "layer" (the default), "omit" or "visible" hiddenObjects {v}: "layer" (výchozí), "omit" nebo "visible" +@msg highlight a layer to merge into zvýrazněte vrstvu, do které se má sloučit +@msg highlight two or more rows in one layer or group zvýrazněte dva nebo více řádků v jedné vrstvě nebo skupině +@msg highlight two or more rows to merge zvýrazněte dva nebo více řádků ke sloučení +@msg hvcC hvcC +@msg icon docks a panel in the icon column: use window.panel.dock icon ukotví panel ve sloupci ikon: použijte window.panel.dock +@msg id must be a dimension id id musí být ID kóty +@msg image has no bounds obraz nemá hranice +@msg image {_1} is linked already obraz {_1} je už propojený +@msg imageMap `{m}`: none, client or server imageMap `{m}`: none, client nebo server +@msg images in a spot ink whose samples couldn't be read were imported in RGB obrazy v přímé barvě, jejichž vzorky nešlo přečíst, byly importovány v RGB +@msg images past the most pixels one file may hold were left out obrazy nad největší počet obrazových bodů, který smí jeden soubor obsahovat, byly vynechány +@msg images too large to read were left out obrazy příliš velké na přečtení byly vynechány +@msg index out of range index je mimo rozsah +@msg indexes may hold at most {MAX_GUIDE_INDEXES} entries indexes smí obsahovat nejvýše {MAX_GUIDE_INDEXES} položek +@msg indexes must be an array of guide indexes indexes musí být pole indexů vodítek +@msg instances must be 1..1000 instances musí být 1..1000 +@msg instruction out of range instrukce je mimo rozsah +@msg instruction {pc} ({op}) pops below the stack instrukce {pc} ({op}) odebírá pod dno zásobníku +@msg instruction {pc} reached with stack depths {seen} and {d} instrukce {pc} byla dosažena s hloubkami zásobníku {seen} a {d} +@msg invalid `color` neplatné `color` +@msg invalid anchor index {v}: expected a non-negative integer neplatný index kotevního bodu {v}: očekáváno nezáporné celé číslo +@msg invalid anchor reference {v}: expected [subpath, anchor] neplatný odkaz na kotevní bod {v}: očekáváno [dílčí cesta, kotevní bod] +@msg invalid angle neplatný úhel +@msg invalid array length neplatná délka pole +@msg invalid brush: {e} neplatný štětec: {e} +@msg invalid color neplatná barva +@msg invalid colour {c} neplatná barva {c} +@msg invalid delta neplatný rozdíl +@msg invalid group neplatná skupina +@msg invalid object id {v}: expected a non-negative integer neplatné ID objektu {v}: očekáváno nezáporné celé číslo +@msg invalid point neplatný bod +@msg invalid regular expression flag '{_1}' neplatný příznak regulárního výrazu '{_1}' +@msg invalid regular expression: {m} neplatný regulární výraz: {m} +@msg invalid size neplatná velikost +@msg invalid t neplatné t +@msg invalid time value neplatná hodnota času +@msg invalid tolerance neplatná tolerance +@msg is a confirm's answer, whose `value` must be true or false je odpověď na potvrzení, jejíž `value` musí být true nebo false +@msg is a prompt's answer, whose `value` must be a string or null je odpověď na výzvu, jejíž `value` musí být řetězec nebo null +@msg is an alert's answer, whose `value` must be "ok" je odpověď na upozornění, jejíž `value` musí být "ok" +@msg is longer than 16 KiB je delší než 16 KiB +@msg it draws its image through a clipping path vykresluje svůj obraz přes ořezovou cestu +@msg it draws no image nevykresluje žádný obraz +@msg it is larger than {MAX_DICTIONARY_FILE_BYTES} bytes je větší než {MAX_DICTIONARY_FILE_BYTES} bajtů +@msg it isn't a file není to soubor +@msg it names {_1} plates, and at most {MAX_PLATES} are read uvádí {_1} výtažků a čte se jich nejvýše {MAX_PLATES} +@msg its art is too long or too detailed for a head jeho kresba je na hrot příliš dlouhá nebo příliš podrobná +@msg its art paints nothing jeho kresba nic nevykresluje +@msg its artboards all lie beyond the canvas (more than {_1} pt from the origin) všechny jeho pracovní plochy leží mimo plátno (více než {_1} pt od počátku) +@msg its clipping masks are nested too deeply jeho ořezové masky jsou vnořeny příliš hluboko +@msg its image is too large to read jeho obraz je příliš velký na přečtení +@msg its metadata has no description jeho metadata nemají popis +@msg its metadata has no direct length jeho metadata nemají přímou délku +@msg its plates are too large: more than {MAX_SAMPLES} pixels together jeho výtažky jsou příliš velké: dohromady více než {MAX_SAMPLES} obrazových bodů +@msg its plates are too large: {_1} plates of {w} × {h} pixels jeho výtažky jsou příliš velké: {_1} výtažků o {w} × {h} obrazových bodech +@msg its plates can't be kept together jeho výtažky nelze udržet pohromadě +@msg its shapes could not be combined into one jeho tvary nešlo spojit do jednoho +@msg join two different paths spojte dvě různé cesty +@msg jump to {pc}, past the end skok na {pc}, za konec +@msg justify must be auto|left|center|right|justifyAll justify musí být auto|left|center|right|justifyAll +@msg kbps must be a positive number, not {kbps} kbps musí být kladné číslo, ne {kbps} +@msg keywords must be a list of words or a comma-separated string keywords musí být seznam slov nebo řetězec oddělený čárkami +@msg keywords must be at most {MAX_KEYWORD} characters, without control characters keywords smí mít nejvýše {MAX_KEYWORD} znaků, bez řídicích znaků +@msg kind must be 1, 2 or 3, or give a preset `name` (see perspective.presets.list) kind musí být 1, 2 nebo 3, nebo zadejte `name` přednastavení (viz perspective.presets.list) +@msg kind must be graphic, fillColor, strokeColor, fillGradient, strokeGradient, fillPattern, strokePattern, charStyle or paraStyle kind musí být graphic, fillColor, strokeColor, fillGradient, strokeGradient, fillPattern, strokePattern, charStyle nebo paraStyle +@msg knockout must be "on", "off", "neutral" or a bool, not {v} knockout musí být "on", "off", "neutral" nebo logická hodnota, ne {v} +@msg layer `{name}` has no art to export vrstva `{name}` nemá žádnou kresbu k exportu +@msg layer must name a layer or sublayer layer musí uvádět vrstvu nebo podvrstvu +@msg layers can't be intertwined: select the objects in them vrstvy nelze proplést: vyberte objekty v nich +@msg layers go only at the top level or in layers, objects in layers and groups vrstvy mohou být jen na nejvyšší úrovni nebo ve vrstvách, objekty ve vrstvách a skupinách +@msg layers must be true or false layers musí být true nebo false +@msg layout must be gridByRow, gridByColumn, row or column layout musí být gridByRow, gridByColumn, row nebo column +@msg leading must be a number or "auto" leading musí být číslo nebo "auto" +@msg left/right must be non-negative widths left/right musí být nezáporné šířky +@msg legacyNameEncoding must be one of {_1} legacyNameEncoding musí být jedna z hodnot {_1} +@msg level `{t}`: 2 or 3 úroveň `{t}`: 2 nebo 3 +@msg line {line}: more than {MAX_CSV_COLS} columns řádek {line}: více než {MAX_CSV_COLS} sloupců +@msg line {line}: unclosed quote řádek {line}: neuzavřená uvozovka +@msg line {line}: value for `{var}` must match its variable kind řádek {line}: hodnota pro `{var}` musí odpovídat druhu její proměnné +@msg lineEndings `{other}`: lf or crlf lineEndings `{other}`: lf nebo crlf +@msg loading profiles from disk isn't available in the browser načítání profilů z disku není v prohlížeči dostupné +@msg localize: the first argument must be a localization object or a string localize: první argument musí být lokalizační objekt nebo řetězec +@msg margin: a {m} pt margin leaves no imageable area on the paper okraj: okraj {m} pt nenechá na papíře žádnou tisknutelnou plochu +@msg matrix must be finite and invertible, depth finite matrix musí být konečná a invertovatelná, depth konečná +@msg matte: {e} matte: {e} +@msg member is for order front, forward, backward or back member se používá s order front, forward, backward nebo back +@msg missing `artboards` chybí `artboards` +@msg missing `at` [x, y] chybí `at` [x, y] +@msg missing `attrs` chybí `attrs` +@msg missing `color` or `opacity` chybí `color` nebo `opacity` +@msg missing `colors` chybí `colors` +@msg missing `commands` chybí `commands` +@msg missing `destinationFolder` chybí `destinationFolder` +@msg missing `effect` id chybí ID `effect` +@msg missing `family` chybí `family` +@msg missing `find` chybí `find` +@msg missing `gid` (a glyph id, or null for the default glyph) chybí `gid` (ID glyfu, nebo null pro výchozí glyf) +@msg missing `group` chybí `group` +@msg missing `id` chybí `id` +@msg missing `id`: give one, or select one type object chybí `id`: zadejte ho, nebo vyberte jeden textový objekt +@msg missing `index` (a point index, or null to clear) chybí `index` (index bodu, nebo null pro vymazání) +@msg missing `index` (a stop index, or null to clear) chybí `index` (index zarážky, nebo null pro vymazání) +@msg missing `index` (an item index or null) chybí `index` (index položky nebo null) +@msg missing `item` chybí `item` +@msg missing `library` chybí `library` +@msg missing `library` (see graphicStyle.libraries) chybí `library` (viz graphicStyle.libraries) +@msg missing `library` (see swatch.library.list) chybí `library` (viz swatch.library.list) +@msg missing `map` (rows [{from, to}] or {current}) chybí `map` (řádky [{from, to}] nebo {current}) +@msg missing `matrix` [a,b,c,d,e,f] chybí `matrix` [a,b,c,d,e,f] +@msg missing `name` (see gradient.presets.list) chybí `name` (viz gradient.presets.list) +@msg missing `offset` (a distance in points) chybí `offset` (vzdálenost v bodech) +@msg missing `path` chybí `path` +@msg missing `path` (a path object id) chybí `path` (ID objektu cesty) +@msg missing `picks` chybí `picks` +@msg missing `rule` chybí `rule` +@msg missing `source` id chybí ID `source` +@msg missing `start` (the byte offset of a character) chybí `start` (bajtový posun znaku) +@msg missing `status`: linked, embedded, missing or modified chybí `status`: linked, embedded, missing nebo modified +@msg missing `target` id chybí ID `target` +@msg missing `text` chybí `text` +@msg missing `to` chybí `to` +@msg missing `to` (an index) chybí `to` (index) +@msg missing `to`: a non-negative integer chybí `to`: nezáporné celé číslo +@msg missing `type` chybí `type` +@msg missing `value` chybí `value` +@msg missing `word` chybí `word` +@msg missing `{key}` chybí `{key}` +@msg missing `{k}` chybí `{k}` +@msg missing anchor chybí kotevní bod +@msg missing anchors chybí kotevní body +@msg missing anchors [[subpath, anchor]…] chybí kotevní body [[dílčí cesta, kotevní bod]…] +@msg missing array `{key}` chybí pole `{key}` +@msg missing case chybí case +@msg missing color chybí barva +@msg missing commands chybí příkazy +@msg missing destination folder chybí cílová složka +@msg missing from chybí from +@msg missing group chybí skupina +@msg missing id or ids chybí id nebo ids +@msg missing ids chybí ids +@msg missing indexes chybí indexes +@msg missing matrix [a,b,c,d,e,f] chybí matrix [a,b,c,d,e,f] +@msg missing name chybí název +@msg missing op chybí op +@msg missing or invalid `color` chybějící nebo neplatné `color` +@msg missing or unknown `tool` chybějící nebo neznámé `tool` +@msg missing point chybí bod +@msg missing point [x,y] chybí bod [x,y] +@msg missing point `{key}` ([x, y]) chybí bod `{key}` ([x, y]) +@msg missing points chybí body +@msg missing points [[x,y]…] chybí body [[x,y]…] +@msg missing segment chybí segment +@msg missing stops chybí zarážky +@msg missing subpaths chybí dílčí cesty +@msg missing target chybí cíl +@msg missing to chybí to +@msg missing x, y chybí x, y +@msg mode is set, add or toggle, not `{other}` mode je set, add nebo toggle, ne `{other}` +@msg mode must be "cmyk" or "rgb" mode musí být "cmyk" nebo "rgb" +@msg mode must be area|onPath, got {o} mode musí být area|onPath, zadáno {o} +@msg more than 10000 linked files: package dependencies in smaller parts více než 10000 propojených souborů: zabalte závislosti po menších částech +@msg more than 256 commands více než 256 příkazů +@msg more than {MAX_BATCH_FILES} data sets více než {MAX_BATCH_FILES} sad dat +@msg more than {MAX_BATCH_FILES} files více než {MAX_BATCH_FILES} souborů +@msg more than {MAX_CSV_ROWS} data rows více než {MAX_CSV_ROWS} řádků dat +@msg more than {MAX_FILES} images více než {MAX_FILES} obrázků +@msg more than {MAX_IMPORT} presets více než {MAX_IMPORT} přednastavení +@msg moved must be [[x,y]…] moved musí být [[x,y]…] +@msg must be an object with `kind` and `value` musí být objekt s `kind` a `value` +@msg must have `kind` alert, confirm or prompt musí mít `kind` alert, confirm nebo prompt +@msg must have exactly `kind` and `value` musí mít právě `kind` a `value` +@msg name (a toolbar's name) is required name (název panelu nástrojů) je povinné +@msg name (a toolbar's name) must be a string name (název panelu nástrojů) musí být řetězec +@msg name must be a toolbar's name name musí být název panelu nástrojů +@msg names is empty names je prázdné +@msg names must be an array of symbol names names musí být pole názvů symbolů +@msg need `anchor` or `segment` + `t` je potřeba `anchor` nebo `segment` + `t` +@msg need at least one anchor je potřeba alespoň jeden kotevní bod +@msg need at least one point je potřeba alespoň jeden bod +@msg need at least two points jsou potřeba alespoň dva body +@msg needs a closing quote after the name vyžaduje za názvem uzavírací uvozovku +@msg needs a name vyžaduje název +@msg needs a name of at most 64 bytes vyžaduje název o nejvýše 64 bajtech +@msg needs a name of letters, digits and _, or a quoted name vyžaduje název z písmen, číslic a _, nebo název v uvozovkách +@msg needs a name without control characters vyžaduje název bez řídicích znaků +@msg needs points vyžaduje body +@msg nesting too deep příliš hluboké vnoření +@msg nineSlice must be true or false nineSlice musí být true nebo false +@msg nineSliceGuides must be [left, top, right, bottom], each -16..16, with left + right < 1 and top + bottom < 1 nineSliceGuides musí být [left, top, right, bottom], každá hodnota -16..16, přičemž left + right < 1 a top + bottom < 1 +@msg no HP-GL format žádný formát HP-GL +@msg no New Document profile called `{shown}` ({_1}) žádný profil nového dokumentu se nejmenuje `{shown}` ({_1}) +@msg no PDF preset named `{n}` přednastavení PDF s názvem `{n}` neexistuje +@msg no SVG filter at index {k} na indexu {k} není žádný filtr SVG +@msg no action set is current žádná sada akcí není aktuální +@msg no active data set žádná aktivní sada dat +@msg no appearance item {index} položka vzhledu {index} neexistuje +@msg no arrowheads file here zde není žádný soubor šipek +@msg no artboard {_1} pracovní plocha {_1} neexistuje +@msg no artboard {artboard} (0-based; the document has {_1}) pracovní plocha {artboard} neexistuje (počítáno od 0; dokument jich má {_1}) +@msg no asset {id} prvek {id} neexistuje +@msg no asset {id} (see assets.list) prvek {id} neexistuje (viz assets.list) +@msg no assets to export žádné prvky k exportu +@msg no assets yet: collect art for export first (assets.add) zatím žádné prvky: nejprve shromážděte kresbu pro export (assets.add) +@msg no brush named `{n}` štětec s názvem `{n}` neexistuje +@msg no character at byte {start} na bajtu {start} není žádný znak +@msg no character has code {code} žádný znak nemá kód {code} +@msg no colour žádná barva +@msg no colour group `{group}` skupina barev `{group}` neexistuje +@msg no colour group `{name}` skupina barev `{name}` neexistuje +@msg no custom arrowhead {name} (see stroke.arrowheads.list) vlastní šipka {name} neexistuje (viz stroke.arrowheads.list) +@msg no data sets žádné sady dat +@msg no dataset named `{from}` sada dat s názvem `{from}` neexistuje +@msg no dataset named `{name}` sada dat s názvem `{name}` neexistuje +@msg no datasets žádné sady dat +@msg no design named `{name}` návrh s názvem `{name}` neexistuje +@msg no design named `{n}` návrh s názvem `{n}` neexistuje +@msg no design named `{old}` návrh s názvem `{old}` neexistuje +@msg no encoder for {_1} yet pro {_1} zatím není žádný kodér +@msg no export preset `{name}` (see document.exportPresets.list) přednastavení exportu `{name}` neexistuje (viz document.exportPresets.list) +@msg no file to open žádný soubor k otevření +@msg no folder: pass `path` or set Preferences › Plug-ins & Scratch Disks › Additional Plug-ins Folder žádná složka: předejte `path` nebo nastavte Předvolby › Zásuvné moduly a odkládací disky › Další složka zásuvných modulů +@msg no fonts to look for: they are all available žádná písma k hledání: všechna jsou dostupná +@msg no formats to export žádné formáty k exportu +@msg no gradient preset `{name}` (see gradient.presets.list) přednastavení přechodu `{name}` neexistuje (viz gradient.presets.list) +@msg no graphic style `{n}` in `{_1}` grafický styl `{n}` v `{_1}` neexistuje +@msg no graphic style library `{key}` (see graphicStyle.libraries) knihovna grafických stylů `{key}` neexistuje (viz graphicStyle.libraries) +@msg no guide selected není vybráno žádné vodítko +@msg no guide selected (or give an index) není vybráno žádné vodítko (nebo zadejte index) +@msg no guide {i} vodítko {i} neexistuje +@msg no images in the folder ve složce nejsou žádné obrázky +@msg no instructions žádné instrukce +@msg no item at index {_1} na indexu {_1} není žádná položka +@msg no item at index {from} na indexu {from} není žádná položka +@msg no item at one of the indices {idx} na některém z indexů {idx} není žádná položka +@msg no layer žádná vrstva +@msg no layer to rename žádná vrstva k přejmenování +@msg no layer {id} (see layer.list) vrstva {id} neexistuje (viz layer.list) +@msg no layers to export žádné vrstvy k exportu +@msg no library `{key}` knihovna `{key}` neexistuje +@msg no metafile format žádný formát metasouboru +@msg no object {_1} objekt {_1} neexistuje +@msg no objects žádné objekty +@msg no parent layer žádná nadřazená vrstva +@msg no perspective grid preset named `{b}` (see perspective.presets.list) přednastavení perspektivní mřížky s názvem `{b}` neexistuje (viz perspective.presets.list) +@msg no perspective grid preset named `{n}` přednastavení perspektivní mřížky s názvem `{n}` neexistuje +@msg no point selected (give `index`) není vybrán žádný bod (zadejte `index`) +@msg no preset called `{from}` (see file.newPresets) přednastavení s názvem `{from}` neexistuje (viz file.newPresets) +@msg no preset called `{name}` (see file.newPresets) přednastavení s názvem `{name}` neexistuje (viz file.newPresets) +@msg no preset named `{n}` přednastavení s názvem `{n}` neexistuje +@msg no print preset named `{b}` (see print.presets.list) přednastavení tisku s názvem `{b}` neexistuje (viz print.presets.list) +@msg no print preset named `{name}` (presets: {_1}) přednastavení tisku s názvem `{name}` neexistuje (přednastavení: {_1}) +@msg no print preset named `{n}` přednastavení tisku s názvem `{n}` neexistuje +@msg no profile named `{name}` profil s názvem `{name}` neexistuje +@msg no random numbers ({e}) náhodná čísla nejsou k dispozici ({e}) +@msg no readable files in the folder ve složce nejsou žádné čitelné soubory +@msg no recovery copy `{f}` (see file.recovery.list) záložní kopie `{f}` neexistuje (viz file.recovery.list) +@msg no rows žádné řádky +@msg no saved PDF preset named `{name}` uložené přednastavení PDF s názvem `{name}` neexistuje +@msg no saved export preset `{name}` uložené přednastavení exportu `{name}` neexistuje +@msg no saved gradient preset called {name} uložené přednastavení přechodu s názvem {name} neexistuje +@msg no saved gradient presets žádná uložená přednastavení přechodu +@msg no saved preset called `{name}` uložené přednastavení s názvem `{name}` neexistuje +@msg no saved presets to export (name [Default] in `names` to export it) žádná uložená přednastavení k exportu (chcete-li exportovat [Default], uveďte ho v `names`) +@msg no saved presets to export (name built-in ones in `names`) žádná uložená přednastavení k exportu (vestavěná uveďte v `names`) +@msg no saved print preset named `{name}` uložené přednastavení tisku s názvem `{name}` neexistuje +@msg no saved profile called {name} uložený profil s názvem {name} neexistuje +@msg no saved selection `{name}` uložený výběr `{name}` neexistuje +@msg no saved theme called {name} (see colorTheme.list) uložený motiv s názvem {name} neexistuje (viz colorTheme.list) +@msg no saved views žádná uložená zobrazení +@msg no selected or given object has a visible 3D effect žádný vybraný ani zadaný objekt nemá viditelný 3D efekt +@msg no series {i} řada {i} neexistuje +@msg no slice {n} in the image (see slice.list) řez {n} v obrazu neexistuje (viz slice.list) +@msg no source art žádná zdrojová kresba +@msg no stop {i} (the gradient has {n}) zarážka {i} neexistuje (přechod jich má {n}) +@msg no style `{name}` styl `{name}` neexistuje +@msg no such artboard {v} taková pracovní plocha neexistuje: {v} +@msg no such assets (see assets.list) takové prvky neexistují (viz assets.list) +@msg no such frame anchor, or the frame would reach past the canvas takový kotevní bod rámce neexistuje, nebo by rámec přesáhl plátno +@msg no such objects takové objekty neexistují +@msg no such path anchor, or the path would reach past the canvas takový kotevní bod cesty neexistuje, nebo by cesta přesáhla plátno +@msg no such rows takové řádky neexistují +@msg no swatch `{keep}` položka vzorníku `{keep}` neexistuje +@msg no swatch `{n}` položka vzorníku `{n}` neexistuje +@msg no swatch `{n}` (swatches and colour groups move separately) položka vzorníku `{n}` neexistuje (položky vzorníku a skupiny barev se přesouvají zvlášť) +@msg no swatch library `{key}` (see swatch.library.list) knihovna vzorníku `{key}` neexistuje (viz swatch.library.list) +@msg no swatch library `{key}` (see swatch.library.list; "document": the document's swatches) knihovna vzorníku `{key}` neexistuje (viz swatch.library.list; "document": vzorník dokumentu) +@msg no swatch library `{key}` (see swatch.library.list; "{DOCUMENT_SWATCHES}": the document's swatches) knihovna vzorníku `{key}` neexistuje (viz swatch.library.list; "{DOCUMENT_SWATCHES}": vzorník dokumentu) +@msg no swatch named `{n}` položka vzorníku s názvem `{n}` neexistuje +@msg no swatch or colour group `{n}` položka vzorníku ani skupina barev `{n}` neexistuje +@msg no swatch or colour group `{n}` in `{_1}` položka vzorníku ani skupina barev `{n}` v `{_1}` neexistuje +@msg no symbol named `{_1}` symbol s názvem `{_1}` neexistuje +@msg no symbol named `{name}` symbol s názvem `{name}` neexistuje +@msg no text objects selected nejsou vybrány žádné textové objekty +@msg no toolbar named `{_1}` panel nástrojů s názvem `{_1}` neexistuje +@msg no toolbar named `{name}` panel nástrojů s názvem `{name}` neexistuje +@msg no tracing preset `{preset}` (see imageTrace.presets) přednastavení vektorizace `{preset}` neexistuje (viz imageTrace.presets) +@msg no user library folder here (save with a path, or without one to get the data) zde není žádná složka uživatelských knihoven (uložte s cestou, nebo bez ní, chcete-li získat data) +@msg no variable named `{from}` proměnná s názvem `{from}` neexistuje +@msg no variable named `{name}` proměnná s názvem `{name}` neexistuje +@msg no variable named `{var}` proměnná s názvem `{var}` neexistuje +@msg no variable named `{v}` proměnná s názvem `{v}` neexistuje +@msg no view named `{name}` zobrazení s názvem `{name}` neexistuje +@msg node {_1} already has the text variable `{_2}` uzel {_1} už má textovou proměnnou `{_2}` +@msg node {_1} is not a graph uzel {_1} není graf +@msg node {_1} is not an image uzel {_1} není obraz +@msg node {_1} is not type uzel {_1} není text +@msg not a DCS file nejde o soubor DCS +@msg not a PDF presets file (format `{_1}`) nejde o soubor přednastavení PDF (formát `{_1}`) +@msg not a PDF presets file: {e} nejde o soubor přednastavení PDF: {e} +@msg not a RegExp object nejde o objekt RegExp +@msg not a Word document: its WordDocument stream doesn't start with a file information block nejde o dokument Word: jeho proud WordDocument nezačíná blokem informací o souboru +@msg not a Word document: its compound file has no WordDocument stream nejde o dokument Word: jeho složený soubor nemá proud WordDocument +@msg not a Word document: its main part is not a WordprocessingML document nejde o dokument Word: jeho hlavní část není dokument WordprocessingML +@msg not a Word document: its package has no main document part nejde o dokument Word: jeho balíček nemá hlavní část dokumentu +@msg not a closed path nejde o uzavřenou cestu +@msg not a flattener presets file (format `{_1}`) nejde o soubor přednastavení sloučení průhlednosti (formát `{_1}`) +@msg not a flattener presets file: {e} nejde o soubor přednastavení sloučení průhlednosti: {e} +@msg not a layer or group nejde o vrstvu ani skupinu +@msg not a library file: {e} nejde o soubor knihovny: {e} +@msg not a mesh envelope point nejde o bod síťové obálky +@msg not a perspective grid presets file (format `{_1}`) nejde o soubor přednastavení perspektivní mřížky (formát `{_1}`) +@msg not a perspective grid presets file: {e} nejde o soubor přednastavení perspektivní mřížky: {e} +@msg not a print presets file (format `{_1}`) nejde o soubor přednastavení tisku (formát `{_1}`) +@msg not a print presets file: {e} nejde o soubor přednastavení tisku: {e} +@msg not a regular expression nejde o regulární výraz +@msg not a stored or deflated central record nejde o uložený ani komprimovaný centrální záznam +@msg not a valid SVGZ file: {e} nejde o platný soubor SVGZ: {e} +@msg not an RTF file: it doesn't start with {\rtf nejde o soubor RTF: nezačíná na {\rtf +@msg not an action set: the text doesn't start with /version and a number nejde o sadu akcí: text nezačíná na /version a číslo +@msg not an image VectorCraft reads (see document.formats) nejde o obrázek, který VectorCraft čte (viz document.formats) +@msg not area type (text in a frame) outside perspective nejde o text v oblasti (text v rámci) mimo perspektivu +@msg not editing an opacity mask maska krytí se neupravuje +@msg not type on a path outside perspective nejde o text na cestě mimo perspektivu +@msg nothing prints nic se netiskne +@msg nothing to bind není co svázat +@msg nothing to change není co změnit +@msg nothing to change: give dx, dy, hScale, vScale or rotation není co změnit: zadejte dx, dy, hScale, vScale nebo rotation +@msg nothing to crop není co oříznout +@msg nothing to export není co exportovat +@msg nothing to export: the document has no visible art není co exportovat: dokument nemá žádnou viditelnou kresbu +@msg nothing to mark není co označit +@msg nothing to print: every artboard picked is blank není co tisknout: každá zvolená pracovní plocha je prázdná +@msg nothing to print: the document has no art that prints není co tisknout: dokument nemá žádnou kresbu, která se tiskne +@msg nothing to repeat není co opakovat +@msg numbers out of order in {_1} quantifier čísla v kvantifikátoru {_1} jsou ve špatném pořadí +@msg object is not a path objekt není cesta +@msg object transparency cannot be sampled onto highlighted characters; disable Transparency in Eyedropper Options or select the whole object průhlednost objektu nelze nabrat na zvýrazněné znaky; vypněte Průhlednost ve volbách kapátka nebo vyberte celý objekt +@msg object {_1} can't be set as point type objekt {_1} nelze nastavit jako bodový text +@msg object {_1} has lost its file's contents: relink it objekt {_1} ztratil obsah svého souboru: propojte ho znovu +@msg object {_1} has no path objekt {_1} nemá cestu +@msg object {_1} has no size objekt {_1} nemá velikost +@msg object {_1} is hidden or locked, or on a locked artboard objekt {_1} je skrytý nebo zamknutý, nebo je na zamknuté pracovní ploše +@msg object {_1} is not a placed document objekt {_1} není umístěný dokument +@msg object {_1} is not an Intertwine group objekt {_1} není skupina propletení +@msg object {_1} is not an image objekt {_1} není obraz +@msg object {_1} is not an image or a linked file objekt {_1} není obraz ani propojený soubor +@msg object {_1} is not an image or a placed document objekt {_1} není obraz ani umístěný dokument +@msg object {_1} is not in this Intertwine group objekt {_1} není v této skupině propletení +@msg object {_1} needs a 3D effect objekt {_1} vyžaduje 3D efekt +@msg object {_1} needs a 3D effect at index {index} objekt {_1} vyžaduje 3D efekt na indexu {index} +@msg object {_1}: a hollow Extrude & Bevel has no caps: turn on Cap to map a graphic objekt {_1}: duté Vysunutí a zkosení nemá zakončení: chcete-li mapovat grafiku, zapněte Zakončení +@msg object {_1}: with a depth of 0 the object has one face: map its graphics onto the front objekt {_1}: při hloubce 0 má objekt jednu plochu: mapujte jeho grafiku na přední stranu +@msg object {_1}: {_2} objekt {_1}: {_2} +@msg object {_1}: {e} objekt {_1}: {e} +@msg object {_1}: {name} at index {index} has no lighting presets; set its lights with effect.setParams objekt {_1}: {name} na indexu {index} nemá žádná přednastavení osvětlení; světla nastavte pomocí effect.setParams +@msg object {id} has anchors 0–{_1} for `corners`, not {past} objekt {id} má pro `corners` kotevní body 0–{_1}, ne {past} +@msg object {id} has {n} anchors, so no anchor {past} objekt {id} má {n} kotevních bodů, takže kotevní bod {past} neexistuje +@msg objects must be none, move or copy objects musí být none, move nebo copy +@msg objects were left out objekty byly vynechány +@msg offset out of range posun je mimo rozsah +@msg on must be true or false on musí být true nebo false +@msg only groups, layers, type and images have a Contents (Characters) row řádek Obsah (Znaky) mají jen skupiny, vrstvy, text a obrazy +@msg only interior mesh lines can be deleted odstranit lze jen vnitřní linie sítě +@msg only solid colours can be added (not gradients or patterns) přidat lze jen plné barvy (ne přechody ani vzorky) +@msg only solid-colour swatches can be spot colours přímými barvami mohou být jen položky vzorníku s plnou barvou +@msg only this Affinity file's embedded preview could be read: use File › Open to see it with its warning, or export SVG or PDF from Affinity first z tohoto souboru Affinity šlo přečíst jen vložený náhled: pomocí Soubor › Otevřít ho zobrazíte s varováním, nebo nejprve exportujte SVG či PDF z Affinity +@msg only this Affinity file's embedded preview could be read; use File › Open to see it with its warning z tohoto souboru Affinity šlo přečíst jen vložený náhled; pomocí Soubor › Otevřít ho zobrazíte s varováním +@msg onto, above, below, icon and a column place belong to window.panel.float and window.panel.dock onto, above, below, icon a umístění ve sloupci patří k window.panel.float a window.panel.dock +@msg onto, above, below, icon and a column place take no anchor, side, zone or before onto, above, below, icon a umístění ve sloupci nepřijímají anchor, side, zone ani before +@msg onto, above, below, icon and a column place take no x, y, width or height onto, above, below, icon a umístění ve sloupci nepřijímají x, y, width ani height +@msg opacity must be a number opacity musí být číslo +@msg open a document to look for its linked files otevřete dokument, jehož propojené soubory se mají hledat +@msg operand too large operand je příliš velký +@msg options must be an object (see file.formatOptions) options musí být objekt (viz file.formatOptions) +@msg order is a whole number from 0 to {others}, not `{v}` order je celé číslo od 0 do {others}, ne `{v}` +@msg order must be leftToRight or rightToLeft order musí být leftToRight nebo rightToLeft +@msg orientation must be portrait or landscape, not `{o}` orientation musí být portrait nebo landscape, ne `{o}` +@msg outlineText {v}: true or false outlineText {v}: true nebo false +@msg output intent profile: {e} profil výstupního záměru: {e} +@msg output.destination: no RGB or CMYK profile is called “{name}” output.destination: žádný profil RGB ani CMYK se nejmenuje „{name}“ +@msg output.destination: {_1} files are CMYK, and “{name}” is an RGB profile output.destination: soubory {_1} jsou CMYK a „{name}“ je profil RGB +@msg output.destination: {e} output.destination: {e} +@msg output.inks: no ink is set to print output.inks: žádná tisková barva není nastavena k tisku +@msg output.outputIntent: no profile is called “{name}”, and a {std} output intent embeds its profile output.outputIntent: žádný profil se nejmenuje „{name}“ a výstupní záměr {std} svůj profil vkládá +@msg output.outputIntent: no profile is called “{name}”: a {std} output intent embeds a profile, or names a registered printing condition (outputConditionId and registry) output.outputIntent: žádný profil se nejmenuje „{name}“: výstupní záměr {std} profil vkládá, nebo uvádí registrovanou tiskovou podmínku (outputConditionId a registry) +@msg output.outputIntent: {std} files print in CMYK, and “{name}” is an RGB profile output.outputIntent: soubory {std} se tisknou v CMYK a „{name}“ je profil RGB +@msg output.outputIntent: “{name}” is a grey profile, which can't be a {std} output intent output.outputIntent: „{name}“ je profil odstínů šedi, který nemůže být výstupním záměrem {std} +@msg overlap: {o} pt is half a tile or more překrytí: {o} pt je polovina dlaždice nebo více +@msg overlapping Shaper paths must be in the same layer or group překrývající se cesty Shaper musí být ve stejné vrstvě nebo skupině +@msg overlapping edits překrývající se úpravy +@msg page art conflicts with image data for {key} kresba stránky je v rozporu s obrazovými daty pro {key} +@msg page art conflicts with pattern {name} kresba stránky je v rozporu se vzorkem {name} +@msg page art conflicts with swatch {name} kresba stránky je v rozporu s položkou vzorníku {name} +@msg page art is missing image data for {key} kresbě stránky chybí obrazová data pro {key} +@msg page art is missing pattern {name} kresbě stránky chybí vzorek {name} +@msg page art is missing swatch {name} kresbě stránky chybí položka vzorníku {name} +@msg page must be a whole number from 1 page musí být celé číslo od 1 +@msg page thumbnail: {e} miniatura stránky: {e} +@msg page {page} of the PDF has no objects stránka {page} dokumentu PDF nemá žádné objekty +@msg page {page}: `{file}` has {n} {artboards} stránka {page}: `{file}` má {n} {artboards} +@msg page {page}: `{name}` has {n} {pages} stránka {page}: `{name}` má {n} {pages} +@msg pages must be a range such as "2-3" or a page number, not {v} pages musí být rozsah jako "2-3" nebo číslo stránky, ne {v} +@msg pages: {e} pages: {e} +@msg panel position must be finite pozice panelu musí být konečná +@msg parameters must be an object parametry musí být objekt +@msg params must be an object params musí být objekt +@msg passwords can have up to {MAX_PASSWORD} bytes hesla mohou mít nejvýše {MAX_PASSWORD} bajtů +@msg path chunks must share their boundary point úseky cesty musí sdílet svůj hraniční bod +@msg path has no open end cesta nemá žádný otevřený konec +@msg paths must be strings paths musí být řetězce +@msg pdfCompatible: false needs every artboard to keep the editable artwork pdfCompatible: false vyžaduje všechny pracovní plochy, aby se zachovala upravitelná kresba +@msg pdfCompatible: false needs the artboards to keep the editable artwork when useArtboards is false pdfCompatible: false vyžaduje pracovní plochy, aby se zachovala upravitelná kresba, když je useArtboards false +@msg pdfs `{m}`: single or multiple pdfs `{m}`: single nebo multiple +@msg pickColorFrom is "artwork" or "swatches", not {v} pickColorFrom je "artwork" nebo "swatches", ne {v} +@msg pins and moved must be non-empty lists of the same length pins a moved musí být neprázdné seznamy stejné délky +@msg pins must be [[x,y]…] pins musí být [[x,y]…] +@msg pins must be finite pins musí být konečné +@msg place is above, below or inside, not `{other}` place je above, below nebo inside, ne `{other}` +@msg plane must be left|right|ground plane musí být left|right|ground +@msg plane must be left|right|ground|none plane musí být left|right|ground|none +@msg point is outside the mesh bod je mimo síť +@msg point x must be a number x bodu musí být číslo +@msg point y must be a number y bodu musí být číslo +@msg points must be [t, left, right] with non-negative widths points musí být [t, left, right] s nezápornými šířkami +@msg points must be [x,y] pairs points musí být dvojice [x,y] +@msg points must be a non-empty [[x,y,pressure?]…] list points musí být neprázdný seznam [[x,y,pressure?]…] +@msg points must be a non-empty list of finite [x,y] points musí být neprázdný seznam konečných [x,y] +@msg points must be an array or null points musí být pole nebo null +@msg points must be finite points musí být konečné +@msg points must be finite [x,y] pairs points musí být konečné dvojice [x,y] +@msg points must be finite canvas points points musí být konečné body plátna +@msg points must contain 1–4096 coordinates points musí obsahovat 1–4096 souřadnic +@msg position must be normal, superscript or subscript position musí být normal, superscript nebo subscript +@msg position must be topLeft, topRight, bottomLeft or bottomRight position musí být topLeft, topRight, bottomLeft nebo bottomRight +@msg positions must be between 0 and 100000 pt positions musí být mezi 0 a 100000 pt +@msg ppi must be a positive number, not {ppi} ppi musí být kladné číslo, ne {ppi} +@msg ppi must be between 1 and 2400 ppi musí být mezi 1 a 2400 +@msg preserve `{v}` is not transforms|bounds|fileDimensions|fit|fill preserve `{v}` není transforms|bounds|fileDimensions|fit|fill +@msg preserveShape must be clippingMask|transparency preserveShape musí být clippingMask|transparency +@msg preset `{id}`: mobile or density přednastavení `{id}`: mobile nebo density +@msg preset must be standard, diffuse, topLeft or right preset musí být standard, diffuse, topLeft nebo right +@msg preset must be the name of a print preset preset musí být název přednastavení tisku +@msg previewMode must be default, pixel or overprint previewMode musí být default, pixel nebo overprint +@msg print settings: {e} nastavení tisku: {e} +@msg procedures nest too deeply procedury jsou vnořeny příliš hluboko +@msg procedures nested too deeply procedury byly vnořeny příliš hluboko +@msg quotes must be {double?, single?} quotes musí být {double?, single?} +@msg quotes.{k} must be an opening and a closing quote, e.g. "“”" quotes.{k} musí být otevírací a uzavírací uvozovka, např. "“”" +@msg range out of order in character class rozsah ve třídě znaků je ve špatném pořadí +@msg rasterEffectsPpi must be 1–2400 (72 screen, 150 medium, 300 high) rasterEffectsPpi musí být 1–2400 (72 obrazovka, 150 střední, 300 vysoké) +@msg rating must be a whole number from 0 to {MAX_RATING} rating musí být celé číslo od 0 do {MAX_RATING} +@msg rect and {k} contradict each other: give the area or the artboards rect a {k} si odporují: zadejte oblast, nebo pracovní plochy +@msg rect applies to raster formats, not {_1} rect platí pro rastrové formáty, ne pro {_1} +@msg rect is [x, y, width, height] in points rect je [x, y, width, height] v bodech +@msg rect must be [x, y, width, height] rect musí být [x, y, width, height] +@msg rect must be [x, y, width, height] with a positive width and height rect musí být [x, y, width, height] s kladnou šířkou a výškou +@msg rect needs finite numbers and a positive width and height rect vyžaduje konečná čísla a kladnou šířku a výšku +@msg redraw needs id redraw vyžaduje id +@msg redraw within must be a finite distance of 0 or more within v redraw musí být konečná vzdálenost 0 nebo větší +@msg reduce of an empty array with no initial value reduce prázdného pole bez počáteční hodnoty +@msg registration must be 0..8 registration musí být 0..8 +@msg regular expression flag '{_1}' given twice příznak regulárního výrazu '{_1}' je zadán dvakrát +@msg release a layer or a group uvolněte vrstvu nebo skupinu +@msg replace keeps the replaced object's place and transform: drop template, at and rect replace zachová umístění a transformaci nahrazeného objektu: vynechte template, at a rect +@msg replace: select the one object to replace replace: vyberte jeden objekt, který se má nahradit +@msg resolution must be a number or screen|medium|high resolution musí být číslo nebo screen|medium|high +@msg resolution must be between 1 and 2400 ppi resolution musí být mezi 1 a 2400 ppi +@msg rotation must be a number of degrees rotation musí být počet stupňů +@msg rotation must be finite rotation musí být konečné +@msg rows and cols must be 1..50 rows a cols musí být 1..50 +@msg rows and columns must be 1..500 rows a columns musí být 1..500 +@msg rows of objects whose appearances differ can't be reordered together řádky objektů s odlišným vzhledem nelze přeskupovat společně +@msg sampled text would exceed the canvas (coordinates out of range) nabraný text by přesáhl plátno (souřadnice mimo rozsah) +@msg save the document first: Package collects a saved document nejprve dokument uložte: Balíček shromažďuje uložený dokument +@msg save the document first: copy puts the file in its folder nejprve dokument uložte: copy vloží soubor do jeho složky +@msg savedPreset: {e} savedPreset: {e} +@msg scale `{s}`: a factor such as 2x, a width (100w), a height (100h) or a resolution (72ppi) scale `{s}`: násobek jako 2x, šířka (100w), výška (100h) nebo rozlišení (72ppi) +@msg scale must be a number above 0, at most 64 scale musí být číslo větší než 0, nejvýše 64 +@msg scale must be non-zero scale nesmí být nula +@msg scope must be selection or all (got {other}) scope musí být selection nebo all (zadáno {other}) +@msg scribble is too long čmáranice je příliš dlouhá +@msg segment does not exist segment neexistuje +@msg select a Shaper group vyberte skupinu Shaper +@msg select a blend to set easing or color shift vyberte prolnutí, u kterého se má nastavit náběh nebo posun barev +@msg select a compound shape vyberte složený tvar +@msg select a graph vyberte graf +@msg select a group or layer with visible, unlocked members vyberte skupinu nebo vrstvu s viditelnými odemknutými členy +@msg select a layer vyberte vrstvu +@msg select a text object vyberte textový objekt +@msg select an SVG filter vyberte filtr SVG +@msg select an image (or an Image Trace group) vyberte obraz (nebo skupinu vektorizace obrazu) +@msg select an image, or pass id vyberte obraz, nebo předejte id +@msg select an object (or pass `id`) vyberte objekt (nebo předejte `id`) +@msg select an object with a 3D effect vyberte objekt s 3D efektem +@msg select an object with a 3D effect, or give its id in ids vyberte objekt s 3D efektem, nebo zadejte jeho ID v ids +@msg select an object with a freeform gradient vyberte objekt s volným přechodem +@msg select an object with an opacity mask vyberte objekt s maskou krytí +@msg select area type vyberte text v oblasti +@msg select area type (text in a frame) vyberte text v oblasti (text v rámci) +@msg select area type and closed paths (at least one area type object) vyberte text v oblasti a uzavřené cesty (alespoň jeden objekt textu v oblasti) +@msg select area type whose first line can fit its frame vyberte text v oblasti, jehož první řádek se vejde do rámce +@msg select artwork to add its colours vyberte kresbu, jejíž barvy se mají přidat +@msg select artwork to make a group of its colours vyberte kresbu, z jejíchž barev se má vytvořit skupina +@msg select artwork to recolour, or give a colour `group` vyberte kresbu k přebarvení, nebo zadejte skupinu barev v `group` +@msg select exactly two path ends to join vyberte právě dva konce cest ke spojení +@msg select members of a compound shape vyberte členy složeného tvaru +@msg select objects or give ids vyberte objekty nebo zadejte ids +@msg select objects to align to the guide vyberte objekty, které se mají zarovnat k vodítku +@msg select one Intertwine group vyberte jednu skupinu propletení +@msg select one image or pass id vyberte jeden obraz nebo předejte id +@msg select one layer, group or object to rename vyberte jednu vrstvu, skupinu nebo objekt k přejmenování +@msg select paths vyberte cesty +@msg select paths or compound paths vyberte cesty nebo složené cesty +@msg select rows or objects to collect vyberte řádky nebo objekty ke shromáždění +@msg select something to export vyberte něco k exportu +@msg select something to export (or turn off selectedOnly) vyberte něco k exportu (nebo vypněte selectedOnly) +@msg select text to redefine the style from vyberte text, podle kterého se má styl předefinovat +@msg select the art and, on top of it, the mask object vyberte kresbu a nad ní objekt masky +@msg select the art for the design vyberte kresbu pro návrh +@msg select the art for the pattern tile vyberte kresbu pro dlaždici vzorku +@msg select the art to add first nejprve vyberte kresbu, která se má přidat +@msg select the art to collect (or give its ids) vyberte kresbu ke shromáždění (nebo zadejte její ids) +@msg select the art to weed vyberte kresbu pro vybírání +@msg select the content and a path on top vyberte obsah a cestu nad ním +@msg select the images to relink, or pass ids vyberte obrazy k novému propojení, nebo předejte ids +@msg select the images, or pass ids vyberte obrazy, nebo předejte ids +@msg select the linked images or placed documents, or pass ids vyberte propojené obrazy nebo umístěné dokumenty, nebo předejte ids +@msg select the object to copy from vyberte objekt, ze kterého se má kopírovat +@msg select the objects (or give their ids) vyberte objekty (nebo zadejte jejich ids) +@msg select the objects to attach to the path vyberte objekty, které se mají připojit k cestě +@msg select the objects to bind vyberte objekty, které se mají svázat +@msg select two or more objects to intertwine vyberte dva nebo více objektů k propletení +@msg select two or more slices to combine vyberte dva nebo více řezů ke spojení +@msg select type on a path vyberte text na cestě +@msg select type on a path or area type vyberte text na cestě nebo text v oblasti +@msg selection `{m}`: one or each selection `{m}`: one nebo each +@msg settings is an object of document.exportForScreens params settings je objekt s parametry document.exportForScreens +@msg settings must be an object settings musí být objekt +@msg show `{show}`: all, missing, modified or embedded show `{show}`: all, missing, modified nebo embedded +@msg show must be true or false show musí být true nebo false +@msg side is left or right, not `{v}` side je left nebo right, ne `{v}` +@msg size must be "small", "medium", "large" or a number of points over 0 up to {_1} size musí být "small", "medium", "large" nebo počet bodů větší než 0 a nejvýše {_1} +@msg size must be positive size musí být kladné +@msg sizeMode is "fixed" or "pressure", not `{other}` sizeMode je "fixed" nebo "pressure", ne `{other}` +@msg sizeMode is "fixed" or "pressure", not {other} sizeMode je "fixed" nebo "pressure", ne {other} +@msg sizeVariation must be 0 or more sizeVariation musí být 0 nebo více +@msg smallCaps must be true or false smallCaps musí být true nebo false +@msg sort `{x}`: name, kind or status sort `{x}`: name, kind nebo status +@msg source paths are too large for Shaper zdrojové cesty jsou pro Shaper příliš velké +@msg source text transform is collapsed or unrepresentable transformace zdrojového textu je zborcená nebo ji nelze vyjádřit +@msg spot, mode and group apply to solid colours only spot, mode a group platí jen pro plné barvy +@msg status `{s}`: linked, embedded, missing or modified status `{s}`: linked, embedded, missing nebo modified +@msg steps must be 1..1000 steps musí být 1..1000 +@msg steps must be 1..{MAX_STEPS} steps musí být 1..{MAX_STEPS} +@msg stop {i}: `plates` must be four numbers from 0 to 1 (C, M, Y, K) zarážka {i}: `plates` musí být čtyři čísla od 0 do 1 (C, M, Y, K) +@msg stopped before the archive was finished zastaveno před dokončením archivu +@msg strokeMode must be within|along|across, got {m} strokeMode musí být within|along|across, zadáno {m} +@msg strokeOptions must be an object of stroke.set options strokeOptions musí být objekt s volbami stroke.set +@msg strokeWidth must be a positive number of pixels strokeWidth musí být kladný počet obrazových bodů +@msg subpath {si} is not an open subpath dílčí cesta {si} není otevřená dílčí cesta +@msg subpaths required when joining the same path při spojování téže cesty je vyžadováno subpaths +@msg swatchConflict must be "merge" or "add", not {v} swatchConflict musí být "merge" nebo "add", ne {v} +@msg table must be true or false table musí být true nebo false +@msg takes one name přijímá jeden název +@msg target text transform is collapsed or unrepresentable transformace cílového textu je zborcená nebo ji nelze vyjádřit +@msg text must be {characterSet?, platform?, removeLineReturns?, removeParagraphReturns?, replaceSpaces?} text musí být {characterSet?, platform?, removeLineReturns?, removeParagraphReturns?, replaceSpaces?} +@msg text transform is collapsed or unrepresentable transformace textu je zborcená nebo ji nelze vyjádřit +@msg text.replaceSpaces must be a whole number from 2 to 100 text.replaceSpaces musí být celé číslo od 2 do 100 +@msg text.{key} `{v}`: use "{_1}" or "{_2}" text.{key} `{v}`: použijte "{_1}" nebo "{_2}" +@msg textureImage: give {path} or {name, dataBase64} of an image file, or a texture as effect.list gives it textureImage: zadejte {path} nebo {name, dataBase64} souboru obrázku, nebo texturu tak, jak ji vrací effect.list +@msg textureImage: {e} textureImage: {e} +@msg that makes more than {MAX_PIECES} slices tím vznikne více než {MAX_PIECES} řezů +@msg that makes too many pieces (at most 100000) or dash steps: simplify the dash pattern or make the dashes longer tím vznikne příliš mnoho dílů (nejvýše 100000) nebo kroků čárkování: zjednodušte vzor čárkování nebo prodlužte čárky +@msg that object is not in the overlap tento objekt není v překryvu +@msg the Affinity document has no page with a size dokument Affinity nemá žádnou stránku s velikostí +@msg the CMYK image couldn't be written obraz CMYK nešlo zapsat +@msg the Layers panel is not shown panel Vrstvy není zobrazen +@msg the Layers panel's search, filter or Show Layers Only hides its row jeho řádek skrývá hledání, filtr nebo volba Zobrazit pouze vrstvy v panelu Vrstvy +@msg the Objects on Path group is hidden or locked skupina Objekty na cestě je skrytá nebo zamknutá +@msg the PDF security settings were saved without their passwords: give openPassword or permissionsPassword again, or security without passwordRequired to export unprotected nastavení zabezpečení PDF bylo uloženo bez hesel: zadejte znovu openPassword nebo permissionsPassword, nebo pro export bez ochrany zadejte security bez passwordRequired +@msg the RTF file has too many paragraphs or formatting changes to place as type (at most {MAX_PARAGRAPHS} paragraphs and {MAX_RUNS} runs) soubor RTF má příliš mnoho odstavců nebo změn formátování na umístění jako text (nejvýše {MAX_PARAGRAPHS} odstavců a {MAX_RUNS} úseků) +@msg the RTF file is too large to place as type (at most {_1} MB) soubor RTF je příliš velký na umístění jako text (nejvýše {_1} MB) +@msg the SVG expands to more than {0} nested SVG images SVG se rozvine na více než {0} vnořených obrázků SVG +@msg the SVG expands to more than {0} objects SVG se rozvine na více než {0} objektů +@msg the SVG file is larger than {MAX_IMPORT_BYTES} bytes soubor SVG je větší než {MAX_IMPORT_BYTES} bajtů +@msg the SVG has no drawable objects SVG nemá žádné vykreslitelné objekty +@msg the SVGZ file unpacks to more than {_1} MB soubor SVGZ se rozbalí na více než {_1} MB +@msg the Word document has more than {MAX_PAGES} pages of properties, too many to place dokument Word má více než {MAX_PAGES} stránek vlastností, což je na umístění příliš mnoho +@msg the Word document has more than {MAX_RUNS} runs of character or paragraph properties, too many to place dokument Word má více než {MAX_RUNS} úseků vlastností znaků nebo odstavců, což je na umístění příliš mnoho +@msg the Word document has more than {_1} MB of formatting properties, too many to place dokument Word má více než {_1} MB vlastností formátování, což je na umístění příliš mnoho +@msg the Word document has too much text or formatting to place as type (at most {MAX_PARAGRAPHS} paragraphs, {MAX_RUNS} runs and {_1} MB of text) dokument Word má příliš mnoho textu nebo formátování na umístění jako text (nejvýše {MAX_PARAGRAPHS} odstavců, {MAX_RUNS} úseků a {_1} MB textu) +@msg the Word document has too much text to place as type (at most {_1} MB) dokument Word má příliš mnoho textu na umístění jako text (nejvýše {_1} MB) +@msg the Word document is encrypted or protected with a password; save it without one to place it dokument Word je zašifrovaný nebo chráněný heslem; chcete-li ho umístit, uložte ho bez hesla +@msg the Word document is too large to place (its {name} stream holds more than {_1} MB) dokument Word je příliš velký na umístění (jeho proud {name} obsahuje více než {_1} MB) +@msg the Word document was last saved with fast save, which VectorCraft doesn't read; save it again with fast save turned off dokument Word byl naposledy uložen rychlým ukládáním, které VectorCraft nečte; uložte ho znovu s vypnutým rychlým ukládáním +@msg the Word document was saved by Word 6.0 or Word 95, which VectorCraft doesn't read; save it as a Word 97-2003 document dokument Word byl uložen ve Wordu 6.0 nebo Wordu 95, což VectorCraft nečte; uložte ho jako dokument Word 97-2003 +@msg the Word document's text is made of more than {MAX_PIECES} pieces, too many to place text dokumentu Word se skládá z více než {MAX_PIECES} částí, což je na umístění příliš mnoho +@msg the XML operation needs an XML or XMLList value operace XML vyžaduje hodnotu XML nebo XMLList +@msg the XPath expression does not evaluate to a node-set výraz XPath se nevyhodnotí na množinu uzlů +@msg the XPath expression ends early výraz XPath končí předčasně +@msg the XPath expression has an unmatched ) výraz XPath obsahuje nespárovanou ) +@msg the XPath expression has an unmatched ] výraz XPath obsahuje nespárovanou ] +@msg the XPath expression has an unmatched closing bracket výraz XPath obsahuje nespárovanou uzavírací závorku +@msg the XPath expression selects a namespace node, which is not an XML value výraz XPath vybírá uzel jmenného prostoru, což není hodnota XML +@msg the XPath expression selects the root node, which is not an XML value výraz XPath vybírá kořenový uzel, což není hodnota XML +@msg the XPath function {name} needs a node-set funkce XPath {name} vyžaduje množinu uzlů +@msg the XPath function {name} takes the wrong number of arguments funkce XPath {name} dostala nesprávný počet argumentů +@msg the XPath name functions need a node-set funkce XPath pro názvy vyžadují množinu uzlů +@msg the XPath prefix {shown} is not bound to a namespace předpona XPath {shown} není svázána se jmenným prostorem +@msg the XPath variable ${shown} is not bound proměnná XPath ${shown} není svázána +@msg the action set ids are not a list ID sad akcí nejsou seznam +@msg the active paint is not a gradient aktivní nátěr není přechod +@msg the argument list is not an object seznam argumentů není objekt +@msg the artboards don't fit on the canvas: fewer artboards, less spacing or a smaller size pracovní plochy se nevejdou na plátno: zvolte méně pracovních ploch, menší rozestup nebo menší velikost +@msg the artwork is too large for EPS: what follows 256 MB of PostScript was left out kresba je pro EPS příliš velká: vše, co následuje po 256 MB PostScriptu, bylo vynecháno +@msg the bitmaps hold more pixels than one file may bitmapy obsahují více obrazových bodů, než smí mít jeden soubor +@msg the character's size can't be measured velikost znaku nelze změřit +@msg the code runs past its last instruction kód běží za svou poslední instrukci +@msg the compound shape is too complex to expand složený tvar je příliš složitý na rozložení +@msg the container of the listed objects is gone kontejner uvedených objektů už neexistuje +@msg the copy `{user_id}` can't be read as a library kopii `{user_id}` nelze přečíst jako knihovnu +@msg the copy would leave the canvas kopie by opustila plátno +@msg the curve tolerance must be from 0.01 to 10 points tolerance křivky musí být od 0.01 do 10 bodů +@msg the custom dictionary couldn't be saved to {_1}: {e} vlastní slovník nešlo uložit do {_1}: {e} +@msg the custom dictionary {_1} can't be read ({why}), so it is left as it is vlastní slovník {_1} nelze přečíst ({why}), proto zůstává beze změny +@msg the cut cannot be made on this art: {e} řez na této kresbě nelze provést: {e} +@msg the data isn't an EMF or WMF picture data nejsou obrázek EMF ani WMF +@msg the data isn't an EPS or PostScript picture data nejsou obrázek EPS ani PostScript +@msg the deferred paste is no longer available odložené vložení už není dostupné +@msg the design is too big to draw at every data point of this graph návrh je příliš velký na vykreslení v každém datovém bodě tohoto grafu +@msg the design is too big to draw in every column of this graph návrh je příliš velký na vykreslení v každém sloupci tohoto grafu +@msg the dialog it was opened over is no longer open dialog, nad kterým byl otevřen, už není otevřený +@msg the dictionary stack overflowed zásobník slovníků přetekl +@msg the document already has an SVG filter named {name} dokument už má filtr SVG s názvem {name} +@msg the document has another SVG filter named {name}: use svgFilter.apply, or svgFilter.define with `replace` to edit it dokument má jiný filtr SVG s názvem {name}: použijte svgFilter.apply, nebo ho upravte pomocí svgFilter.define s `replace` +@msg the document has no SVG filter named {name} dokument nemá žádný filtr SVG s názvem {name} +@msg the document has no SVG filter named {r} dokument nemá žádný filtr SVG s názvem {r} +@msg the document has no color swatches dokument nemá žádné barevné položky vzorníku +@msg the document's swatches hold {_1} colors; the document reduction takes at most 255 vzorník dokumentu obsahuje {_1} barev; redukce podle dokumentu jich přijímá nejvýše 255 +@msg the editing data's hash has no place pro hash dat pro úpravy není místo +@msg the entities the document declares expand to too much text entity, které dokument deklaruje, se rozvinou na příliš mnoho textu +@msg the envelope's content has no bounds obsah obálky nemá hranice +@msg the envelope's mesh is malformed síť obálky je poškozená +@msg the file holds no `variableSets` element soubor neobsahuje žádný prvek `variableSets` +@msg the file is larger than {_1} MB soubor je větší než {_1} MB +@msg the file is too large soubor je příliš velký +@msg the file isn't valid SVG: {e} soubor není platné SVG: {e} +@msg the file names no plate soubor neuvádí žádný výtažek +@msg the file was updated or encrypted already soubor už byl aktualizován nebo zašifrován +@msg the first character of a line has no character before it to kern: it moves only up and down (dy) první znak řádku nemá před sebou znak, vůči kterému by se vyrovnával: posouvá se jen nahoru a dolů (dy) +@msg the font {_1} is not available písmo {_1} není dostupné +@msg the format has no file extension formát nemá příponu souboru +@msg the function's prototype is not an object prototyp funkce není objekt +@msg the graphic can't be read: {e} grafiku nelze přečíst: {e} +@msg the graphic is empty grafika je prázdná +@msg the graphic's data is damaged data grafiky jsou poškozená +@msg the graphic's document has no artboard dokument grafiky nemá žádnou pracovní plochu +@msg the guide is hidden or locked vodítko je skryté nebo zamknuté +@msg the header `{cell}` for `{name}` would read back as the variable `{other}`: rename one of them záhlaví `{cell}` pro `{name}` by se zpětně načetlo jako proměnná `{other}`: jednu z nich přejmenujte +@msg the image `{path}` isn't followed: {r} obrázek `{path}` se nenačítá: {r} +@msg the image has no embedded pixels obraz nemá žádné vložené obrazové body +@msg the image is empty obraz je prázdný +@msg the image is fully transparent obraz je zcela průhledný +@msg the image is not on an artboard; pass rect obraz není na pracovní ploše; předejte rect +@msg the image's pixels are missing chybí obrazové body obrazu +@msg the image's pixels aren't in the document obrazové body obrazu nejsou v dokumentu +@msg the image's pixels can't be read: {e} obrazové body obrazu nelze přečíst: {e} +@msg the image's transparency doesn't fit it průhlednost obrazu k němu nepasuje +@msg the job would print more than {MAX_PAGES} pages úloha by vytiskla více než {MAX_PAGES} stránek +@msg the job would print more than {_1} pages úloha by vytiskla více než {_1} stránek +@msg the layers hold no art to mask vrstvy neobsahují žádnou kresbu k maskování +@msg the layout moved rozvržení se posunulo +@msg the library has a group `{name}` already knihovna už má skupinu `{name}` +@msg the library has no group `{name}` knihovna nemá skupinu `{name}` +@msg the library has no item `{item}` knihovna nemá položku `{item}` +@msg the library has no item `{other}` knihovna nemá položku `{other}` +@msg the library holds {MAX_GROUPS} groups already knihovna už obsahuje {MAX_GROUPS} skupin +@msg the library holds {MAX_ITEMS} items of this kind already knihovna už obsahuje {MAX_ITEMS} položek tohoto druhu +@msg the library's file is outside the read roots soubor knihovny je mimo kořenové složky pro čtení +@msg the line is too long, or the paths it passes too many, to check čára je příliš dlouhá, nebo prochází přes příliš mnoho cest, takže ji nelze zkontrolovat +@msg the method needs an XML value metoda vyžaduje hodnotu XML +@msg the name is empty název je prázdný +@msg the object has no fill, stroke or effect objekt nemá výplň, tah ani efekt +@msg the object has no graphic style (pass `name`) objekt nemá grafický styl (předejte `name`) +@msg the objects don't match the plan objekty neodpovídají plánu +@msg the open and permissions passwords must differ heslo pro otevření a heslo pro oprávnění se musí lišit +@msg the operand stack overflowed zásobník operandů přetekl +@msg the page has no area stránka nemá plochu +@msg the page's type in an unread object's box isn't in its page art text stránky v rámečku nepřečteného objektu není v kresbě jeho stránky +@msg the paint behind the proxy is not a gradient nátěr za aktivním políčkem není přechod +@msg the paint is not a freeform gradient (apply one with paint.editGradient {kind}) nátěr není volný přechod (použijte ho pomocí paint.editGradient {kind}) +@msg the parameters or body do not form one function parametry nebo tělo netvoří jednu funkci +@msg the parent must be a layer or sublayer nadřazený prvek musí být vrstva nebo podvrstva +@msg the pasted SVG filter {name} draws differently from the document's filter of that name, and no free name fits it vložený filtr SVG {name} se vykresluje jinak než filtr dokumentu s tímto názvem a nehodí se pro něj žádný volný název +@msg the path can't be extended cestu nelze prodloužit +@msg the path can't be inside one of the objects to attach cesta nemůže být uvnitř některého z připojovaných objektů +@msg the path has no segments to measure cesta nemá žádné segmenty k měření +@msg the path is empty cesta je prázdná +@msg the path is too short to shorten that much cesta je příliš krátká na takové zkrácení +@msg the paths are too many or too tangled to find where they cross cest je příliš mnoho nebo jsou příliš zamotané, takže nelze najít, kde se kříží +@msg the pen table holds more than 255 pens tabulka per obsahuje více než 255 per +@msg the picture has no objects obrázek nemá žádné objekty +@msg the plates can't be kept výtažky nelze zachovat +@msg the position table does not match the instructions tabulka pozic neodpovídá instrukcím +@msg the program runs too long program běží příliš dlouho +@msg the program uses too much memory program používá příliš mnoho paměti +@msg the prompt's text is longer than {MAX_PROMPT_BYTES} bytes text výzvy je delší než {MAX_PROMPT_BYTES} bajtů +@msg the radix must be between 2 and 36 základ soustavy musí být mezi 2 a 36 +@msg the rectangle must have a width and a height obdélník musí mít šířku a výšku +@msg the rectangle needs a size and must lie on the canvas obdélník potřebuje velikost a musí ležet na plátně +@msg the rectangle or line reaches too many paths to check obdélník nebo čára zasahuje příliš mnoho cest, takže je nelze zkontrolovat +@msg the right side of 'in' is not an object pravá strana operátoru 'in' není objekt +@msg the right side of 'instanceof' is not a function pravá strana operátoru 'instanceof' není funkce +@msg the selected art has no width vybraná kresba nemá šířku +@msg the selected art is nested more than {MAX_DEPTH} levels deep vybraná kresba je vnořena hlouběji než {MAX_DEPTH} úrovní +@msg the selected art is too large to measure vybraná kresba je příliš velká na změření +@msg the selection draws nothing výběr nic nevykresluje +@msg the selection has no area výběr nemá plochu +@msg the selection has no art to export výběr nemá žádnou kresbu k exportu +@msg the selection has no bounds výběr nemá hranice +@msg the selection has no graphic style výběr nemá grafický styl +@msg the selection has no outlines to weed around výběr nemá žádné obrysy, kolem kterých by šlo vybírat +@msg the slice would leave the canvas řez by opustil plátno +@msg the spot colour couldn't be added přímou barvu nešlo přidat +@msg the subpath has no ends to extend (it is closed or a single point) dílčí cesta nemá konce k prodloužení (je uzavřená nebo je to jediný bod) +@msg the symbols are nested too deeply to expand their instances symboly jsou vnořeny příliš hluboko na rozložení jejich instancí +@msg the text file is too large to place as type (at most {_1} MB) textový soubor je příliš velký na umístění jako text (nejvýše {_1} MB) +@msg the text is empty text je prázdný +@msg the text is over {_1} MB text má více než {_1} MB +@msg the top object must be a path horní objekt musí být cesta +@msg the trace was cancelled vektorizace byla zrušena +@msg the trailer has no size zakončení nemá velikost +@msg the type object is flattened to nothing textový objekt se sloučením změní v nic +@msg the value bind was called on is not a function hodnota, na které byla zavolána bind, není funkce +@msg the value is not a constructor hodnota není konstruktor +@msg the value is not a function hodnota není funkce +@msg the value is not a valid XML name hodnota není platný název XML +@msg the value is not an XML attribute name hodnota není název atributu XML +@msg the value is not an XML name hodnota není název XML +@msg the value of axis `{tag}` must be a number or null hodnota osy `{tag}` musí být číslo nebo null +@msg the variable library declares more than {MAX_LIBRARY_DATASETS} data sets knihovna proměnných deklaruje více než {MAX_LIBRARY_DATASETS} sad dat +@msg the variable library declares more than {MAX_LIBRARY_ENTITIES} entities knihovna proměnných deklaruje více než {MAX_LIBRARY_ENTITIES} entit +@msg the variable library declares more than {MAX_LIBRARY_VARIABLES} variables knihovna proměnných deklaruje více než {MAX_LIBRARY_VARIABLES} proměnných +@msg the variable library declares no variables knihovna proměnných nedeklaruje žádné proměnné +@msg the variable library is larger than {MAX_LIBRARY_BYTES} bytes knihovna proměnných je větší než {MAX_LIBRARY_BYTES} bajtů +@msg the variable library is not UTF-8 knihovna proměnných není v UTF-8 +@msg the variable library is not well-formed XML: {e} knihovna proměnných není správně utvořené XML: {e} +@msg the variable library nests elements more than {MAX_LIBRARY_NESTING} deep knihovna proměnných vnořuje prvky hlouběji než {MAX_LIBRARY_NESTING} úrovní +@msg the variable library's document type declaration holds something other than entities of plain text deklarace typu dokumentu knihovny proměnných obsahuje něco jiného než entity s prostým textem +@msg the variable library's entities expand to more than {MAX_LIBRARY_BYTES} bytes entity knihovny proměnných se rozvinou na více než {MAX_LIBRARY_BYTES} bajtů +@msg the weeding lines cross the art's outlines too many times to measure; use fewer lines linie pro vybírání kříží obrysy kresby tolikrát, že je nelze změřit; použijte méně linií +@msg the weeding lines pass too close to too many outline segments to measure; use fewer lines or a smaller gap linie pro vybírání procházejí příliš blízko příliš mnoha segmentů obrysu, takže je nelze změřit; použijte méně linií nebo menší mezeru +@msg the weeding lines would be more than {max_pieces} pieces linie pro vybírání by tvořily více než {max_pieces} dílů +@msg the window has no dock okno nemá žádný dok +@msg the written PDF has no catalog zapsané PDF nemá katalog +@msg the written PDF has no cross-reference table zapsané PDF nemá tabulku křížových odkazů +@msg the written PDF's metadata can't be edited metadata zapsaného PDF nelze upravit +@msg the {_1} plate lies outside the file výtažek {_1} leží mimo soubor +@msg there are no colour swatches to draw nejsou žádné barevné položky vzorníku k vykreslení +@msg there is already a design named `{name}` návrh s názvem `{name}` už existuje +@msg there is already a design named `{to}` návrh s názvem `{to}` už existuje +@msg there is already a toolbar named `{name}` panel nástrojů s názvem `{name}` už existuje +@msg there is already a toolbar named `{to}` panel nástrojů s názvem `{to}` už existuje +@msg there is no library: create one first žádná knihovna neexistuje: nejprve ji vytvořte +@msg these paths are too degenerate for Shaper tyto cesty jsou pro Shaper příliš degenerované +@msg this is a binary DXF file, which can't be read: save it from the CAD app as an ASCII DXF and open that toto je binární soubor DXF, který nelze přečíst: uložte ho z aplikace CAD jako ASCII DXF a otevřete ten +@msg this warp's points can't be edited: use Reset with Mesh first body této deformace nelze upravovat: nejprve použijte Obnovit se sítí +@msg thumbnail: no page {v} (the {what} has {count}) miniatura: stránka {v} neexistuje ({what} jich má {count}) +@msg tileRange of {what}: {e} tileRange pro {what}: {e} +@msg title can't be empty title nesmí být prázdné +@msg to (the new name) is required to (nový název) je povinné +@msg to must be fill or stroke to musí být fill nebo stroke +@msg to must be smooth or corner to musí být smooth nebo corner +@msg toExponential() digits must be between 0 and 20 počet číslic pro toExponential() musí být mezi 0 a 20 +@msg toFixed() digits must be between 0 and 20 počet číslic pro toFixed() musí být mezi 0 a 20 +@msg toISOString is not a function toISOString není funkce +@msg toPrecision() argument must be between 1 and 21 argument toPrecision() musí být mezi 1 a 21 +@msg toSource: a getter cannot be written as source toSource: getter nelze zapsat jako zdrojový kód +@msg toSource: an array with properties besides its elements, a property that is not enumerable or another prototype cannot be written as source toSource: pole s vlastnostmi mimo své prvky, s vlastností, která není výčtová, nebo s jiným prototypem nelze zapsat jako zdrojový kód +@msg toSource: an object with a property that is not enumerable, or whose prototype is not Object.prototype, cannot be written as source toSource: objekt s vlastností, která není výčtová, nebo jehož prototyp není Object.prototype, nelze zapsat jako zdrojový kód +@msg toSource: the source is too long toSource: zdrojový kód je příliš dlouhý +@msg toSource: the value contains itself toSource: hodnota obsahuje sama sebe +@msg toSource: the value has too many entries toSource: hodnota má příliš mnoho položek +@msg toSource: the value is nested too deep toSource: hodnota je vnořena příliš hluboko +@msg toString is not a function toString není funkce +@msg too large for a zip archive: package to a folder příliš velké pro archiv zip: zabalte do složky +@msg too many Shaper edits příliš mnoho úprav Shaper +@msg too many `points` (at most 100000) příliš mnoho `points` (nejvýše 100000) +@msg too many arguments příliš mnoho argumentů +@msg too many characters: at most {MAX_CHARS} příliš mnoho znaků: nejvýše {MAX_CHARS} +@msg too many dots for this size: lower the frequency příliš mnoho bodů pro tuto velikost: snižte frekvenci +@msg too many filters over one file příliš mnoho filtrů nad jedním souborem +@msg too many overlapping paths for Shaper příliš mnoho překrývajících se cest pro Shaper +@msg too many quantifiers příliš mnoho kvantifikátorů +@msg too many saved clips příliš mnoho uložených ořezů +@msg too many saved graphics states příliš mnoho uložených grafických stavů +@msg toolbar (a toolbar's name) must be a string toolbar (název panelu nástrojů) musí být řetězec +@msg toolbar name can't be empty název panelu nástrojů nesmí být prázdný +@msg transparentImages {v}: "flatten" (the default) or "omit" transparentImages {v}: "flatten" (výchozí) nebo "omit" +@msg two saved selections would be named `{_1}` dva uložené výběry by se jmenovaly `{_1}` +@msg type dimension cannot be represented with this text transform rozměr textu nelze vyjádřit touto transformací textu +@msg type dimension must be finite rozměr textu musí být konečný +@msg unexpected resources neočekávané prostředky +@msg unknown CMYK profile `{name}` neznámý profil CMYK `{name}` +@msg unknown File Info field `{k}` neznámé pole informací o souboru `{k}` +@msg unknown OpenType feature `{t}` (liga, calt, dlig, smcp, frac, onum, tnum, ordn, swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom, aalt; prefix - to turn off; swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom and aalt take an alternate's number as `tag=N` with N from 0 to {_1}, as `salt=2`) neznámá funkce OpenType `{t}` (liga, calt, dlig, smcp, frac, onum, tnum, ordn, swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom, aalt; předpona - funkci vypne; swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom a aalt přijímají číslo alternativy jako `tag=N` s N od 0 do {_1}, například `salt=2`) +@msg unknown OpenType feature `{t}` in featureChanges (the tags `features` takes) neznámá funkce OpenType `{t}` ve featureChanges (značky, které přijímá `features`) +@msg unknown PDF preset `{name}` (presets: {_1}) neznámé přednastavení PDF `{name}` (přednastavení: {_1}) +@msg unknown Warp style neznámý styl deformace +@msg unknown alignToPath `{a}` neznámé alignToPath `{a}` +@msg unknown arrowhead {v} neznámá šipka {v} +@msg unknown artboardLayout key `{k}` (layout, columns, spacing, rightToLeft) neznámý klíč artboardLayout `{k}` (layout, columns, spacing, rightToLeft) +@msg unknown attribute `{attribute}` neznámý atribut `{attribute}` +@msg unknown attribute `{k}` neznámý atribut `{k}` +@msg unknown axis `{other}` (vertical|horizontal|free) neznámá osa `{other}` (vertical|horizontal|free) +@msg unknown blend mode `{b}` neznámý režim míchání `{b}` +@msg unknown blend mode {b} neznámý režim míchání {b} +@msg unknown brush type `{o}` neznámý typ štětce `{o}` +@msg unknown category `{c}` neznámá kategorie `{c}` +@msg unknown category `{c}` ({_1}) neznámá kategorie `{c}` ({_1}) +@msg unknown character `{c}` neznámý znak `{c}` +@msg unknown character style number field neznámé číselné pole stylu znaků +@msg unknown dither `{d}` (diffusion, pattern, noise or none) neznámý rozklad barev `{d}` (diffusion, pattern, noise nebo none) +@msg unknown effect `{e}` neznámý efekt `{e}` +@msg unknown end {e} neznámý konec {e} +@msg unknown flattenerPreset `{name}` (High Resolution, Medium Resolution, Low Resolution or a saved one: see flattener.presets.list) neznámé flattenerPreset `{name}` (High Resolution, Medium Resolution, Low Resolution nebo uložené přednastavení: viz flattener.presets.list) +@msg unknown format `{f}` (vcswatches, gpl, ase or css) neznámý formát `{f}` (vcswatches, gpl, ase nebo css) +@msg unknown from {f} neznámé from {f} +@msg unknown graph type `{t}` neznámý typ grafu `{t}` +@msg unknown grid colours `{name}` (one of {_1}) neznámé barvy mřížky `{name}` (jedna z hodnot {_1}) +@msg unknown gridType `{t}` neznámé gridType `{t}` +@msg unknown highlight `{v}` neznámé zvýraznění `{v}` +@msg unknown intent `{i}` neznámý záměr `{i}` +@msg unknown issue kind {id} neznámý druh problému {id} +@msg unknown issue kind {v} neznámý druh problému {v} +@msg unknown knockout state {k} neznámý stav vykrojení {k} +@msg unknown language `{language}` (one of {_1}) neznámý jazyk `{language}` (jeden z {_1}) +@msg unknown language `{l}` (one of {_1}) neznámý jazyk `{l}` (jeden z {_1}) +@msg unknown method `{m}` ({_1}) neznámá metoda `{m}` ({_1}) +@msg unknown mode `{other}` (gray, rgb, hsb, lab, cmyk or web) neznámý režim `{other}` (gray, rgb, hsb, lab, cmyk nebo web) +@msg unknown mode `{other}` (mono|cmyk) neznámý režim `{other}` (mono|cmyk) +@msg unknown mode `{other}` (rgb|cmyk|gray|global) neznámý režim `{other}` (rgb|cmyk|gray|global) +@msg unknown mode `{other}` (set, add, subtract) neznámý režim `{other}` (set, add, subtract) +@msg unknown mode `{o}` neznámý režim `{o}` +@msg unknown mode {m} neznámý režim {m} +@msg unknown model `{other}` neznámý model `{other}` +@msg unknown model `{other}` (keep, new or document) neznámý model `{other}` (keep, new nebo document) +@msg unknown op {o} neznámé op {o} +@msg unknown order `{o}`: toggle, front, forward, backward or back neznámé pořadí `{o}`: toggle, front, forward, backward nebo back +@msg unknown overprints `{v}` (preserve, simulate or discard) neznámé overprints `{v}` (preserve, simulate nebo discard) +@msg unknown panel neznámý panel +@msg unknown panel `{panel}` neznámý panel `{panel}` +@msg unknown parameter `{key}` neznámý parametr `{key}` +@msg unknown parameter `{within}settings.{format}`; {why} neznámý parametr `{within}settings.{format}`; {why} +@msg unknown parameter `{within}{key}`; {why} neznámý parametr `{within}{key}`; {why} +@msg unknown pieLegend `{v}` (none, standard or wedges) neznámé pieLegend `{v}` (none, standard nebo wedges) +@msg unknown piePosition `{v}` (even, ratio or stacked) neznámé piePosition `{v}` (even, ratio nebo stacked) +@msg unknown pieSort `{v}` (none, all or first) neznámé pieSort `{v}` (none, all nebo first) +@msg unknown plate `{n}` neznámý výtažek `{n}` +@msg unknown preference `{k}` neznámá předvolba `{k}` +@msg unknown profile {id} (see stroke.widthProfile.list) neznámý profil {id} (viz stroke.widthProfile.list) +@msg unknown proof target `{t}` neznámý cíl nátisku `{t}` +@msg unknown quotes key `{k}` (double, single) neznámý klíč quotes `{k}` (double, single) +@msg unknown reduction `{reduction}` (selective, perceptual, adaptive, web, gray, blackWhite, uniform or document) neznámá redukce `{reduction}` (selective, perceptual, adaptive, web, gray, blackWhite, uniform nebo document) +@msg unknown resolution `{v}` neznámé rozlišení `{v}` +@msg unknown rule `{rule}` ({_1}) neznámé pravidlo `{rule}` ({_1}) +@msg unknown rule `{r}` (see color.harmony) neznámé pravidlo `{r}` (viz color.harmony) +@msg unknown setting `{k}` neznámé nastavení `{k}` +@msg unknown shape `{v}` (circle|ellipse|square|diamond|line) neznámý tvar `{v}` (circle|ellipse|square|diamond|line) +@msg unknown spacing `{o}` (smooth|steps|distance) neznámé rozestupy `{o}` (smooth|steps|distance) +@msg unknown tileType `{t}` ({_1}) neznámé tileType `{t}` ({_1}) +@msg unknown units neznámé jednotky +@msg unknown units `{u}` neznámé jednotky `{u}` +@msg unknown value axis `{v}` (left, right or both) neznámá osa hodnot `{v}` (left, right nebo both) +@msg unknown variation `{v}` (tintsShades|warmCool|vividMuted) neznámá variace `{v}` (tintsShades|warmCool|vividMuted) +@msg unknown warp style `{s}` neznámý styl deformace `{s}` +@msg unknown {key} `{v}` (none, short or full) neznámé {key} `{v}` (none, short nebo full) +@msg unknown {key} profile `{n}` neznámý profil {key} `{n}` +@msg unknown {k} key `{key}` (size, position) neznámý klíč {k} `{key}` (size, position) +@msg unmatched ')' nespárovaná ')' +@msg unreadable object nečitelný objekt +@msg unsafe destination file name nebezpečný název cílového souboru +@msg unterminated character class neukončená třída znaků +@msg unterminated group neukončená skupina +@msg use paths or compound paths použijte cesty nebo složené cesty +@msg useArtboards must be true or false, not {v} useArtboards musí být true nebo false, ne {v} +@msg value for `{var}` must match its variable kind hodnota pro `{var}` musí odpovídat druhu její proměnné +@msg variable `{_1}` is already defined proměnná `{_1}` je už definována +@msg variable `{name}` has no `trait` proměnná `{name}` nemá `trait` +@msg variable `{name}` is already defined proměnná `{name}` je už definována +@msg variable `{name}` is declared twice proměnná `{name}` je deklarována dvakrát +@msg variable `{to}` already exists proměnná `{to}` už existuje +@msg view is required view je povinné +@msg view must be one of {_1} view musí být jedna z hodnot {_1} +@msg warpStyle can only edit an applied Warp effect warpStyle může upravit jen použitý efekt Deformace +@msg width and height must be more than 0 and at most {limit} width a height musí být více než 0 a nejvýše {limit} +@msg width factors must be finite koeficienty šířky musí být konečné +@msg width must be positive width musí být kladné +@msg width out of range šířka je mimo rozsah +@msg width/height must be > 0 width/height musí být > 0 +@msg wordGap and lineGap need area type in the selection wordGap a lineGap vyžadují ve výběru text v oblasti +@msg x and y must be finite numbers x a y musí být konečná čísla +@msg x and y must be given together x a y je nutné zadat společně +@msg xpath needs its variables as an object xpath vyžaduje své proměnné jako objekt +@msg xpath needs the expression as a string xpath vyžaduje výraz jako řetězec +@msg zone needs an anchor: dock beside a panel with anchor, or in a new dock column with side (Start or End) zone vyžaduje kotvu: ukotvěte vedle panelu pomocí anchor, nebo do nového sloupce doku pomocí side (Start nebo End) +@msg zoom must be positive zoom musí být kladné +@msg {C}: no effect at index {list} {C}: na indexu {list} není žádný efekt +@msg {DEFAULT_PRESET} is protected and stays {DEFAULT_PRESET} je chráněné a zůstává +@msg {DEFAULT_PRESET} is protected: save the settings under another name {DEFAULT_PRESET} je chráněné: uložte nastavení pod jiným názvem +@msg {GRANT_NOT_REMOVED}, and its settings and cache can't be moved back from {_1} to {_2}: {e} {GRANT_NOT_REMOVED} a jeho nastavení a mezipaměť nelze přesunout zpět z {_1} do {_2}: {e} +@msg {LABEL} produced an empty result {LABEL} vytvořilo prázdný výsledek +@msg {_1} MB of document, at most {_2} MB {_1} MB dokumentu, nejvýše {_2} MB +@msg {_1} MB of images, at most {_2} MB {_1} MB obrázků, nejvýše {_2} MB +@msg {_1} bytes of RGBA data for a {width} × {height} image {_1} bajtů dat RGBA pro obraz {width} × {height} +@msg {_1} can't be read, or changed since it was read: relink or update it first {_1} nelze přečíst, nebo se od přečtení změnil: nejprve ho znovu propojte nebo aktualizujte +@msg {_1} can't go into {into} {_1} nelze vložit do {into} +@msg {_1} can't limit printing to low resolution: choose PDF 1.4 or later, or allow high-resolution printing {_1} nemůže omezit tisk na nízké rozlišení: zvolte PDF 1.4 nebo novější, nebo povolte tisk ve vysokém rozlišení +@msg {_1} files can't be opened yet soubory {_1} zatím nelze otevřít +@msg {_1} files can't be password-protected: remove the passwords or choose no standard soubory {_1} nelze chránit heslem: odeberte hesla nebo nezvolte žádný standard +@msg {_1} files can't be {_2} soubory {_1} nemohou být {_2} +@msg {_1} files can't carry editing data: turn off preserveEditing soubory {_1} nemohou obsahovat data pro úpravy: vypněte preserveEditing +@msg {_1} files can't have PDF layers: turn off createLayers soubory {_1} nemohou mít vrstvy PDF: vypněte createLayers +@msg {_1} files need a creation date, and this platform has no clock to give one soubory {_1} vyžadují datum vytvoření a tato platforma nemá hodiny, které by ho poskytly +@msg {_1} is not a folder: {e} {_1} není složka: {e} +@msg {_1} isn't a path {_1} není cesta +@msg {_1} options: {e} volby {_1}: {e} +@msg {_1} paints nothing to rasterize {_1} nevykresluje nic, co by šlo rastrovat +@msg {_1} passwords can have up to {MAX_LEGACY_PASSWORD} ASCII characters (PDF 1.7 and later take any) hesla {_1} mohou mít nejvýše {MAX_LEGACY_PASSWORD} znaků ASCII (PDF 1.7 a novější přijímají libovolné znaky) +@msg {_1} with linked images or an image map writes several files: use document.export {_1} s propojenými obrázky nebo obrazovou mapou zapisuje několik souborů: použijte document.export +@msg {_1} writes one file per artboard here: use document.export, or name one artboard {_1} zde zapisuje jeden soubor na každou pracovní plochu: použijte document.export, nebo uveďte jednu pracovní plochu +@msg {_1} × {_2} pixels is too large for {_3} (at most {max} pixels a side): lower the scale {_1} × {_2} obrazových bodů je pro {_3} příliš mnoho (nejvýše {max} obrazových bodů na stranu): zmenšete měřítko +@msg {_1}: belongs to another account {_1}: patří jinému účtu +@msg {_1}: not a folder of its own {_1}: nejde o jeho vlastní složku +@msg {_1}: not a plain file {_1}: nejde o obyčejný soubor +@msg {_1}: {_2} and {_3} are in the way {_1}: překáží {_2} a {_3} +@msg {code}: {0} {code}: {0} +@msg {dest}: {e} {dest}: {e} +@msg {dir}: {e} {dir}: {e} +@msg {doc} has no folder {doc} nemá složku +@msg {file} isn't linked {file} není propojený +@msg {file} names more than one linked JavaScript file {file} uvádí více než jeden propojený soubor JavaScript +@msg {folder} is not a package folder {folder} není složka balíčku +@msg {folder}: more than {max} files and folders {folder}: více než {max} souborů a složek +@msg {folder}: {e} {folder}: {e} +@msg {g} is not a Live Paint group {g} není skupina živé malby +@msg {id} is not a slice {id} není řez +@msg {key} must be 0–{MAX_ADD_AROUND} pt {key} musí být 0–{MAX_ADD_AROUND} pt +@msg {key} must be [x,y] {key} musí být [x,y] +@msg {key} must be a percentage {min}..100 {key} musí být procento {min}..100 +@msg {key} must be a positive number, not {n} {key} musí být kladné číslo, ne {n} +@msg {key} must be a positive number, not {v} {key} musí být kladné číslo, ne {v} +@msg {key} must be one of {_1} {key} musí být jedna z hodnot {_1} +@msg {key} must be {_1}, got {s} {key} musí být {_1}, zadáno {s} +@msg {key} must name a floating panel {key} musí uvádět plovoucí panel +@msg {key} must name a panel in another group {key} musí uvádět panel v jiné skupině +@msg {key} must name a panel that shows {key} musí uvádět panel, který je zobrazen +@msg {key} must name a registered panel {key} musí uvádět registrovaný panel +@msg {kind} files have no transparency, and the file would have {what}: flatten it first (object.flattenTransparency) soubory {kind} nemají průhlednost a soubor by obsahoval {what}: nejprve ji slučte (object.flattenTransparency) +@msg {kind} images can't be opened (see document.formats) obrázky {kind} nelze otevřít (viz document.formats) +@msg {k} `{v}` is not one of the choices {k} `{v}` není jedna z nabízených voleb +@msg {k} has control characters{_1} {k} obsahuje řídicí znaky{_1} +@msg {k} is too long (at most {MAX_TEXT} characters) {k} je příliš dlouhé (nejvýše {MAX_TEXT} znaků) +@msg {k} must be > 0 {k} musí být > 0 +@msg {k} must be a number (pt) or a length such as "210 mm" {k} musí být číslo (pt) nebo délka jako "210 mm" +@msg {k} must be a number from {min} to {max} {k} musí být číslo od {min} do {max} +@msg {k} must be a number or "auto" {k} musí být číslo nebo "auto" +@msg {k} must be a string {k} musí být řetězec +@msg {k} must be text {k} musí být text +@msg {k} must be true or false {k} musí být true nebo false +@msg {k} must be {{size?, position?}} {k} musí být {{size?, position?}} +@msg {k}: a custom arrowhead's path needs an area to fill and at most {most} anchors and {most} subpaths, each anchor within {far} head units of its tip {k}: cesta vlastní šipky potřebuje plochu k vyplnění a nejvýše {most} kotevních bodů a {most} dílčích cest, každý kotevní bod nejdále {far} jednotek hrotu od její špičky +@msg {k}: bad custom arrowhead path: {e} {k}: chybná cesta vlastní šipky: {e} +@msg {k}: bad custom arrowhead: {e} {k}: chybná vlastní šipka: {e} +@msg {k}: can't read `{s}` as a length {k}: `{s}` nelze přečíst jako délku +@msg {k}: custom must be a name {k}: custom musí být název +@msg {label} must be a number at most {max} {label} musí být číslo nejvýše {max} +@msg {label} must be a number from -1296 to 1296 {label} musí být číslo od -1296 do 1296 +@msg {label} must be a number from 1 to 10000 {label} musí být číslo od 1 do 10000 +@msg {name} `{s}`: {ids} {name} `{s}`: {ids} +@msg {name} is built in and can't be deleted {name} je vestavěné a nelze ho odstranit +@msg {name} must be a number {name} musí být číslo +@msg {name} must be {lo}–{hi}{unit} (got {v}) {name} musí být {lo}–{hi}{unit} (zadáno {v}) +@msg {name}: CRC or size mismatch {name}: nesouhlasí CRC nebo velikost +@msg {name}: only this Affinity file's embedded preview could be read; use File › Open to see it with its warning, or export SVG or PDF from Affinity before placing {name}: z tohoto souboru Affinity šlo přečíst jen vložený náhled; pomocí Soubor › Otevřít ho zobrazíte s varováním, nebo před umístěním exportujte SVG či PDF z Affinity +@msg {name}: {e} {name}: {e} +@msg {native}; its embedded preview can't be read either ({e}) {native}; jeho vložený náhled také nelze přečíst ({e}) +@msg {path}: copy takes a DCS file only when its plates are inside it; relink to it where its plate files are {path}: copy přijímá soubor DCS, jen když jsou jeho výtažky uvnitř něj; propojte ho znovu tam, kde jsou soubory jeho výtažků +@msg {path}: larger than {_1} MB {path}: větší než {_1} MB +@msg {shown} is not an XPath 1.0 function {shown} není funkce XPath 1.0 +@msg {std} files are CMYK, and the file would have colours in {_1} soubory {std} jsou CMYK a soubor by obsahoval barvy v {_1} +@msg {std} files embed their fonts, and the file would have one that isn't soubory {std} vkládají svá písma a soubor by obsahoval písmo, které vložené není +@msg {target} is the file this document was read from, and reading it left things out ({what}): writing over it would lose them for good. Write another file instead, or pass acknowledgeLoss: true to replace it anyway {target} je soubor, ze kterého byl tento dokument načten, a při čtení bylo něco vynecháno ({what}): přepsáním by se to nenávratně ztratilo. Zapište místo toho jiný soubor, nebo předejte acknowledgeLoss: true, chcete-li ho přesto nahradit +@msg {ty} brushes need selected art (or params.{k}) štětce typu {ty} vyžadují vybranou kresbu (nebo params.{k}) +@msg {v} is not an asset id {v} není ID prvku +@msg {v} names no layer or sublayer {v} neuvádí žádnou vrstvu ani podvrstvu +@msg {what} can't be intertwined {what} nelze proplést +@msg {what} doesn't fit the paper with its bleed and marks {what} se na papír se spadávkou a značkami nevejde +@msg {what} is not a function {what} není funkce +@msg {what} would print more than {MAX_COPIES_PER_SHEET} copies on a sheet: scale it up {what} by vytisklo více než {MAX_COPIES_PER_SHEET} kopií na arch: zvětšete měřítko +@msg {what} would print on more than {MAX_TILES} tiles: scale it down {what} by se vytisklo na více než {MAX_TILES} dlaždic: zmenšete měřítko +@msg {what} {i} out of range {what} {i} je mimo rozsah +@msg `{key}` must be from 0.01 to 1000 pt `{key}` musí být od 0.01 do 1000 pt +@msg select the banner, or mark every artboard vyberte banner, nebo označte každou pracovní plochu +@msg the banner has no width or height banner nemá šířku nebo výšku +@msg the grommet inset is too large for the banner odstup průchodek od okraje je pro banner příliš velký +@msg the hem is too deep for the banner lem je pro banner příliš hluboký +@msg the spacing makes more than {MAX_GROMMETS} grommets při tomto rozestupu vznikne více než {MAX_GROMMETS} průchodek +@msg there is no banner to mark není žádný banner k označení +@msg turn on at least one side zapněte alespoň jednu stranu +@msg with no hem and no grommets there is nothing to mark bez lemu a bez průchodek není co označit +@msg {saving} failed: {e} {saving} se nezdařilo: {e} diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index a0d987fe69..ec1178652c 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -7138,3 +7138,1818 @@ breakText Glyphs 字符 Grommets 扣眼 Grommet Inset 扣眼邊距 Diameter 直徑 + +# Status and error messages of commands, scripts, file import and export, and plug-ins. +@msg 'caller', 'callee' and 'arguments' cannot be used on strict mode functions 嚴格模式的函式不能使用 'caller'、'callee' 和 'arguments' +@msg Alignment must be one of the choices 對齊方式必須是選項之一 +@msg Boolean.prototype.{name} was called on a value that is not a Boolean 在不是 Boolean 的值上呼叫了 Boolean.prototype.{name} +@msg CMYK images whose samples couldn't be read in CMYK were imported in RGB 無法以 CMYK 讀取取樣的 CMYK 影像已以 RGB 匯入 +@msg Cannot write to the location of “{name}”; choose where to save it 無法寫入「{name}」的位置;請選擇儲存位置 +@msg DCS files can only be placed linked: use File › Place with Link on DCS 檔案只能以連結方式置入:請使用「檔案 › 置入」並開啟「連結」 +@msg Date.prototype method called on a value that is not a Date object 在不是 Date 物件的值上呼叫了 Date.prototype 方法 +@msg Error.prototype.toString was called on a value that is not an object 在不是物件的值上呼叫了 Error.prototype.toString +@msg Function.prototype.toString was called on a value that is not a function 在不是函式的值上呼叫了 Function.prototype.toString +@msg Import SVG Filter reads SVG files, not SVGZ 「匯入 SVG 濾鏡」讀取 SVG 檔案,不讀取 SVGZ +@msg JSON.parse: {why} (at offset {at}) JSON.parse:{why} (位於偏移 {at}) +@msg JSON.stringify cannot write a structure that contains itself JSON.stringify 無法寫入包含自身的結構 +@msg Line Gap must be a number 行間距必須是數字 +@msg Namespace.prototype.toString needs a Namespace Namespace.prototype.toString 需要 Namespace +@msg New Document profiles need the preferences folder, which this run doesn't have 新增文件描述檔需要偏好設定資料夾,而這次執行沒有該資料夾 +@msg Number.prototype.{name} was called on a value that is not a number 在不是數字的值上呼叫了 Number.prototype.{name} +@msg Object.create's prototype must be an object or null Object.create 的原型必須是物件或 null +@msg Object.{function} was given a value that is not an object Object.{function} 收到了不是物件的值 +@msg QName.prototype.toString needs a QName QName.prototype.toString 需要 QName +@msg RegExp.prototype.{name} was called on a value that is not a RegExp object 在不是 RegExp 物件的值上呼叫了 RegExp.prototype.{name} +@msg Stencil Bridges: the selected art is too large or too detailed to bridge 鏤空版連接橋:所選圖稿過大或過於細緻,無法建立連接橋 +@msg String.prototype.toString was called on a value that is not a string 在不是字串的值上呼叫了 String.prototype.toString +@msg The {name} profile could not be read, so the new document has the default settings: {reason} 無法讀取 {name} 描述檔,因此新文件使用預設設定:{reason} +@msg Trap: more than {_1} pairs of objects lie close enough to trap, or too many objects share a horizontal range; trap fewer objects at a time 補漏白:有超過 {_1} 對物件近到需要補漏白,或有太多物件位於相同的水平範圍;請一次對較少的物件補漏白 +@msg Weed Box and Lines: no weeding line fits outside the art, and the weed box is off 除廢框與除廢線:圖稿外側放不下任何除廢線,而且除廢框已關閉 +@msg \ at end of pattern \ 出現在模式結尾 +@msg `alignOn` cannot be empty `alignOn` 不能為空 +@msg `alignOn` must be a string `alignOn` 必須是字串 +@msg `align` must be a string `align` 必須是字串 +@msg `answer` for this {kind} dialog must be one of: {_1} 此 {kind} 對話框的 `answer` 必須是下列其中之一:{_1} +@msg `answers` has more than {MAX_ANSWERS} answers `answers` 的答案超過 {MAX_ANSWERS} 個 +@msg `answers` is larger than 1 MiB `answers` 大於 1 MiB +@msg `answers` must be a list of answers `answers` 必須是答案清單 +@msg `artboard` must be the index of an artboard of the document `artboard` 必須是文件中某個工作區域的索引 +@msg `artboardsAt` must be [x, y] `artboardsAt` 必須是 [x, y] +@msg `artboards` names an artboard the document does not have `artboards` 指定了文件中沒有的工作區域 +@msg `artboards` names an artboard twice `artboards` 將同一個工作區域指定了兩次 +@msg `at` must be [x, y] (got {at}) `at` 必須是 [x, y] (收到 {at}) +@msg `at` must be a point [x, y] `at` 必須是點 [x, y] +@msg `beside` needs `side` `beside` 需要 `side` +@msg `code` must be a whole number `code` 必須是整數 +@msg `colorMode` must be one of rgb, cmyk `colorMode` 必須是 rgb、cmyk 其中之一 +@msg `colors` does not apply to the {name} reduction `colors` 不適用於 {name} 縮減 +@msg `colors` must be a whole number from 2 to 256 `colors` 必須是 2 到 256 之間的整數 +@msg `colors` must be at least 9 for the uniform reduction 使用均勻縮減時,`colors` 至少必須是 9 +@msg `colors` must be between 1 and {MAX_THEME_COLORS} (got {n}) `colors` 必須介於 1 和 {MAX_THEME_COLORS} 之間 (收到 {n}) +@msg `count` must be a whole number from 0 to {MAX_COUNT} `count` 必須是 0 到 {MAX_COUNT} 之間的整數 +@msg `ditherAmount` must be a number from 0 to 100 `ditherAmount` 必須是 0 到 100 之間的數字 +@msg `fidelity` must be from {lo} to {hi} pt `fidelity` 必須介於 {lo} 到 {hi} pt 之間 +@msg `focal` and `radius` cannot be used together `focal` 和 `radius` 不能同時使用 +@msg `focal` must be an array of [subpath, anchor] pairs `focal` 必須是 [subpath, anchor] 配對的陣列 +@msg `focal` names [{si}, {ai}], which is not an anchor of the path `focal` 指定了 [{si}, {ai}],它不是該路徑的錨點 +@msg `glyphAlternate` takes only null, which takes a glyph choice away (text.setGlyphAlternate makes one) `glyphAlternate` 只接受 null,表示移除字符選擇 (text.setGlyphAlternate 可建立選擇) +@msg `group` must be one of {_1} `group` 必須是 {_1} 其中之一 +@msg `group` must be the Objects on Path group of `member` and `target` `group` 必須是 `member` 和 `target` 所屬的「路徑上的物件」群組 +@msg `id` is an object id, not {v} `id` 是物件 ID,而非 {v} +@msg `item` needs `index` `item` 需要 `index` +@msg `kerningBefore` belongs to a line's first character, not to a character style (text.setRangeStyle sets it) `kerningBefore` 屬於一行的第一個字元,不屬於字元樣式 (由 text.setRangeStyle 設定) +@msg `kinsokuType` must be "pushInFirst", "pushOutFirst" or "pushOutOnly" `kinsokuType` 必須是 "pushInFirst"、"pushOutFirst" 或 "pushOutOnly" +@msg `leader` must be a string `leader` 必須是字串 +@msg `max` must be 1 to {MAX_SUGGESTIONS} `max` 必須是 1 到 {MAX_SUGGESTIONS} +@msg `name` must be a name that is not empty `name` 必須是不為空的名稱 +@msg `name` must not be empty `name` 不能為空 +@msg `origin` must be [x, y] in points `origin` 必須是以點為單位的 [x, y] +@msg `picks` must be an array (got {v}) `picks` 必須是陣列 (收到 {v}) +@msg `picks` must hold 1 to {MAX_PICKS} picks (got {_1}) `picks` 必須包含 1 到 {MAX_PICKS} 個選擇 (收到 {_1}) +@msg `points` must hold from 2 to 100000 points `points` 必須包含 2 到 100000 個點 +@msg `radius` must be 0 or more `radius` 必須大於或等於 0 +@msg `rect` must be [x, y, width, height] `rect` 必須是 [x, y, width, height] +@msg `rect` must be [x0, y0, x1, y1] (got {r}) `rect` 必須是 [x0, y0, x1, y1] (收到 {r}) +@msg `replace` must be a string `replace` 必須是字串 +@msg `rows` must be lists of numbers or nulls, not {r} `rows` 必須是由數字或 null 組成的清單,而非 {r} +@msg `scale` must be a number from 0.001 to 1000 `scale` 必須是 0.001 到 1000 之間的數字 +@msg `scope.{key}` must be a non-empty array `scope.{key}` 必須是非空陣列 +@msg `scope` must be "document", {artboards} or {layers} `scope` 必須是 "document"、{artboards} 或 {layers} +@msg `side` must be "left", "right", "top" or "bottom" `side` 必須是 "left"、"right"、"top" 或 "bottom" +@msg `side` places the artboard: leave out x, y, width and height `side` 會決定工作區域的位置:請不要提供 x、y、width 和 height +@msg `source` is the only path in series group `target` `source` 是系列群組 `target` 中唯一的路徑 +@msg `spacing` makes more than {MAX_COUNT} lines across the box `spacing` 會在方框內產生超過 {MAX_COUNT} 條線 +@msg `spacing` must be more than 0 and at most {MAX_DISTANCE} pt `spacing` 必須大於 0 且不超過 {MAX_DISTANCE} pt +@msg `target` must be an object of the same Objects on Path group as `member` `target` 必須是與 `member` 屬於同一個「路徑上的物件」群組的物件 +@msg `tolerance` must be from 0 to 100 pt `tolerance` 必須介於 0 到 100 pt 之間 +@msg `version` must be 0 or {_1} `version` 必須是 0 或 {_1} +@msg `version` must be 0 or {newest} `version` 必須是 0 或 {newest} +@msg `warichuAlign` must be one of {_1} `warichuAlign` 必須是 {_1} 其中之一 +@msg `warichuLines` must be a whole number from {_1} to {_2} `warichuLines` 必須是 {_1} 到 {_2} 之間的整數 +@msg `weight` must be from 0.01 to 1000 pt `weight` 必須介於 0.01 到 1000 pt 之間 +@msg `weights` must be a list of {_1} numbers, one per row (got {v}) `weights` 必須是包含 {_1} 個數字的清單,每列一個 (收到 {v}) +@msg `xml` must be a string `xml` 必須是字串 +@msg `{KEY}` entry {n} gives the paragraph at byte {start} of {_1} other indents than an entry before it `{KEY}` 項目 {n} 為 {_1} 中位於位元組 {start} 的段落指定的縮排與先前的項目不同 +@msg `{KEY}` entry {n} must be an object `{KEY}` 項目 {n} 必須是物件 +@msg `{KEY}` entry {n} sets neither `leftIndent` nor `firstLineIndent` `{KEY}` 項目 {n} 既未設定 `leftIndent`,也未設定 `firstLineIndent` +@msg `{KEY}` entry {n}: `id` must be an object id `{KEY}` 項目 {n}:`id` 必須是物件 ID +@msg `{KEY}` entry {n}: `start` must be a byte offset `{KEY}` 項目 {n}:`start` 必須是位元組偏移 +@msg `{KEY}` entry {n}: `{k}` must be a number from -{MAX_PARA} to {MAX_PARA} pt `{KEY}` 項目 {n}:`{k}` 必須是 -{MAX_PARA} 到 {MAX_PARA} pt 之間的數字 +@msg `{KEY}` entry {n}: no paragraph of {_1} starts at byte {start} `{KEY}` 項目 {n}:{_1} 中沒有從位元組 {start} 開始的段落 +@msg `{KEY}` entry {n}: unknown key `{k}` `{KEY}` 項目 {n}:未知的鍵 `{k}` +@msg `{KEY}` entry {n}: {_1} is not a type object `{KEY}` 項目 {n}:{_1} 不是文字物件 +@msg `{KEY}` is empty `{KEY}` 為空 +@msg `{KEY}` must be a list `{KEY}` 必須是清單 +@msg `{KEY}` takes at most {MAX_PARAGRAPH_INDENTS} entries (got {_1}) `{KEY}` 最多接受 {MAX_PARAGRAPH_INDENTS} 個項目 (收到 {_1}) +@msg `{KEY}` takes no `{other}` beside it `{KEY}` 不能與 `{other}` 一起使用 +@msg `{base}` is larger than {_1} MB `{base}` 大於 {_1} MB +@msg `{base}` is not in the DCS file's folder `{base}` 不在 DCS 檔案的資料夾中 +@msg `{key}` holds more than {MAX_EDIT_WORDS} words `{key}` 包含超過 {MAX_EDIT_WORDS} 個單字 +@msg `{key}` must be 0 or more `{key}` 必須大於或等於 0 +@msg `{key}` must be [x, y] numbers `{key}` 必須是 [x, y] 數字 +@msg `{key}` must be a list of words `{key}` 必須是單字清單 +@msg `{key}` must be a list, not {v} `{key}` 必須是清單,而非 {v} +@msg `{key}` must be a number or null, not {v} `{key}` 必須是數字或 null,而非 {v} +@msg `{key}` must be a whole number of 0 or more `{key}` 必須是大於或等於 0 的整數 +@msg `{key}` must be from 0 to {MAX_DISTANCE} pt `{key}` 必須介於 0 到 {MAX_DISTANCE} pt 之間 +@msg `{key}` must be from 0.01 to 1000 pt `{key}` 必須介於 0.01 到 1000 pt 之間 +@msg `{key}` must be from {lo} to {hi}, not {v} `{key}` 必須介於 {lo} 到 {hi} 之間,而非 {v} +@msg `{key}` must be one of auto, always, never `{key}` 必須是 auto、always、never 其中之一 +@msg `{key}` must be one of miter, round, bevel `{key}` 必須是 miter、round、bevel 其中之一 +@msg `{key}` must be one word of at most {_1} characters `{key}` 必須是一個不超過 {_1} 個字元的單字 +@msg `{key}` must hold single words of at most {_1} characters `{key}` 中的每一項必須是不超過 {_1} 個字元的單字 +@msg `{key}` must name an object attached to the path of an Objects on Path group `{key}` 必須指定附加在「路徑上的物件」群組路徑上的物件 +@msg `{key}` names an object that is hidden or locked `{key}` 指定的物件已隱藏或鎖定 +@msg `{name}` is a file of its own, which can only be found next to the DCS file's path `{name}` 是獨立的檔案,只能在 DCS 檔案的路徑旁找到 +@msg `{name}`: {_1}: {e} `{name}`:{_1}:{e} +@msg `{u}` is no Unicode character `{u}` 不是 Unicode 字元 +@msg `{word}` isn't in the custom dictionary `{word}` 不在自訂字典中 +@msg a CMap has too many mappings CMap 的對應過多 +@msg a \u escape needs four hexadecimal digits \u 逸出序列需要四個十六進位數字 +@msg a comma in an XPath expression must separate function arguments XPath 運算式中的逗號必須用來分隔函式引數 +@msg a document holds at most {_1} SVG filters 一份文件最多包含 {_1} 個 SVG 濾鏡 +@msg a document with unsaved changes has no recovery copy 有未儲存變更的文件沒有復原副本 +@msg a font's data is too large 字體的資料過大 +@msg a font's subroutines are too large 字體的副程式過大 +@msg a function declaration without a name 函式宣告沒有名稱 +@msg a host value has too many entries 主機值的項目過多 +@msg a host value is nested too deep 主機值的巢狀層次過深 +@msg a namespace declaration uses a reserved prefix or URI 命名空間宣告使用了保留的前置詞或 URI +@msg a namespace qualifier is undefined 命名空間限定詞未定義 +@msg a namespace with an empty URI cannot have a prefix URI 為空的命名空間不能有前置詞 +@msg a number has no digits 數值中沒有數字 +@msg a number's exponent has no digits 數值的指數部分沒有數字 +@msg a number's fraction has no digits 數值的小數部分沒有數字 +@msg a property descriptor cannot have both a value or writable and a get or set 屬性描述元不能同時具有 value 或 writable,以及 get 或 set +@msg a property descriptor must be an object 屬性描述元必須是物件 +@msg a property's {name} must be a function or undefined 屬性的 {name} 必須是函式或 undefined +@msg a stream in it would decode to more than 256 MB, or its decode parameters can't be applied 其中有一個資料流解碼後會超過 256 MB,或無法套用其解碼參數 +@msg a string holds a control character 字串包含控制字元 +@msg a string holds an escape sequence JSON does not have 字串包含 JSON 沒有的逸出序列 +@msg a string is not closed 字串未結束 +@msg an SVG filter is named by its id: give `xml` with `name` SVG 濾鏡以其 id 作為名稱:請搭配 `name` 提供 `xml` +@msg an XML element has two attributes with the same name XML 元素有兩個同名的屬性 +@msg an XML value cannot be inserted into itself or its descendants XML 值不能插入其本身或其後代 +@msg an XML value's children cannot be assigned by position 不能依位置指定 XML 值的子項 +@msg an XML value's children cannot be deleted by position 不能依位置刪除 XML 值的子項 +@msg an XMLList converts to XML only when it has one item XMLList 只有在包含一個項目時才能轉換為 XML +@msg an XPath node test is missing XPath 運算式少了節點測試 +@msg an XPath operand is missing XPath 運算式少了運算元 +@msg an XPath operator is missing XPath 運算式少了運算子 +@msg an XPath predicate or step cannot follow here 這裡不能接 XPath 述詞或步驟 +@msg an XPath predicate or step follows a value that is not a node-set XPath 述詞或步驟接在不是節點集的值之後 +@msg an XPath step is missing XPath 運算式少了步驟 +@msg an image couldn't be decoded and is missing from the picture 有一個影像無法解碼,因此未出現在圖片中 +@msg an image of {w} × {h} pixels is too large to convert (at most {_1} pixels) {w} × {h} 像素的影像過大,無法轉換 (最多 {_1} 像素) +@msg apply was called on a value that is not a function 在不是函式的值上呼叫了 apply +@msg area type in a thread cannot use Dynamic Text: {frames} 串連文字中的區域文字無法使用動態文字:{frames} +@msg array literal too long 陣列常值過長 +@msg assignment to a constant binding 對常數繫結進行了指定 +@msg at least one row that isn't excluded needs a weight above 0 至少需要一個未排除的列具有大於 0 的權重 +@msg bad point {v}: expected [x, y] 無效的點 {v}:應為 [x, y] +@msg blend must be a mode name blend 必須是模式名稱 +@msg both sides of an XPath | must select nodes XPath | 的兩側都必須選取節點 +@msg canceled 已取消 +@msg cannot convert the object to a primitive value 無法將物件轉換為基本型別值 +@msg cannot convert undefined or null to an object 無法將 undefined 或 null 轉換為物件 +@msg character dimensions cannot be represented with the source text transform 字元尺寸無法以來源文字變形表示 +@msg character dimensions cannot be represented with the target text transform 字元尺寸無法以目標文字變形表示 +@msg continuation must be an array of path chunks continuation 必須是路徑片段的陣列 +@msg continuation requires points continuation 需要 points +@msg each path chunk must contain 1 to 4096 points 每個路徑片段必須包含 1 到 4096 個點 +@msg each pick is {{at: [x, y]}} or {{rect: [x0, y0, x1, y1]}} (got {v}) 每個選擇都是 {{at: [x, y]}} 或 {{rect: [x0, y0, x1, y1]}} (收到 {v}) +@msg each weight must be a number of 0 or more (got {v}) 每個權重必須是大於或等於 0 的數字 (收到 {v}) +@msg finally table {t} out of range finally 表格 {t} 超出範圍 +@msg flags cannot be given with a RegExp object 提供 RegExp 物件時不能再提供旗標 +@msg function declaration index out of range 函式宣告索引超出範圍 +@msg give `char`, `text`, `code` or `unicode` 請提供 `char`、`text`、`code` 或 `unicode` +@msg give `count` or `spacing`, not both 請提供 `count` 或 `spacing`,不要兩者都提供 +@msg give `name`, an SVG filter's name 請提供 `name`,即 SVG 濾鏡的名稱 +@msg give `path`, an SVG file, or `svg`, SVG text 請提供 `path` (SVG 檔案) 或 `svg` (SVG 文字) +@msg give `xml`, one SVG element 請提供 `xml`,即一個 SVG 元素 +@msg give exactly one of `at`, `rect` and `points` `at`、`rect` 和 `points` 請只提供其中一個 +@msg give exactly one of `path`, `data` and `dataBase64` `path`、`data` 和 `dataBase64` 請只提供其中一個 +@msg give index or indexes, not both 請提供 index 或 indexes,不要兩者都提供 +@msg give one element 請提供一個 元素 +@msg give opacity or blend 請提供 opacity 或 blend +@msg handler at {_1} expects {_2} values but its range starts with {d} 位於 {_1} 的處理常式預期有 {_2} 個值,但其範圍的起始深度為 {d} +@msg handler depth too large 處理常式深度過大 +@msg handler range {_1}..{_2} out of range 處理常式範圍 {_1}..{_2} 超出範圍 +@msg hiddenLayers must be true or false hiddenLayers 必須是 true 或 false +@msg hvcC hvcC +@msg images in a spot ink whose samples couldn't be read were imported in RGB 取樣無法讀取的特別色油墨影像已以 RGB 匯入 +@msg images past the most pixels one file may hold were left out 超過單一檔案像素上限的影像已略過 +@msg images too large to read were left out 過大而無法讀取的影像已略過 +@msg indexes may hold at most {MAX_GUIDE_INDEXES} entries indexes 最多可包含 {MAX_GUIDE_INDEXES} 個項目 +@msg indexes must be an array of guide indexes indexes 必須是參考線索引的陣列 +@msg instruction out of range 指令超出範圍 +@msg instruction {pc} ({op}) pops below the stack 指令 {pc} ({op}) 彈出的值超出堆疊底部 +@msg instruction {pc} reached with stack depths {seen} and {d} 到達指令 {pc} 時的堆疊深度有 {seen} 和 {d} 兩種 +@msg invalid array length 陣列長度無效 +@msg invalid group 群組無效 +@msg invalid object id {v}: expected a non-negative integer 物件 ID {v} 無效:應為非負整數 +@msg invalid regular expression flag '{_1}' 無效的正規表示式旗標 '{_1}' +@msg invalid regular expression: {m} 正規表示式無效:{m} +@msg invalid time value 時間值無效 +@msg is a confirm's answer, whose `value` must be true or false 是 confirm 的答案,其 `value` 必須是 true 或 false +@msg is a prompt's answer, whose `value` must be a string or null 是 prompt 的答案,其 `value` 必須是字串或 null +@msg is an alert's answer, whose `value` must be "ok" 是 alert 的答案,其 `value` 必須是 "ok" +@msg is longer than 16 KiB 長度超過 16 KiB +@msg it draws its image through a clipping path 它透過剪裁路徑繪製影像 +@msg it draws no image 它沒有繪製影像 +@msg it is larger than {MAX_DICTIONARY_FILE_BYTES} bytes 它大於 {MAX_DICTIONARY_FILE_BYTES} 位元組 +@msg it isn't a file 它不是檔案 +@msg it names {_1} plates, and at most {MAX_PLATES} are read 它指定了 {_1} 個色版,而最多只讀取 {MAX_PLATES} 個 +@msg its art is too long or too detailed for a head 其圖稿過長或過於細緻,無法作為箭頭 +@msg its art paints nothing 其圖稿沒有繪製任何內容 +@msg its image is too large to read 其影像過大,無法讀取 +@msg its plates are too large: more than {MAX_SAMPLES} pixels together 其色版過大:合計超過 {MAX_SAMPLES} 像素 +@msg its plates are too large: {_1} plates of {w} × {h} pixels 其色版過大:{_1} 個 {w} × {h} 像素的色版 +@msg its plates can't be kept together 其色版無法保持在一起 +@msg its shapes could not be combined into one 其形狀無法合併為一個 +@msg jump to {pc}, past the end 跳躍至 {pc},已超過結尾 +@msg legacyNameEncoding must be one of {_1} legacyNameEncoding 必須是 {_1} 其中之一 +@msg localize: the first argument must be a localization object or a string localize:第一個引數必須是本地化物件或字串 +@msg missing `picks` 未提供 `picks` +@msg missing `word` 未提供 `word` +@msg must be an object with `kind` and `value` 必須是包含 `kind` 和 `value` 的物件 +@msg must have `kind` alert, confirm or prompt `kind` 必須是 alert、confirm 或 prompt +@msg must have exactly `kind` and `value` 只能有 `kind` 和 `value` +@msg needs a closing quote after the name 名稱之後需要結尾引號 +@msg needs a name 需要名稱 +@msg needs a name of at most 64 bytes 需要不超過 64 位元組的名稱 +@msg needs a name of letters, digits and _, or a quoted name 需要由字母、數字和 _ 組成的名稱,或加上引號的名稱 +@msg needs a name without control characters 需要不含控制字元的名稱 +@msg nesting too deep 巢狀層次過深 +@msg no HP-GL format 沒有 HP-GL 格式 +@msg no New Document profile called `{shown}` ({_1}) 沒有名為 `{shown}` 的新增文件描述檔 ({_1}) +@msg no SVG filter at index {k} 索引 {k} 沒有 SVG 濾鏡 +@msg no arrowheads file here 這裡沒有箭頭檔案 +@msg no character has code {code} 沒有代碼為 {code} 的字元 +@msg no custom arrowhead {name} (see stroke.arrowheads.list) 沒有自訂箭頭 {name} (請參閱 stroke.arrowheads.list) +@msg no file to open 沒有可開啟的檔案 +@msg no instructions 沒有指令 +@msg no layer to rename 沒有可重新命名的圖層 +@msg no random numbers ({e}) 沒有亂數 ({e}) +@msg no selected or given object has a visible 3D effect 所選或指定的物件都沒有可見的 3D 效果 +@msg no such artboard {v} 沒有這個工作區域 {v} +@msg no symbol named `{_1}` 沒有名為 `{_1}` 的符號 +@msg node {_1} already has the text variable `{_2}` 節點 {_1} 已有文字變數 `{_2}` +@msg not a DCS file 不是 DCS 檔案 +@msg not a RegExp object 不是 RegExp 物件 +@msg not a regular expression 不是正規表示式 +@msg not an action set: the text doesn't start with /version and a number 不是動作組:文字的開頭不是 /version 和一個數字 +@msg nothing to repeat 沒有可重複的內容 +@msg numbers out of order in {_1} quantifier {_1} 量詞中的數字順序錯誤 +@msg object {_1} needs a 3D effect 物件 {_1} 需要 3D 效果 +@msg object {_1}: a hollow Extrude & Bevel has no caps: turn on Cap to map a graphic 物件 {_1}:空心的「突出與斜角」沒有端面:請開啟「端點」才能對應圖形 +@msg object {_1}: with a depth of 0 the object has one face: map its graphics onto the front 物件 {_1}:深度為 0 時物件只有一個面:請將圖形對應到正面 +@msg object {_1}: {_2} 物件 {_1}:{_2} +@msg object {_1}: {e} 物件 {_1}:{e} +@msg object {_1}: {name} at index {index} has no lighting presets; set its lights with effect.setParams 物件 {_1}:索引 {index} 的 {name} 沒有光源預設集;請以 effect.setParams 設定其光源 +@msg opacity must be a number opacity 必須是數字 +@msg operand too large 運算元過大 +@msg order is a whole number from 0 to {others}, not `{v}` order 是 0 到 {others} 之間的整數,而非 `{v}` +@msg path chunks must share their boundary point 路徑片段必須共用其邊界點 +@msg pdfCompatible: false needs the artboards to keep the editable artwork when useArtboards is false pdfCompatible: false 在 useArtboards 為 false 時需要工作區域來保留可編輯的圖稿 +@msg point x must be a number 點的 x 必須是數字 +@msg point y must be a number 點的 y 必須是數字 +@msg points must be [x,y] pairs points 必須是 [x,y] 配對 +@msg points must be finite canvas points points 必須是有限的畫布座標點 +@msg range out of order in character class 字元類別中的範圍順序錯誤 +@msg reduce of an empty array with no initial value 對空陣列執行 reduce 時沒有初始值 +@msg regular expression flag '{_1}' given twice 正規表示式旗標 '{_1}' 提供了兩次 +@msg sampled text would exceed the canvas (coordinates out of range) 取樣的文字會超出畫布 (座標超出範圍) +@msg select an SVG filter 請選取 SVG 濾鏡 +@msg select an object with a 3D effect 請選取具有 3D 效果的物件 +@msg select an object with a 3D effect, or give its id in ids 請選取具有 3D 效果的物件,或在 ids 中提供其 ID +@msg select one layer, group or object to rename 請選取一個要重新命名的圖層、群組或物件 +@msg select the art to weed 請選取要除廢的圖稿 +@msg select the banner, or mark every artboard 請選取橫幅,或標記每個工作區域 +@msg select type on a path or area type 請選取路徑文字或區域文字 +@msg side is left or right, not `{v}` side 是 left 或 right,而非 `{v}` +@msg source text transform is collapsed or unrepresentable 來源文字變形已塌陷或無法表示 +@msg table must be true or false table 必須是 true 或 false +@msg takes one name 接受一個名稱 +@msg target text transform is collapsed or unrepresentable 目標文字變形已塌陷或無法表示 +@msg that makes too many pieces (at most 100000) or dash steps: simplify the dash pattern or make the dashes longer 這會產生過多片段 (最多 100000 個) 或虛線步數:請簡化虛線樣式或加長虛線 +@msg the Layers panel is not shown 「圖層」面板未顯示 +@msg the Layers panel's search, filter or Show Layers Only hides its row 「圖層」面板的搜尋、篩選或「僅顯示圖層」隱藏了它的列 +@msg the Objects on Path group is hidden or locked 「路徑上的物件」群組已隱藏或鎖定 +@msg the SVG file is larger than {MAX_IMPORT_BYTES} bytes SVG 檔案大於 {MAX_IMPORT_BYTES} 位元組 +@msg the XML operation needs an XML or XMLList value XML 運算需要 XML 或 XMLList 值 +@msg the XPath expression does not evaluate to a node-set XPath 運算式的結果不是節點集 +@msg the XPath expression ends early XPath 運算式提前結束 +@msg the XPath expression has an unmatched ) XPath 運算式中有不成對的 ) +@msg the XPath expression has an unmatched ] XPath 運算式中有不成對的 ] +@msg the XPath expression has an unmatched closing bracket XPath 運算式中有不成對的右括號 +@msg the XPath expression selects a namespace node, which is not an XML value XPath 運算式選取了命名空間節點,而它不是 XML 值 +@msg the XPath expression selects the root node, which is not an XML value XPath 運算式選取了根節點,而它不是 XML 值 +@msg the XPath function {name} needs a node-set XPath 函式 {name} 需要節點集 +@msg the XPath function {name} takes the wrong number of arguments XPath 函式 {name} 的引數數目不正確 +@msg the XPath name functions need a node-set XPath 名稱函式需要節點集 +@msg the XPath prefix {shown} is not bound to a namespace XPath 前置詞 {shown} 未繫結到命名空間 +@msg the XPath variable ${shown} is not bound XPath 變數 ${shown} 未繫結 +@msg the argument list is not an object 引數清單不是物件 +@msg the artwork is too large for EPS: what follows 256 MB of PostScript was left out 圖稿對 EPS 而言過大:超過 256 MB PostScript 之後的內容已略過 +@msg the banner has no width or height 橫幅沒有寬度或高度 +@msg the bitmaps hold more pixels than one file may 點陣圖的像素總數超過單一檔案的上限 +@msg the code runs past its last instruction 程式碼執行超過了最後一個指令 +@msg the curve tolerance must be from 0.01 to 10 points 曲線容許度必須介於 0.01 到 10 點之間 +@msg the custom dictionary couldn't be saved to {_1}: {e} 自訂字典無法儲存到 {_1}:{e} +@msg the custom dictionary {_1} can't be read ({why}), so it is left as it is 無法讀取自訂字典 {_1} ({why}),因此保持原狀 +@msg the document already has an SVG filter named {name} 文件中已有名為 {name} 的 SVG 濾鏡 +@msg the document has another SVG filter named {name}: use svgFilter.apply, or svgFilter.define with `replace` to edit it 文件中有另一個名為 {name} 的 SVG 濾鏡:請使用 svgFilter.apply,或以帶有 `replace` 的 svgFilter.define 編輯它 +@msg the document has no SVG filter named {name} 文件中沒有名為 {name} 的 SVG 濾鏡 +@msg the document has no SVG filter named {r} 文件中沒有名為 {r} 的 SVG 濾鏡 +@msg the document has no color swatches 文件中沒有顏色色票 +@msg the document's swatches hold {_1} colors; the document reduction takes at most 255 文件的色票包含 {_1} 種顏色;文件縮減最多接受 255 種 +@msg the file isn't valid SVG: {e} 檔案不是有效的 SVG:{e} +@msg the file names no plate 檔案未指定任何色版 +@msg the function's prototype is not an object 函式的原型不是物件 +@msg the grommet inset is too large for the banner 扣眼邊距對橫幅而言過大 +@msg the guide is hidden or locked 參考線已隱藏或鎖定 +@msg the hem is too deep for the banner 折邊對橫幅而言過深 +@msg the library's file is outside the read roots 資料庫的檔案位於讀取根目錄之外 +@msg the line is too long, or the paths it passes too many, to check 線條過長,或經過的路徑過多,無法檢查 +@msg the method needs an XML value 此方法需要 XML 值 +@msg the paint is not a freeform gradient (apply one with paint.editGradient {kind}) 此上色不是任意形狀漸層 (請以 paint.editGradient {kind} 套用) +@msg the parameters or body do not form one function 參數或主體無法構成一個函式 +@msg the pasted SVG filter {name} draws differently from the document's filter of that name, and no free name fits it 貼上的 SVG 濾鏡 {name} 的繪製結果與文件中同名的濾鏡不同,而且找不到可用的名稱 +@msg the paths are too many or too tangled to find where they cross 路徑過多或過於糾結,無法找出交叉處 +@msg the pen table holds more than 255 pens 筆表包含超過 255 支筆 +@msg the plates can't be kept 色版無法保留 +@msg the position table does not match the instructions 位置表與指令不相符 +@msg the prompt's text is longer than {MAX_PROMPT_BYTES} bytes 提示的文字超過 {MAX_PROMPT_BYTES} 位元組 +@msg the radix must be between 2 and 36 基數必須介於 2 和 36 之間 +@msg the rectangle or line reaches too many paths to check 矩形或線條觸及的路徑過多,無法檢查 +@msg the right side of 'in' is not an object 'in' 的右側不是物件 +@msg the right side of 'instanceof' is not a function 'instanceof' 的右側不是函式 +@msg the selected art is nested more than {MAX_DEPTH} levels deep 所選圖稿的巢狀層次超過 {MAX_DEPTH} 層 +@msg the selected art is too large to measure 所選圖稿過大,無法測量 +@msg the selection has no outlines to weed around 選取範圍沒有可供除廢的外框 +@msg the spacing makes more than {MAX_GROMMETS} grommets 此間距會產生超過 {MAX_GROMMETS} 個扣眼 +@msg the value bind was called on is not a function 呼叫 bind 時所用的值不是函式 +@msg the value is not a constructor 該值不是建構函式 +@msg the value is not a function 該值不是函式 +@msg the value is not a valid XML name 該值不是有效的 XML 名稱 +@msg the value is not an XML attribute name 該值不是 XML 屬性名稱 +@msg the value is not an XML name 該值不是 XML 名稱 +@msg the weeding lines cross the art's outlines too many times to measure; use fewer lines 除廢線與圖稿外框交叉的次數過多,無法測量;請減少線條 +@msg the weeding lines pass too close to too many outline segments to measure; use fewer lines or a smaller gap 除廢線過於接近太多外框線段,無法測量;請減少線條或縮小間隙 +@msg the weeding lines would be more than {max_pieces} pieces 除廢線會超過 {max_pieces} 段 +@msg the {_1} plate lies outside the file {_1} 色版位於檔案之外 +@msg there is no banner to mark 沒有可標記的橫幅 +@msg this is a binary DXF file, which can't be read: save it from the CAD app as an ASCII DXF and open that 這是二進位 DXF 檔案,無法讀取:請在 CAD 應用程式中將它儲存為 ASCII DXF,再開啟該檔案 +@msg this warp's points can't be edited: use Reset with Mesh first 無法編輯此彎曲的點:請先使用「以網格重設」 +@msg toExponential() digits must be between 0 and 20 toExponential() 的位數必須介於 0 和 20 之間 +@msg toFixed() digits must be between 0 and 20 toFixed() 的位數必須介於 0 和 20 之間 +@msg toISOString is not a function toISOString 不是函式 +@msg toPrecision() argument must be between 1 and 21 toPrecision() 的引數必須介於 1 和 21 之間 +@msg toSource: a getter cannot be written as source toSource:getter 無法寫成原始碼 +@msg toSource: an array with properties besides its elements, a property that is not enumerable or another prototype cannot be written as source toSource:除了元素之外還有其他屬性的陣列、不可列舉的屬性或其他原型都無法寫成原始碼 +@msg toSource: an object with a property that is not enumerable, or whose prototype is not Object.prototype, cannot be written as source toSource:具有不可列舉屬性的物件,或原型不是 Object.prototype 的物件,無法寫成原始碼 +@msg toSource: the source is too long toSource:原始碼過長 +@msg toSource: the value contains itself toSource:該值包含其本身 +@msg toSource: the value has too many entries toSource:該值的項目過多 +@msg toSource: the value is nested too deep toSource:該值的巢狀層次過深 +@msg toString is not a function toString 不是函式 +@msg too many arguments 引數過多 +@msg too many quantifiers 量詞過多 +@msg turn on at least one side 請至少開啟一側 +@msg unknown OpenType feature `{t}` (liga, calt, dlig, smcp, frac, onum, tnum, ordn, swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom, aalt; prefix - to turn off; swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom and aalt take an alternate's number as `tag=N` with N from 0 to {_1}, as `salt=2`) 未知的 OpenType 功能 `{t}` (liga, calt, dlig, smcp, frac, onum, tnum, ordn, swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom, aalt;加上前置的 - 可關閉;swsh, ss01–ss20, salt, titl, pnum, lnum, sups, subs, numr, dnom 和 aalt 可用 `tag=N` 指定替代字的編號,N 為 0 到 {_1},例如 `salt=2`) +@msg unknown dither `{d}` (diffusion, pattern, noise or none) 未知的仿色 `{d}` (diffusion、pattern、noise 或 none) +@msg unknown panel `{panel}` 未知的面板 `{panel}` +@msg unknown parameter `{key}` 未知的參數 `{key}` +@msg unknown parameter `{within}settings.{format}`; {why} 未知的參數 `{within}settings.{format}`;{why} +@msg unknown parameter `{within}{key}`; {why} 未知的參數 `{within}{key}`;{why} +@msg unknown reduction `{reduction}` (selective, perceptual, adaptive, web, gray, blackWhite, uniform or document) 未知的縮減 `{reduction}` (selective、perceptual、adaptive、web、gray、blackWhite、uniform 或 document) +@msg unmatched ')' 不成對的 ')' +@msg unterminated character class 字元類別未結束 +@msg unterminated group 群組未結束 +@msg with no hem and no grommets there is nothing to mark 沒有折邊也沒有扣眼,因此沒有可標記的內容 +@msg wordGap and lineGap need area type in the selection wordGap 和 lineGap 需要選取範圍中有區域文字 +@msg xpath needs its variables as an object xpath 需要以物件形式提供變數 +@msg xpath needs the expression as a string xpath 需要以字串形式提供運算式 +@msg {GRANT_NOT_REMOVED}, and its settings and cache can't be moved back from {_1} to {_2}: {e} {GRANT_NOT_REMOVED},而且其設定和快取無法從 {_1} 移回 {_2}:{e} +@msg {_1} is not a folder: {e} {_1} 不是資料夾:{e} +@msg {_1}: {_2} and {_3} are in the way {_1}:{_2} 和 {_3} 擋住了 +@msg {code}: {0} {code}:{0} +@msg {dir}: {e} {dir}:{e} +@msg {file} names more than one linked JavaScript file {file} 指定了多個連結的 JavaScript 檔案 +@msg {k}: a custom arrowhead's path needs an area to fill and at most {most} anchors and {most} subpaths, each anchor within {far} head units of its tip {k}:自訂箭頭的路徑需要有可填色的區域,最多 {most} 個錨點和 {most} 個子路徑,且每個錨點與箭頭尖端的距離在 {far} 個箭頭單位以內 +@msg {k}: bad custom arrowhead path: {e} {k}:自訂箭頭路徑無效:{e} +@msg {k}: bad custom arrowhead: {e} {k}:自訂箭頭無效:{e} +@msg {k}: custom must be a name {k}:custom 必須是名稱 +@msg {name} must be a number {name} 必須是數字 +@msg {path}: copy takes a DCS file only when its plates are inside it; relink to it where its plate files are {path}:只有當 DCS 檔案的色版位於檔案內時才能複製它;請在其色版檔案所在位置重新連結 +@msg {path}: larger than {_1} MB {path}:大於 {_1} MB +@msg {saving} failed: {e} {saving} 失敗:{e} +@msg {shown} is not an XPath 1.0 function {shown} 不是 XPath 1.0 函式 +@msg {v} names no layer or sublayer {v} 不是任何圖層或子圖層的名稱 +@msg {what} is not a function {what} 不是函式 +@msg {what} would print more than {MAX_COPIES_PER_SHEET} copies on a sheet: scale it up {what} 會在一張紙上列印超過 {MAX_COPIES_PER_SHEET} 份:請放大 +@msg {what} {i} out of range {what} {i} 超出範圍 +@msg A profile supports one Revolve effect. Edit the existing effect's options instead. 一個剖面只支援一個「迴轉」效果。請改為編輯現有效果的選項。 +@msg Add Points at Crossings: a path went missing 在交叉處增加錨點:有一條路徑不見了 +@msg CSS options: {e} CSS 選項:{e} +@msg CSV has a header but no data rows CSV 有標題列但沒有資料列 +@msg CSV holds NUL bytes: save it as UTF-8, or as UTF-16 with a byte-order mark CSV 包含 NUL 位元組:請儲存為 UTF-8,或帶有位元組順序記號的 UTF-16 +@msg CSV is empty CSV 為空 +@msg CSV is larger than {MAX_CSV_BYTES} bytes CSV 大於 {MAX_CSV_BYTES} 位元組 +@msg CSV is not UTF-16 CSV 不是 UTF-16 +@msg CSV is not UTF-8 CSV 不是 UTF-8 +@msg CSV would be larger than {MAX_CSV_BYTES} bytes CSV 會大於 {MAX_CSV_BYTES} 位元組 +@msg Choose original artwork, not a dimension's generated paths 請選擇原始圖稿,而不是尺寸標註產生的路徑 +@msg Contour: select paths or shapes 輪廓:請選取路徑或形狀 +@msg Contour: the Offset Path effect is not available 輪廓:無法使用「位移複製」效果 +@msg Create needs fills, strokes or both 「建立」需要填色、筆畫或兩者 +@msg DXF options: {e} DXF 選項:{e} +@msg DXF scale must be a positive number up to {_1}, not {scale} DXF 比例必須是不超過 {_1} 的正數,而非 {scale} +@msg DXF {field} `{s}`: {allowed} DXF {field} `{s}`:{allowed} +@msg Dimension is locked or hidden 尺寸標註已鎖定或隱藏 +@msg Dimension mode does not match its source 尺寸標註模式與其來源不相符 +@msg Draw Inside needs exactly one selected path, compound path or text 「內部繪圖」需要剛好選取一個路徑、複合路徑或文字 +@msg EPS Save writes all artwork: use document.export for selected-only EPS EPS 儲存會寫入所有圖稿:若只要所選圖稿的 EPS,請使用 document.export +@msg EPS flattener: {e} EPS 平面化:{e} +@msg EPS options: {e} EPS 選項:{e} +@msg EPS {field} `{s}`: {allowed} EPS {field} `{s}`:{allowed} +@msg Export for Screens writes png, png8, jpg, webp, gif, tiff, bmp, tga, psd, svg, svgz, pdf, eps, ai or vectorcraft 「匯出為螢幕適用」可寫入 png、png8、jpg、webp、gif、tiff、bmp、tga、psd、svg、svgz、pdf、eps、ai 或 vectorcraft +@msg Flare click coordinates must be finite numbers 光暈的點按座標必須是有限的數字 +@msg HTML Text applies to object slices of type only HTML 文字只適用於文字的物件切片 +@msg Identify Objects By is XML ID: the name must be a valid XML ID (start with a letter, underscore or colon; no spaces) 「識別物件依據」為 XML ID:名稱必須是有效的 XML ID (以字母、底線或冒號開頭;不含空格) +@msg Image Trace failed: internal error: its thread stopped (please report this bug) 影像描圖失敗:內部錯誤:其執行緒已停止 (請回報此錯誤) +@msg Image Trace failed: {e} 影像描圖失敗:{e} +@msg Image Trace finished, but its document was closed 影像描圖已完成,但其文件已關閉 +@msg Image Trace finished, but the image or its settings changed meanwhile: trace it again 影像描圖已完成,但影像或其設定在此期間已變更:請重新描圖 +@msg Invalid dimension offset 尺寸標註位移無效 +@msg Invalid point 點無效 +@msg Join: a subpath went missing 連接:有一條子路徑不見了 +@msg Lock Workspace is not available in VectorCraft VectorCraft 不提供「鎖定工作區」 +@msg Move Panel to New Window is not available: floating panels stay in the main window 無法使用「將面板移至新視窗」:浮動面板會留在主視窗中 +@msg Offset Path: the path is too complex to offset 位移複製:路徑過於複雜,無法位移 +@msg Offset Path: {e} 位移複製:{e} +@msg PDF content is incomplete or exceeds the reader's limits; no document was imported PDF 內容不完整或超出讀取器的限制;未匯入任何文件 +@msg PDF flattener: {e} PDF 平面化:{e} +@msg PDF options: {e} PDF 選項:{e} +@msg Recolor Artwork is no longer open 「重新上色圖稿」已不再開啟 +@msg SVG is not UTF-8, UTF-16 or ISO 8859-1 SVG 不是 UTF-8、UTF-16 或 ISO 8859-1 +@msg Save writes one artboard: name one, or export several with document.export 「儲存」只寫入一個工作區域:請指定一個,或以 document.export 匯出多個 +@msg Select a dimension first 請先選取尺寸標註 +@msg Select dimensions to update 請選取要更新的尺寸標註 +@msg Select only dimensions 請只選取尺寸標註 +@msg Select two or more objects, or a group 請選取兩個以上的物件,或一個群組 +@msg Shaper needs 1–64 source paths Shaper 需要 1–64 條來源路徑 +@msg Switch x/y is for scatter graphs 「切換 x/y」適用於散佈圖 +@msg Text options: {e} 文字選項:{e} +@msg `align` is start, center or end `align` 是 start、center 或 end +@msg `anchors` must be an array of [subpath, anchor] pairs `anchors` 必須是 [subpath, anchor] 配對的陣列 +@msg `anchors` must list anchor indices (0, 1, 2…), not {k} `anchors` 必須列出錨點索引 (0, 1, 2…),而非 {k} +@msg `anchors` must list anchor indices (0, 1, 2…), not {v} `anchors` 必須列出錨點索引 (0, 1, 2…),而非 {v} +@msg `artboards` must be a list of artboard indices `artboards` 必須是工作區域索引的清單 +@msg `asset` is the asset id (see assets.list) `asset` 是資產 ID (請參閱 assets.list) +@msg `at` must be a byte offset `at` 必須是位元組偏移 +@msg `autoLeading` must be a number `autoLeading` 必須是數字 +@msg `background` must be "", "matte" or #rrggbb `background` 必須是 ""、"matte" 或 #rrggbb +@msg `burasagari` must be "none", "standard" or "forced" `burasagari` 必須是 "none"、"standard" 或 "forced" +@msg `center` must be [x, y] `center` 必須是 [x, y] +@msg `charAlign` must be "romanBaseline", "emBoxTop", "emBoxCenter", "emBoxBottom", "icfTop" or "icfBottom" `charAlign` 必須是 "romanBaseline"、"emBoxTop"、"emBoxCenter"、"emBoxBottom"、"icfTop" 或 "icfBottom" +@msg `charDirection` must be "default", "leftToRight" or "rightToLeft" `charDirection` 必須是 "default"、"leftToRight" 或 "rightToLeft" +@msg `clearStroke` requires `stroke: false`, `ids: []` and no `stop` `clearStroke` 需要 `stroke: false`、`ids: []`,且不能有 `stop` +@msg `clear` must be a list of type object ids, not {v} `clear` 必須是文字物件 ID 的清單,而非 {v} +@msg `clear` must list type objects; {_1} is not one `clear` 必須列出文字物件;{_1} 不是文字物件 +@msg `clear` must not list `id` `clear` 不能列出 `id` +@msg `color` needs a `rule` to make the theme from `color` 需要 `rule` 才能建立主題 +@msg `colors` is empty `colors` 為空 +@msg `columnType` is vertical, uniform, repeating or sliding `columnType` 是 vertical、uniform、repeating 或 sliding +@msg `columns` must be a whole number 1..50 `columns` 必須是 1..50 的整數 +@msg `commands` must not be empty `commands` 不能為空 +@msg `contents` goes with `to` `contents` 要與 `to` 一起使用 +@msg `corners` must be sharp, round or square, not `{other}` `corners` 必須是 sharp、round 或 square,而非 `{other}` +@msg `corners` must list anchor indices (0, 1, 2…), not {v} `corners` 必須列出錨點索引 (0, 1, 2…),而非 {v} +@msg `count` must be a whole number from 1 to 100 `count` 必須是 1 到 100 之間的整數 +@msg `dataBase64` is larger than the module limit `dataBase64` 大於模組上限 +@msg `dataBase64` is not valid base64 `dataBase64` 不是有效的 base64 +@msg `defaultsOnly` cannot be combined with `ids`, `reverse` or `append` `defaultsOnly` 不能與 `ids`、`reverse` 或 `append` 一起使用 +@msg `depth` and `childLimit` slice the summary: pass `summary: true` `depth` 和 `childLimit` 用於裁切摘要:請傳入 `summary: true` +@msg `design` is a design name, or null for plain columns `design` 是設計名稱,或以 null 表示一般直條 +@msg `design` is a design name, or null for the default marker `design` 是設計名稱,或以 null 表示預設標記 +@msg `destinationFolder` is required when destination is `folder` destination 為 `folder` 時必須提供 `destinationFolder` +@msg `destination` must be `none`, `saveAndClose` or `folder` `destination` 必須是 `none`、`saveAndClose` 或 `folder` +@msg `diameter` must be from 0.1 to 2500 pt `diameter` 必須介於 0.1 到 2500 pt 之間 +@msg `digits` must be one of {_1} `digits` 必須是 {_1} 其中之一 +@msg `dimImages` is a percentage or false `dimImages` 是百分比或 false +@msg `direction` must be "auto", "leftToRight" or "rightToLeft" `direction` 必須是 "auto"、"leftToRight" 或 "rightToLeft" +@msg `each` is the value one design stands for, more than 0 `each` 是一個設計所代表的值,必須大於 0 +@msg `end` must be "start" or "end" `end` 必須是 "start" 或 "end" +@msg `ends` applies to joining exactly two paths `ends` 只適用於連接剛好兩條路徑 +@msg `event` must be one of {_1} `event` 必須是 {_1} 其中之一 +@msg `every` must be "all", "odd" or "even", not {v} `every` 必須是 "all"、"odd" 或 "even",而非 {v} +@msg `expand` must be true or false `expand` 必須是 true 或 false +@msg `files` must be 1 to 1000 paths of font files the last text.findFontFiles search found `files` 必須是 1 到 1000 個字體檔案路徑,且出自最近一次 text.findFontFiles 搜尋的結果 +@msg `folder` must be an absolute folder path `folder` 必須是絕對資料夾路徑 +@msg `fontAxes` must be an object of axis tags and values, such as {"wght"} `fontAxes` 必須是由軸標籤和值組成的物件,例如 {"wght"} +@msg `format` must be a string `format` 必須是字串 +@msg `format` must be one of {_1} `format` 必須是 {_1} 其中之一 +@msg `fractions` is chop or scale `fractions` 是 chop 或 scale +@msg `from` and `to` must differ `from` 和 `to` 必須不同 +@msg `from` has an empty frame `from` 中有空的文字框 +@msg `from` must be a non-negative integer `from` 必須是非負整數 +@msg `from` must be area type or type on a path `from` 必須是區域文字或路徑文字 +@msg `gid` must be a glyph id, not {v} `gid` 必須是字符 ID,而非 {v} +@msg `glyphAlternate` belongs to one character, not to a character style (text.setGlyphAlternate sets it) `glyphAlternate` 屬於單一字元,不屬於字元樣式 (由 text.setGlyphAlternate 設定) +@msg `guide` must be a guide index (guide.list) `guide` 必須是參考線索引 (guide.list) +@msg `hAlign` must be default, left, center or right `hAlign` 必須是 default、left、center 或 right +@msg `id` must be a node id `id` 必須是節點 ID +@msg `id` must be an object id, not {v} `id` 必須是物件 ID,而非 {v} +@msg `ids` must name Objects on Path groups or objects in them `ids` 必須指定「路徑上的物件」群組或其中的物件 +@msg `ids` takes at most {MAX_INSPECT_IDS} ids `ids` 最多接受 {MAX_INSPECT_IDS} 個 ID +@msg `imageMap` must be none, rectangle or polygon `imageMap` 必須是 none、rectangle 或 polygon +@msg `includeArtboardFill` must be true or false `includeArtboardFill` 必須是 true 或 false +@msg `includeSubdirs` must be true or false `includeSubdirs` 必須是 true 或 false +@msg `index` must be a point index `index` 必須是點的索引 +@msg `index` must be a whole number or null `index` 必須是整數或 null +@msg `indices` must be a non-empty array of item indices `indices` 必須是項目索引的非空陣列 +@msg `items` is a list of {kind, item} `items` 是 {kind, item} 的清單 +@msg `items` is empty `items` 為空 +@msg `items` must be a list of {id, points} `items` 必須是 {id, points} 的清單 +@msg `items` must be a list of {{id, anchors?}}, not {v} `items` 必須是 {{id, anchors?}} 的清單,而非 {v} +@msg `items` must be an array of {id, anchors} `items` 必須是 {id, anchors} 的陣列 +@msg `items` must be an array of {{id, corners?}}, not {v} `items` 必須是 {{id, corners?}} 的陣列,而非 {v} +@msg `kashida` must be "none", "short", "medium", "long" or "stylistic" `kashida` 必須是 "none"、"short"、"medium"、"long" 或 "stylistic" +@msg `kind` is one of {_1} `kind` 是 {_1} 其中之一 +@msg `kind` must be "round", "invertedRound" or "chamfer", not {v} `kind` 必須是 "round"、"invertedRound" 或 "chamfer",而非 {v} +@msg `kind` must be `text`, `visibility`, `image` or `graph` `kind` 必須是 `text`、`visibility`、`image` 或 `graph` +@msg `kind` must be a string `kind` 必須是字串 +@msg `kind` must be image, noImage or htmlText `kind` 必須是 image、noImage 或 htmlText +@msg `kinsoku` must be "none", "hard" or "soft" `kinsoku` 必須是 "none"、"hard" 或 "soft" +@msg `label` must be a non-empty name of at most 200 characters `label` 必須是不超過 200 個字元的非空名稱 +@msg `language` must be a language name or tag, such as "Turkish" or "tr" `language` 必須是語言名稱或標籤,例如 "Turkish" 或 "tr" +@msg `leadingModel` must be "romanBaseline" or "emBoxTop" `leadingModel` 必須是 "romanBaseline" 或 "emBoxTop" +@msg `leading` must be from 0.1 to 5000, or null for Auto `leading` 必須介於 0.1 到 5000 之間,或以 null 表示自動 +@msg `length` must be a number of at most 1000000 pt either way `length` 必須是正負都不超過 1000000 pt 的數字 +@msg `line` must be true or false `line` 必須是 true 或 false +@msg `minAngle` ({min_angle}°) can't be more than `maxAngle` ({max_angle}°) `minAngle` ({min_angle}°) 不能大於 `maxAngle` ({max_angle}°) +@msg `mode` must be "handles", "straight" or "smooth" `mode` 必須是 "handles"、"straight" 或 "smooth" +@msg `mode` must be "straight", "bezier" or "arc" `mode` 必須是 "straight"、"bezier" 或 "arc" +@msg `mode` must be one of {_1} `mode` 必須是 {_1} 其中之一 +@msg `mojikumi` must be "none", "yakumonoHankaku", "gyomatsuYakumonoHankaku", "gyomatsuYakumonoZenkaku", "yakumonoZenkaku" or "lineEndHalf" `mojikumi` 必須是 "none"、"yakumonoHankaku"、"gyomatsuYakumonoHankaku"、"gyomatsuYakumonoZenkaku"、"yakumonoZenkaku" 或 "lineEndHalf" +@msg `names` is a list of preset names `names` 是預設集名稱的清單 +@msg `names` lists preset names `names` 用來列出預設集名稱 +@msg `names` must be a list of names `names` 必須是名稱清單 +@msg `names` must be a list of swatch names `names` 必須是色票名稱的清單 +@msg `names` must be an array of style names `names` 必須是樣式名稱的陣列 +@msg `new` is a design name, or true `new` 是設計名稱,或 true +@msg `path` must be a folder `path` 必須是資料夾 +@msg `path` must be a path object `path` 必須是路徑物件 +@msg `pivot` must be a whole number from 0 to 8 `pivot` 必須是 0 到 8 之間的整數 +@msg `points` must be a list of [x, y] points `points` 必須是 [x, y] 點的清單 +@msg `points` must be a list of point indexes `points` 必須是點索引的清單 +@msg `points` must be an array of point indices `points` 必須是點索引的陣列 +@msg `points` must be point indexes `points` 必須是點的索引 +@msg `port` must be "in" or "out" `port` 必須是 "in" 或 "out" +@msg `position` is above or below `position` 是 above 或 below +@msg `preset` must be a string `preset` 必須是字串 +@msg `ratio` must be from 0.1 to 0.5 `ratio` 必須介於 0.1 到 0.5 之間 +@msg `rect` must be [x, y, width, height] with a positive size `rect` 必須是大小為正值的 [x, y, width, height] +@msg `relation` must be overlap, inside or outside `relation` 必須是 overlap、inside 或 outside +@msg `reversed` must be true or false `reversed` 必須是 true 或 false +@msg `rotate` must be a finite number `rotate` 必須是有限的數字 +@msg `rule` must be nonZero or evenOdd `rule` 必須是 nonZero 或 evenOdd +@msg `scale` must be a number in (0, 100] `scale` 必須是 (0, 100] 範圍內的數字 +@msg `scope` must be "selection" or "document", not {other} `scope` 必須是 "selection" 或 "document",而非 {other} +@msg `script` must be a string `script` 必須是字串 +@msg `seriesIndexes` is a non-empty list of series indexes `seriesIndexes` 是數列索引的非空清單 +@msg `seriesIndexes` needs a `type` or a `valueAxis` `seriesIndexes` 需要 `type` 或 `valueAxis` +@msg `shift` must be a number of points `shift` 必須是以點為單位的數字 +@msg `showCenter` must be true or false `showCenter` 必須是 true 或 false +@msg `singleWordJustification` must be "fullJustify", "alignLeft", "alignCenter" or "alignRight" `singleWordJustification` 必須是 "fullJustify"、"alignLeft"、"alignCenter" 或 "alignRight" +@msg `size` is a percentage of the base text's size, 1 to 100 `size` 是基底文字大小的百分比,1 到 100 +@msg `source` and `target` are the same object `source` 和 `target` 是同一個物件 +@msg `source` must be `folder` or `datasets` `source` 必須是 `folder` 或 `datasets` +@msg `spacing` must be a number `spacing` 必須是數字 +@msg `spacing` must be a number of points, 0 or more, or "auto" `spacing` 必須是以點為單位且大於或等於 0 的數字,或 "auto" +@msg `start` must be a finite number `start` 必須是有限的數字 +@msg `starts` must be an array of anchor indices (or nulls) `starts` 必須是錨點索引 (或 null) 的陣列 +@msg `status` must be linked, embedded, missing or modified, or a list of them `status` 必須是 linked、embedded、missing 或 modified,或由它們組成的清單 +@msg `stop` must be a stop index `stop` 必須是色標索引 +@msg `story` styles the whole story: give no `start` or `end` `story` 會設定整篇文章的樣式:請不要提供 `start` 或 `end` +@msg `story` takes the whole story: give no `start` or `end` `story` 會涵蓋整篇文章:請不要提供 `start` 或 `end` +@msg `strokeMode` applies to strokes (stroke: true) `strokeMode` 適用於筆畫 (stroke: true) +@msg `style` must be roman or japanese `style` 必須是 roman 或 japanese +@msg `subpaths` must be two integer indices `subpaths` 必須是兩個整數索引 +@msg `symbol` must be a symbol name `symbol` 必須是符號名稱 +@msg `target` must be "object" or "contents", not {v} `target` 必須是 "object" 或 "contents",而非 {v} +@msg `tint` applies to global and spot colours `tint` 適用於全域色和特別色 +@msg `tint` goes with a global or spot `swatch` `tint` 要與全域色或特別色的 `swatch` 一起使用 +@msg `tint` must be a number (%) `tint` 必須是數字 (%) +@msg `tint` needs a global or spot colour `tint` 需要全域色或特別色 +@msg `to` is already threaded `to` 已經串連 +@msg `to` is the design's new name `to` 是設計的新名稱 +@msg `to` must be [x, y] `to` 必須是 [x, y] +@msg `to` must be a closed path, area type or type on a path other than `from` `to` 必須是 `from` 以外的封閉路徑、區域文字或路徑文字 +@msg `to` must be a whole number `to` 必須是整數 +@msg `to` takes the rows of one object's stack, not aligned rows `to` 接受單一物件堆疊中的列,而非已對齊的列 +@msg `useLab` must be true or false `useLab` 必須是 true 或 false +@msg `vAlign` must be default, top, middle, baseline or bottom `vAlign` 必須是 default、top、middle、baseline 或 bottom +@msg `values` must be a list `values` 必須是清單 +@msg `values` must be an object `values` 必須是物件 +@msg `values` must name hex, rgb, cmyk, lab or gray `values` 必須指定 hex、rgb、cmyk、lab 或 gray +@msg `values` names a kind twice `values` 將同一種類指定了兩次 +@msg `{_1}` can't be edited or removed `{_1}` 無法編輯或移除 +@msg `{_1}` is built in and always listed `{_1}` 是內建項目,一律會列出 +@msg `{_1}` is not a font file the last text.findFontFiles search found `{_1}` 不是最近一次 text.findFontFiles 搜尋找到的字體檔案 +@msg `{_1}` would be overwritten by the package: choose a different folder or name `{_1}` 會被封裝覆寫:請選擇其他資料夾或名稱 +@msg `{file}` has no art to place `{file}` 沒有可置入的圖稿 +@msg `{file}` is over {_1} MB `{file}` 超過 {_1} MB +@msg `{f}` belongs to a VectorCraft that is running `{f}` 屬於執行中的 VectorCraft +@msg `{f}` is the copy of a document open now `{f}` 是目前開啟文件的副本 +@msg `{id}` is no writable format (see document.formats) `{id}` 不是可寫入的格式 (請參閱 document.formats) +@msg `{id}` isn't a loaded library `{id}` 不是已載入的資料庫 +@msg `{key}` has no colours `{key}` 沒有顏色 +@msg `{key}` is a design name `{key}` 是設計名稱 +@msg `{key}` is a design name or a list of them `{key}` 是設計名稱或設計名稱的清單 +@msg `{key}` is longer than {MAX_NAME} characters `{key}` 超過 {MAX_NAME} 個字元 +@msg `{key}` is out of range `{key}` 超出範圍 +@msg `{key}` must be [min, desired, max] or {{min?, desired?, max?}}, in percent `{key}` 必須是 [min, desired, max] 或 {{min?, desired?, max?}},以百分比表示 +@msg `{key}` must be a non-negative integer `{key}` 必須是非負整數 +@msg `{key}` must be a number {_1}..{_2} `{key}` 必須是 {_1}..{_2} 的數字 +@msg `{key}` must be a whole number of at least 0, not {n} `{key}` 必須是至少為 0 的整數,而非 {n} +@msg `{key}` must be an appearance item index (paint order) or null `{key}` 必須是外觀項目索引 (繪製順序) 或 null +@msg `{key}` must be an array of asset ids (see assets.list) `{key}` 必須是資產 ID 的陣列 (請參閱 assets.list) +@msg `{key}` must be from 0 to 180 degrees, not {a} `{key}` 必須介於 0 到 180 度之間,而非 {a} +@msg `{key}` must be from {_1} to {shift_max} `{key}` 必須介於 {_1} 到 {shift_max} 之間 +@msg `{key}`: not a colour: {v} `{key}`:不是顏色:{v} +@msg `{k}.family` is required 必須提供 `{k}.family` +@msg `{k}` is a number 0..1 `{k}` 是 0..1 的數字 +@msg `{k}` is true or false `{k}` 是 true 或 false +@msg `{k}` isn't an export setting: {_1} `{k}` 不是匯出設定:{_1} +@msg `{k}` must be a byte offset `{k}` 必須是位元組偏移 +@msg `{k}` must be a number `{k}` 必須是數字 +@msg `{k}` must be a number of points `{k}` 必須是以點為單位的數字 +@msg `{k}` must be a string `{k}` 必須是字串 +@msg `{k}` must be a whole number `{k}` 必須是整數 +@msg `{k}` must be from {lo} to {hi} for {key} 對 {key} 而言,`{k}` 必須介於 {lo} 到 {hi} 之間 +@msg `{k}` must be {what}, not {v} `{k}` 必須是 {what},而非 {v} +@msg `{l}` isn't a global or spot colour `{l}` 不是全域色或特別色 +@msg `{m}` isn't a bitmap: use clipboard.importSvg, importPdf or importText `{m}` 不是點陣圖:請使用 clipboard.importSvg、importPdf 或 importText +@msg `{name}` can't be deleted `{name}` 無法刪除 +@msg `{name}` can't be duplicated `{name}` 無法製作複本 +@msg `{name}` can't be edited `{name}` 無法編輯 +@msg `{name}` can't be edited this way `{name}` 無法以這種方式編輯 +@msg `{name}` can't be renamed `{name}` 無法重新命名 +@msg `{name}` can't name a folder `{name}` 不能作為資料夾名稱 +@msg `{name}` has no art to place `{name}` 沒有可置入的圖稿 +@msg `{name}` has no text to place `{name}` 沒有可置入的文字 +@msg `{name}` in the Word document is not UTF-8 or UTF-16 text Word 文件中的 `{name}` 不是 UTF-8 或 UTF-16 文字 +@msg `{name}` in the Word document is not well-formed XML: {e} Word 文件中的 `{name}` 不是格式正確的 XML:{e} +@msg `{name}` in the Word document nests elements more than {MAX_NESTING} deep Word 文件中的 `{name}` 的元素巢狀層次超過 {MAX_NESTING} 層 +@msg `{name}` is a built-in preset and is read-only: save it under another name `{name}` 是內建預設集,為唯讀:請以其他名稱儲存 +@msg `{name}` is a built-in preset: save under another name `{name}` 是內建預設集:請以其他名稱儲存 +@msg `{name}` is a built-in profile and stays `{name}` 是內建描述檔,會保留 +@msg `{name}` is a tint of `{base}`: edit `{base}` (a tint swatch only takes a new name) `{name}` 是 `{base}` 的色調:請編輯 `{base}` (色調色票只能變更名稱) +@msg `{name}` is a working space: choose another with edit.colorSettings first `{name}` 是工作色域:請先以 edit.colorSettings 選擇其他色域 +@msg `{name}` is built in and stays `{name}` 是內建項目,會保留 +@msg `{name}` takes a paint of its own kind (colour, gradient or pattern) `{name}` 只接受同類型的上色 (顏色、漸層或圖樣) +@msg `{n}` can't be deleted `{n}` 無法刪除 +@msg `{n}` can't be merged `{n}` 無法合併 +@msg `{n}` can't be moved `{n}` 無法移動 +@msg `{n}` is not a colour swatch `{n}` 不是顏色色票 +@msg `{n}` isn't a solid colour `{n}` 不是純色 +@msg `{n}`: colour groups hold solid colours only `{n}`:顏色群組只能包含純色 +@msg `{other}` doesn't trace an image `{other}` 不會描圖影像 +@msg `{s}`: the step's references copy in more than {_1} MB of values `{s}`:此步驟的參照複製了超過 {_1} MB 的值 +@msg `{tag}` is not an axis tag: a tag is four characters, such as "wght" `{tag}` 不是軸標籤:標籤為四個字元,例如 "wght" +@msg `{to}` is empty or already used `{to}` 為空或已被使用 +@msg `{what}` is longer than {MAX_TEXT} bytes `{what}` 超過 {MAX_TEXT} 位元組 +@msg `{what}` must be text `{what}` 必須是文字 +@msg a DXF drawing has one origin: pass useArtboards: true for one drawing per artboard DXF 圖面只有一個原點:若要每個工作區域各一份圖面,請傳入 useArtboards: true +@msg a PDF presets file with over {_1} presets PDF 預設集檔案包含超過 {_1} 個預設集 +@msg a batch preview cannot switch documents 批次預覽無法切換文件 +@msg a brush named `{nn}` exists 已有名為 `{nn}` 的筆刷 +@msg a container of the listed objects is gone 所列物件的某個容器已不存在 +@msg a content stream can't be read 有一個內容資料流無法讀取 +@msg a content stream isn't a stream 有一個內容資料流不是資料流 +@msg a design holds at most {_1} objects 一個設計最多包含 {_1} 個物件 +@msg a design needs a name 設計需要名稱 +@msg a dictionary grew too large 有一個字典變得過大 +@msg a document keeps at most {_1} graph designs 一份文件最多保留 {_1} 個圖表設計 +@msg a document keeps at most {_1} saved selections 一份文件最多保留 {_1} 個已儲存的選取範圍 +@msg a document keeps at most {_1} views 一份文件最多保留 {_1} 個檢視 +@msg a document links at most {MAX_SVG_SCRIPTS} JavaScript files 一份文件最多連結 {MAX_SVG_SCRIPTS} 個 JavaScript 檔案 +@msg a feConvolveMatrix filter's order is {x}×{y}, which overflows the kernel-size multiply usvg makes feConvolveMatrix 濾鏡的階數為 {x}×{y},會使 usvg 計算核心大小的乘法溢位 +@msg a gradient preset is already called {n} 已有名為 {n} 的漸層預設集 +@msg a graph has at most {_1} series, so it transposes with at most that many categories 一個圖表最多有 {_1} 個數列,因此轉置時最多只能有同樣數量的類別 +@msg a layer can't be merged into its own sublayer 圖層無法合併到自己的子圖層 +@msg a layer's form box isn't an array 有一個圖層的表單方框不是陣列 +@msg a layer's form can't be read 有一個圖層的表單無法讀取 +@msg a layer's form has no box 有一個圖層的表單沒有方框 +@msg a layer's form has no dictionary 有一個圖層的表單沒有字典 +@msg a legend draws at most {MAX_CHIPS} swatches 圖例最多繪製 {MAX_CHIPS} 個色票 +@msg a name names one asset: give multiple: false, or one object 一個名稱只代表一個資產:請指定 multiple: false,或提供一個物件 +@msg a page can't be read 有一個頁面無法讀取 +@msg a page object is used by something else 有一個頁面物件已被其他內容使用 +@msg a page thumbnail must be RGB pixels, 1 to {THUMBNAIL_SIZE} a side (got {w} × {h}) 頁面縮圖必須是 RGB 像素,每邊 1 到 {THUMBNAIL_SIZE} (收到 {w} × {h}) +@msg a pattern layer doesn't end what it starts 有一個圖樣圖層沒有結束它所開始的內容 +@msg a pattern layer's colors hold something else 有一個圖樣圖層的顏色包含其他內容 +@msg a pattern named `{n}` exists 已有名為 `{n}` 的圖樣 +@msg a plug-in with id {_1} is already installed 已安裝 ID 為 {_1} 的增效模組 +@msg a preset named `{n}` exists 已有名為 `{n}` 的預設集 +@msg a print presets file with over {_1} presets 列印預設集檔案包含超過 {_1} 個預設集 +@msg a profile is already called {n} 已有名為 {n} 的描述檔 +@msg a row can't go into itself 列不能移入其本身 +@msg a series goes on the left or the right value axis 數列只能放在左側或右側的數值軸上 +@msg a start must be an anchor index ≥ 0 or null 起點必須是 ≥ 0 的錨點索引或 null +@msg a style named `{name}` already exists 已有名為 `{name}` 的樣式 +@msg a style named `{to}` already exists 已有名為 `{to}` 的樣式 +@msg a swatch needs a colour, gradient or pattern 色票需要顏色、漸層或圖樣 +@msg a symbol named `{n}` already exists 已有名為 `{n}` 的符號 +@msg a theme has 1 to {THEME_SIZE} colours 一個主題有 1 到 {THEME_SIZE} 種顏色 +@msg a theme is already called {name} (replace: "{name}" overwrites it) 已有名為 {name} 的主題 (replace: "{name}" 會覆寫它) +@msg a toolbar name has at most {MAX_NAME} characters 工具列名稱最多 {MAX_NAME} 個字元 +@msg a view named `{_1}` exists 已有名為 `{_1}` 的檢視 +@msg a view named `{name}` exists 已有名為 `{name}` 的檢視 +@msg a workspace keeps at most {MAX} toolbars 一個工作區最多保留 {MAX} 個工具列 +@msg a {_1} series can't go in a {_2} graph {_1} 數列不能放在 {_2} 圖表中 +@msg aiVersion {v}: "pdf" (PDF-compatible, the default) or "7" (legacy .ai, version 7) aiVersion {v}:"pdf" (PDF 相容,預設值) 或 "7" (舊版 .ai,第 7 版) +@msg already editing an opacity mask 已在編輯不透明度遮色片 +@msg already editing another object's opacity mask 已在編輯另一個物件的不透明度遮色片 +@msg already in pattern editing mode 已在圖樣編輯模式中 +@msg an artboard is listed twice 有一個工作區域列出了兩次 +@msg an empty artboard has no width or height to scale to 空的工作區域沒有可供縮放的寬度或高度 +@msg an image is too large for DXF and was left out 有一個影像對 DXF 而言過大,已略過 +@msg an image of {_1} MB, at most {_2} MB 影像為 {_1} MB,上限為 {_2} MB +@msg an image of {declared_w} × {declared_h} pixels is too large to draw {declared_w} × {declared_h} 像素的影像過大,無法繪製 +@msg an image of {width} × {height} pixels is too large to draw {width} × {height} 像素的影像過大,無法繪製 +@msg an index must be a whole number 索引必須是整數 +@msg an inline graphic has no glyphs 行內圖形沒有字符 +@msg an invisible text form can't be read 有一個不可見文字表單無法讀取 +@msg an object is missing 有一個物件遺失 +@msg an object's header is missing 有一個物件的標頭遺失 +@msg an overprinting form can't be read 有一個疊印表單無法讀取 +@msg an unread object has no readable bounds 有一個未讀取的物件沒有可讀取的邊界 +@msg an unread object holds a frame of threaded type 有一個未讀取的物件包含串連文字的文字框 +@msg an unread object is missing from its layer 有一個未讀取的物件不在其圖層中 +@msg anchor `smooth` must be true or false 錨點的 `smooth` 必須是 true 或 false +@msg anchor `{key}` must be [x, y] 錨點的 `{key}` 必須是 [x, y] +@msg anchor `{key}` must be a number 錨點的 `{key}` 必須是數字 +@msg angle and roundness must be finite angle 和 roundness 必須是有限值 +@msg angles must be a list as long as pins (degrees or null) angles 必須是與 pins 等長的清單 (度數或 null) +@msg appearance must be flat|center|edge appearance 必須是 flat|center|edge +@msg apply is "fill" or "stroke", not `{other}` apply 是 "fill" 或 "stroke",而非 `{other}` +@msg area must be a closed polygon of 3 to 100000 [x, y] points area 必須是由 3 到 100000 個 [x, y] 點組成的封閉多邊形 +@msg area type needs a path that encloses an area 區域文字需要圍出區域的路徑 +@msg area type {_1} is named twice 區域文字 {_1} 指定了兩次 +@msg arrowAlign must be extend|tip, got {o} arrowAlign 必須是 extend|tip,收到 {o} +@msg arrowScale must be [start, end] arrowScale 必須是 [start, end] +@msg artboard is a 0-based index artboard 是從 0 起算的索引 +@msg artboard must be a 0-based index artboard 必須是從 0 起算的索引 +@msg artboard {i} doesn't print 工作區域 {i} 不會列印 +@msg artboardLayout must be {layout?, columns?, spacing?, rightToLeft?} artboardLayout 必須是 {layout?, columns?, spacing?, rightToLeft?} +@msg artboardLayout.columns must be 1 or more artboardLayout.columns 必須大於或等於 1 +@msg artboardLayout.layout must be gridByRow, gridByColumn, row or column artboardLayout.layout 必須是 gridByRow、gridByColumn、row 或 column +@msg artboardLayout.rightToLeft must be true or false artboardLayout.rightToLeft 必須是 true 或 false +@msg artboardLayout.spacing must be 0–{MAX_SPACING} pt artboardLayout.spacing 必須是 0–{MAX_SPACING} pt +@msg artboards must be a non-empty list artboards 必須是非空清單 +@msg artboards must be a number artboards 必須是數字 +@msg asset `{_1}` has no art to export 資產 `{_1}` 沒有可匯出的圖稿 +@msg at most {MAX_KEYWORDS} keywords 最多 {MAX_KEYWORDS} 個關鍵字 +@msg at most {MAX_MATCHES} matches are kept 最多保留 {MAX_MATCHES} 個相符項目 +@msg at most {MAX_POINTS} points 最多 {MAX_POINTS} 個點 +@msg at most {MAX_QUEUE} files 最多 {MAX_QUEUE} 個檔案 +@msg at must be [x, y] at 必須是 [x, y] +@msg at/rect lie outside the canvas at/rect 位於畫布之外 +@msg attribute must be size|leading|tracking|kerning|baselineShift attribute 必須是 size|leading|tracking|kerning|baselineShift +@msg attrs must be an object attrs 必須是物件 +@msg automation path rejected: the folder's name isn't valid text 已拒絕自動化路徑:資料夾名稱不是有效的文字 +@msg automation path rejected: {_1} isn't valid text 已拒絕自動化路徑:{_1} 不是有效的文字 +@msg automation path rejected: {why}: {path} 已拒絕自動化路徑:{why}:{path} +@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{given}` axis 必須是 "vertical"、"horizontal" 或以度為單位的角度,而非 `{given}` +@msg backgroundContents must be transparent or white backgroundContents 必須是 transparent 或 white +@msg bad AES key AES 金鑰無效 +@msg bad `runs`: {e} `runs` 無效:{e} +@msg bad arrowScale arrowScale 無效 +@msg bad base64 base64 無效 +@msg bad color {c} 顏色 {c} 無效 +@msg bad colour 顏色無效 +@msg bad colour in `colors` `colors` 中有無效的顏色 +@msg bad colour {v} 顏色 {v} 無效 +@msg bad colour {v} in groupColors groupColors 中的顏色 {v} 無效 +@msg bad cross-reference entry 交互參照項目無效 +@msg bad cross-reference table 交互參照表無效 +@msg bad current colour {v} 目前的顏色 {v} 無效 +@msg bad dataBase64 dataBase64 無效 +@msg bad edit 編輯無效 +@msg bad fill {v} 填色 {v} 無效 +@msg bad fit: {e} fit 無效:{e} +@msg bad model {other} (keep, new or document) model {other} 無效 (keep、new 或 document) +@msg bad new colour {v} 新的顏色 {v} 無效 +@msg bad object 物件無效 +@msg bad object number 物件編號無效 +@msg bad offset 偏移無效 +@msg bad path data: {e} 路徑資料無效:{e} +@msg bad point {v}: expected [x, y] or [x, y, pressure] 無效的點 {v}:應為 [x, y] 或 [x, y, pressure] +@msg bad reference 參照無效 +@msg bad trailer size 檔尾大小無效 +@msg bad {k} colour {k} 顏色無效 +@msg batches cannot nest 批次不能巢狀 +@msg bind something to a variable first 請先將某個項目綁定到變數 +@msg bleed must be 0–{MAX_BLEED} pt: a number, [top, bottom, left, right] or {{top, bottom, left, right}} bleed 必須是 0–{MAX_BLEED} pt:一個數字、[top, bottom, left, right] 或 {{top, bottom, left, right}} +@msg brush must be a name or null brush 必須是名稱或 null +@msg by must be a number by 必須是數字 +@msg can't add page thumbnails: {why} 無法加入頁面縮圖:{why} +@msg can't add the editing data for other apps: {why} 無法加入供其他應用程式使用的編輯資料:{why} +@msg can't edit the written PDF: {why} 無法編輯已寫入的 PDF:{why} +@msg can't encrypt the PDF: {why} 無法加密 PDF:{why} +@msg can't linearise the PDF: {why} 無法將 PDF 線性化:{why} +@msg can't open `{_1}`: {_2} 無法開啟 `{_1}`:{_2} +@msg can't open `{_1}`: {e} 無法開啟 `{_1}`:{e} +@msg can't open `{name}`: not a format VectorCraft reads (see document.formats) 無法開啟 `{name}`:不是 VectorCraft 可讀取的格式 (請參閱 document.formats) +@msg can't place `{name}`: not a format VectorCraft reads (see document.formats) 無法置入 `{name}`:不是 VectorCraft 可讀取的格式 (請參閱 document.formats) +@msg can't read back the written PDF: {e} 無法讀回已寫入的 PDF:{e} +@msg can't read this Word document: {why} 無法讀取此 Word 文件:{why} +@msg can't write .{e} images: use .png, .jpg, .gif, .webp, .tif or .bmp 無法寫入 .{e} 影像:請使用 .png、.jpg、.gif、.webp、.tif 或 .bmp +@msg can't write PDF layers, overprint or invisible text: {why} 無法寫入 PDF 圖層、疊印或不可見文字:{why} +@msg can't write the file's copyright: {why} 無法寫入檔案的著作權資訊:{why} +@msg can't write the file's modification date: {why} 無法寫入檔案的修改日期:{why} +@msg can't write the pages' user units: {why} 無法寫入頁面的使用者單位:{why} +@msg cannot distort a zero-size or non-finite bounding box 無法扭曲大小為零或非有限的邊框 +@msg cannot move an object into itself 無法將物件移入其本身 +@msg case must be upper|lower|title|sentence case 必須是 upper|lower|title|sentence +@msg category `{c}`: one of {_1} 類別 `{c}`:應為 {_1} 其中之一 +@msg center must be [x, y] center 必須是 [x, y] +@msg choose at least one artboard 請至少選擇一個工作區域 +@msg choose at least one status 請至少選擇一種狀態 +@msg clip must be true or false clip 必須是 true 或 false +@msg clippingMask must be true or false clippingMask 必須是 true 或 false +@msg closed must be a boolean closed 必須是布林值 +@msg collapsed must be true or false collapsed 必須是 true 或 false +@msg color.profile: no RGB or CMYK profile is called “{profile}” color.profile:沒有名為「{profile}」的 RGB 或 CMYK 描述檔 +@msg colorMode must be rgb or cmyk, not `{m}` colorMode 必須是 rgb 或 cmyk,而非 `{m}` +@msg colorModel must be {own} (the document's mode), grayscale or bitmap colorModel 必須是 {own} (文件的模式)、grayscale 或 bitmap +@msg colour groups can't go into colour groups 顏色群組不能放入顏色群組 +@msg colour, mode and spot apply to solid-colour swatches only colour、mode 和 spot 只適用於純色色票 +@msg column {column}: `{cell}` is a `%` column of graph data files, which are not read 第 {column} 欄:`{cell}` 是圖表資料檔案的 `%` 欄,不會讀取 +@msg column {column}: `{cell}` names `{name}`, which is a {_1} variable 第 {column} 欄:`{cell}` 指定了 `{name}`,而它是 {_1} 變數 +@msg column {column}: `{cell}` names no variable 第 {column} 欄:`{cell}` 未指定任何變數 +@msg column {column}: the variable name is longer than {MAX_NAME} characters 第 {column} 欄:變數名稱超過 {MAX_NAME} 個字元 +@msg column: true floats the whole column and takes no onto, above or below column: true 會讓整欄浮動,不接受 onto、above 或 below +@msg command must be a shape.* command command 必須是 shape.* 指令 +@msg commands[{i}]: missing `command` commands[{i}]:未提供 `command` +@msg composer must be "singleLine" or "everyLine" composer 必須是 "singleLine" 或 "everyLine" +@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes 複合形狀接受路徑、複合路徑、群組、複合形狀、文字、漸變物件和封套 +@msg compound {_1} must contain exactly one open path to join 複合路徑 {_1} 必須剛好包含一條可連接的開放路徑 +@msg connect needs a path other than the one extended connect 需要延伸路徑以外的另一條路徑 +@msg connect needs id connect 需要 id +@msg connect path has no open end connect 的路徑沒有開放的端點 +@msg copy needs path: the file to copy into the document's folder copy 需要 path:要複製到文件資料夾的檔案 +@msg copy takes images only: relink placed documents where their files are copy 只接受影像:請在置入文件的檔案所在位置重新連結 +@msg copying a file isn't available on the web 網頁版無法複製檔案 +@msg copyrightStatus must be unknown, copyrighted or publicDomain copyrightStatus 必須是 unknown、copyrighted 或 publicDomain +@msg copyrightUrl must be a URL (no spaces, at most 2048 characters) copyrightUrl 必須是 URL (不含空格,最多 2048 個字元) +@msg corners must be 4 [x, y] points (TL, TR, BR, BL) corners 必須是 4 個 [x, y] 點 (TL、TR、BR、BL) +@msg counterPer `{c}`: item or file counterPer `{c}`:應為 item 或 file +@msg crop `{_1}`: only PDF pages have art, trim, bleed and media boxes; use "crop" or "bounding" crop `{_1}`:只有 PDF 頁面有 art、trim、bleed 和 media 方框;請使用 "crop" 或 "bounding" +@msg crop rectangle doesn't overlap the image 裁切矩形與影像沒有重疊 +@msg cross-reference and object streams aren't supported 不支援交互參照資料流和物件資料流 +@msg damaged compressed data: {e} 壓縮資料已損毀:{e} +@msg dash lengths must be numbers, got {v} 虛線長度必須是數字,收到 {v} +@msg dash must be a list of lengths or null, got {v} dash 必須是長度清單或 null,收到 {v} +@msg data key `{k}`: letters, digits, -, _ and . (not name or vc-…) 資料鍵 `{k}`:只能使用字母、數字、-、_ 和 . (不能是 name 或 vc-…) +@msg data must be an object of key: value, not {v} data 必須是 key: value 形式的物件,而非 {v} +@msg data set `{name}` holds a value for `{var}`, which the library doesn't declare 資料集 `{name}` 包含 `{var}` 的值,但資料庫未宣告該變數 +@msg data set `{name}` holds two values for `{var}` 資料集 `{name}` 包含 `{var}` 的兩個值 +@msg data set `{name}` is declared twice 資料集 `{name}` 宣告了兩次 +@msg data takes at most {MAX_DATA} keys at once data 一次最多接受 {MAX_DATA} 個鍵 +@msg dataset `{name}` already exists 資料集 `{name}` 已存在 +@msg dataset `{to}` already exists 資料集 `{to}` 已存在 +@msg date `{d}`: YYYY-MM-DD 日期 `{d}`:應為 YYYY-MM-DD +@msg decoded data is too large 解碼後的資料過大 +@msg define a variable first 請先定義變數 +@msg detect must be true or false detect 必須是 true 或 false +@msg direct-select anchor points of a path 請以直接選取方式選取路徑的錨點 +@msg distance must be > 0 distance 必須 > 0 +@msg dx and dy give the arrow's direction dx 和 dy 用來指定箭頭的方向 +@msg dx and dy must be numbers dx 和 dy 必須是數字 +@msg dxf fitTo must be [width, height], positive dxf fitTo 必須是正值的 [width, height] +@msg dxf must be an object of DXF import options dxf 必須是 DXF 匯入選項的物件 +@msg dxf scale must be a positive number up to {_1}, not {s} dxf scale 必須是不超過 {_1} 的正數,而非 {s} +@msg dxf unit `{u}`: a unit such as mm, cm, in or pt dxf unit `{u}`:應為 mm、cm、in 或 pt 這類單位 +@msg dxf: {e} dxf:{e} +@msg each format is an object {format, scale?, suffix?} 每個格式都是物件 {format, scale?, suffix?} +@msg each item needs an id 每個項目都需要 id +@msg each match needs `kind` 每個相符項目都需要 `kind` +@msg each match needs a `name` 每個相符項目都需要 `name` +@msg each of `fonts` is {family, style?}; 1 to 1000 of them `fonts` 的每一項都是 {family, style?};共 1 到 1000 項 +@msg each of `items` is {kind, item} `items` 的每一項都是 {kind, item} +@msg each of `items` is {{id, corners?}} with an object id, not {it} `items` 的每一項都是帶有物件 ID 的 {{id, corners?}},而非 {it} +@msg each row needs `from` 每一列都需要 `from` +@msg each stop needs a position 每個色標都需要位置 +@msg each subpath needs an anchors array 每條子路徑都需要 anchors 陣列 +@msg easingType must be easeIn, easeOut, easeInOut or easeOutIn easingType 必須是 easeIn、easeOut、easeInOut 或 easeOutIn +@msg editingData must be true or false editingData 必須是 true 或 false +@msg editingData must be true, false or "always" editingData 必須是 true、false 或 "always" +@msg edits overlap 編輯範圍重疊 +@msg effects of objects whose appearances differ can't be moved together 外觀不同的物件,其效果無法一起移動 +@msg empty header in column {_1} 第 {_1} 欄的標題為空 +@msg encoding `{_1}`: utf8 or utf16 編碼 `{_1}`:應為 utf8 或 utf16 +@msg ends must be two of "first" and "last" ends 必須是兩個值,各為 "first" 或 "last" +@msg every numbered name for the result is taken 結果可用的編號名稱都已被使用 +@msg expanded SVG styles exceed the import size limit 展開後的 SVG 樣式超過匯入大小上限 +@msg export presets file is larger than {MAX_PRESET_FILE_BYTES} bytes 匯出預設集檔案大於 {MAX_PRESET_FILE_BYTES} 位元組 +@msg exportText must be editable or appearance exportText 必須是 editable 或 appearance +@msg exportType must be movieClip or graphic, not `{s}` exportType 必須是 movieClip 或 graphic,而非 `{s}` +@msg extend needs id extend 需要 id +@msg featureChanges lists at most {MAX_FEATURE_CHANGES} tags featureChanges 最多列出 {MAX_FEATURE_CHANGES} 個標籤 +@msg featureChanges must be a list of tags featureChanges 必須是標籤清單 +@msg features must be a list of tags features 必須是標籤清單 +@msg fidelity must be 0..100 fidelity 必須是 0..100 +@msg files must be {name, dataBase64} files 必須是 {name, dataBase64} +@msg fit must be none|autoHeight|shrinkText|block, got {id} fit 必須是 none|autoHeight|shrinkText|block,收到 {id} +@msg flattener: {e} 平面化:{e} +@msg flattenerPreset `{name}`: high, medium, low or a saved one (see flattener.presets.list) flattenerPreset `{name}`:應為 high、medium、low 或已儲存的預設集 (請參閱 flattener.presets.list) +@msg flipProfile must be along|across, got {o} flipProfile 必須是 along|across,收到 {o} +@msg folders `{f}`: none, rows, format, item or itemFormat folders `{f}`:應為 none、rows、format、item 或 itemFormat +@msg folders deeper than {MAX_BATCH_DEPTH} levels 資料夾深度超過 {MAX_BATCH_DEPTH} 層 +@msg folders deeper than {MAX_DEPTH} levels 資料夾深度超過 {MAX_DEPTH} 層 +@msg font family `{family}` is not available 無法使用字體系列 `{family}` +@msg font family `{tf}` is not available 無法使用字體系列 `{tf}` +@msg format `{f}`: pdf or postscript format `{f}`:應為 pdf 或 postscript +@msg format `{f}`: text or json format `{f}`:應為 text 或 json +@msg format is `{format}` format 為 `{format}` +@msg formats must be an array of rows, not {v} formats 必須是列的陣列,而非 {v} +@msg frequency must be between 1 and 300 lines per inch frequency 必須介於每英寸 1 到 300 線之間 +@msg from and to must be finite from 和 to 必須是有限值 +@msg from must be [x0, y0, x1, y1] from 必須是 [x0, y0, x1, y1] +@msg give `before` or `after`, not both 請提供 `before` 或 `after`,不要兩者都提供 +@msg give `colors`, or `color` and `rule` 請提供 `colors`,或 `color` 和 `rule` +@msg give `event`, such as onclick 請提供 `event`,例如 onclick +@msg give `file`, the JavaScript file's path or URL 請提供 `file`,即 JavaScript 檔案的路徑或 URL +@msg give `fill` and/or `stroke` 請提供 `fill` 和/或 `stroke` +@msg give `fill`, `stroke` or both 請提供 `fill`、`stroke` 或兩者 +@msg give `folder` 請提供 `folder` +@msg give `fonts`, or open a document 請提供 `fonts`,或開啟文件 +@msg give `from` or `indices`, not both 請提供 `from` 或 `indices`,不要兩者都提供 +@msg give `id` (no text is being edited) 請提供 `id` (目前沒有正在編輯的文字) +@msg give `id` and `anchors`, or `items`, not both 請提供 `id` 和 `anchors`,或提供 `items`,不要兩者都提供 +@msg give `id` or `guide`, not both 請提供 `id` 或 `guide`,不要兩者都提供 +@msg give `length` or `to` 請提供 `length` 或 `to` +@msg give `matches`: [{kind, name, target}] 請提供 `matches`: [{kind, name, target}] +@msg give `name` (or edit a pattern) 請提供 `name` (或編輯圖樣) +@msg give `name` or `names` 請提供 `name` 或 `names` +@msg give `path` (a .wasm file) or `dataBase64` (the module) 請提供 `path` (.wasm 檔案) 或 `dataBase64` (模組) +@msg give `path`, `data` or `dataBase64` 請提供 `path`、`data` 或 `dataBase64` +@msg give `path`, `data`, `dataBase64` or `csv` 請提供 `path`、`data`、`dataBase64` 或 `csv` +@msg give `path`, `xml` or `dataBase64` 請提供 `path`、`xml` 或 `dataBase64` +@msg give `script`, the JavaScript the event runs ("" removes the event) 請提供 `script`,即事件執行的 JavaScript ("" 會移除事件) +@msg give `text` (the reading) or `remove` 請提供 `text` (讀音) 或 `remove` +@msg give `x` and `y` (and a `tolerance` of 0 or more) 請提供 `x` 和 `y` (以及大於或等於 0 的 `tolerance`) +@msg give a mode or r/g/b, c/m/y/k, gray or tint adjustments 請提供模式,或 r/g/b、c/m/y/k、gray 或 tint 調整值 +@msg give a name, or paint the active proxy with a saved preset 請提供名稱,或以已儲存的預設集為作用中的代理上色 +@msg give a name, or select a stroke with a saved profile 請提供名稱,或選取使用已儲存描述檔的筆畫 +@msg give a pattern name or select an object painted with a pattern 請提供圖樣名稱,或選取以圖樣上色的物件 +@msg give at least one of clip, invert, disabled, linked clip、invert、disabled、linked 請至少提供一個 +@msg give color, none, swatch or gradient 請提供 color、none、swatch 或 gradient +@msg give dataBase64 請提供 dataBase64 +@msg give either at (a click) or area (a path drawn around the overlaps) 請提供 at (一次點按) 或 area (圍繞重疊處繪製的路徑) 其中之一 +@msg give formats or a preset, not both 請提供 formats 或預設集,不要兩者都提供 +@msg give newName or delete 請提供 newName 或 delete +@msg give offset or by 請提供 offset 或 by +@msg give one of `to`, `rect` or `at` 請提供 `to`、`rect` 或 `at` 其中一個 +@msg give one of assets, layers, selection or fullDocument 請提供 assets、layers、selection 或 fullDocument 其中一個 +@msg give only one of onto, above, below, icon and a column place onto、above、below、icon 和欄位置只能提供其中一個 +@msg give origin: [x, y], or reset: true 請提供 origin: [x, y],或 reset: true +@msg give overprintFill, overprintStroke, showCenter, imageMap, url or note 請提供 overprintFill、overprintStroke、showCenter、imageMap、url 或 note +@msg give path (a file) or folder 請提供 path (檔案) 或 folder +@msg give path, or name and dataBase64 請提供 path,或 name 和 dataBase64 +@msg give paths or files 請提供 paths 或 files +@msg give rows, rowHeight, columns or columnWidth 請提供 rows、rowHeight、columns 或 columnWidth +@msg give svg, or dataBase64 of an SVG or SVGZ file 請提供 svg,或 SVG 或 SVGZ 檔案的 dataBase64 +@msg give text 請提供 text +@msg give the asset a name 請為資產命名 +@msg give the preset a `name` 請為預設集提供 `name` +@msg give the preset a name 請為預設集命名 +@msg give the preset a name (1–64 characters) 請為預設集命名 (1–64 個字元) +@msg give the settings to change, e.g. {"formats"}]} 請提供要變更的設定,例如 {"formats"}]} +@msg give the style a name 請為樣式命名 +@msg give two or more style `names` 請在 `names` 提供兩個以上的樣式名稱 +@msg give two or more swatches 請提供兩個以上的色票 +@msg give x, y, or a handle's length or angle 請提供 x、y,或控制把手的長度或角度 +@msg give {key, value} or {values} 請提供 {key, value} 或 {values} +@msg global must be true or false global 必須是 true 或 false +@msg glyph {_1} is not drawn for {ch} with the character's style (such as All Caps, Small Caps or a numeral system) 以該字元的樣式 (例如全部大寫、小型大寫或數字系統) 繪製 {ch} 時不會使用字符 {_1} +@msg glyph {g} is not an alternate of {ch} in {_1} {_2} 字符 {g} 不是 {_1} {_2} 中 {ch} 的替代字 +@msg gradient must be "objects" or "mesh" gradient 必須是 "objects" 或 "mesh" +@msg grays must be "profile" or "black", not `{g}` grays 必須是 "profile" 或 "black",而非 `{g}` +@msg gridColors must be a preset name or two colours gridColors 必須是預設集名稱或兩種顏色 +@msg gridSize must be small, medium or large gridSize 必須是 small、medium 或 large +@msg guide {g} is not selected 參考線 {g} 未選取 +@msg handle must be 0..3 handle 必須是 0..3 +@msg hiddenObjects {v}: "layer" (the default), "omit" or "visible" hiddenObjects {v}:應為 "layer" (預設值)、"omit" 或 "visible" +@msg highlight a layer to merge into 請反白標示要合併到的圖層 +@msg highlight two or more rows in one layer or group 請在同一個圖層或群組中反白標示兩列以上 +@msg highlight two or more rows to merge 請反白標示兩列以上以進行合併 +@msg icon docks a panel in the icon column: use window.panel.dock icon 會將面板停駐在圖示欄:請使用 window.panel.dock +@msg id must be a dimension id id 必須是尺寸標註 ID +@msg image has no bounds 影像沒有邊界 +@msg image {_1} is linked already 影像 {_1} 已經是連結影像 +@msg imageMap `{m}`: none, client or server imageMap `{m}`:應為 none、client 或 server +@msg index out of range 索引超出範圍 +@msg instances must be 1..1000 instances 必須是 1..1000 +@msg invalid `color` `color` 無效 +@msg invalid anchor index {v}: expected a non-negative integer 錨點索引 {v} 無效:應為非負整數 +@msg invalid anchor reference {v}: expected [subpath, anchor] 錨點參照 {v} 無效:應為 [subpath, anchor] +@msg invalid angle 角度無效 +@msg invalid brush: {e} 筆刷無效:{e} +@msg invalid color 顏色無效 +@msg invalid colour {c} 顏色 {c} 無效 +@msg invalid delta 位移量無效 +@msg invalid point 點無效 +@msg invalid size 大小無效 +@msg invalid t t 無效 +@msg invalid tolerance 容許度無效 +@msg its artboards all lie beyond the canvas (more than {_1} pt from the origin) 其工作區域全都位於畫布之外 (距離原點超過 {_1} pt) +@msg its clipping masks are nested too deeply 其剪裁遮色片的巢狀層次過深 +@msg its metadata has no description 其中繼資料沒有描述 +@msg its metadata has no direct length 其中繼資料沒有直接長度 +@msg join two different paths 請連接兩條不同的路徑 +@msg justify must be auto|left|center|right|justifyAll justify 必須是 auto|left|center|right|justifyAll +@msg kbps must be a positive number, not {kbps} kbps 必須是正數,而非 {kbps} +@msg keywords must be a list of words or a comma-separated string keywords 必須是單字清單或以逗號分隔的字串 +@msg keywords must be at most {MAX_KEYWORD} characters, without control characters keywords 最多 {MAX_KEYWORD} 個字元,且不含控制字元 +@msg kind must be 1, 2 or 3, or give a preset `name` (see perspective.presets.list) kind 必須是 1、2 或 3,或提供預設集的 `name` (請參閱 perspective.presets.list) +@msg kind must be graphic, fillColor, strokeColor, fillGradient, strokeGradient, fillPattern, strokePattern, charStyle or paraStyle kind 必須是 graphic、fillColor、strokeColor、fillGradient、strokeGradient、fillPattern、strokePattern、charStyle 或 paraStyle +@msg knockout must be "on", "off", "neutral" or a bool, not {v} knockout 必須是 "on"、"off"、"neutral" 或布林值,而非 {v} +@msg layer `{name}` has no art to export 圖層 `{name}` 沒有可匯出的圖稿 +@msg layer must name a layer or sublayer layer 必須指定圖層或子圖層 +@msg layers can't be intertwined: select the objects in them 圖層無法交織:請選取其中的物件 +@msg layers go only at the top level or in layers, objects in layers and groups 圖層只能放在最上層或圖層中,物件只能放在圖層和群組中 +@msg layers must be true or false layers 必須是 true 或 false +@msg layout must be gridByRow, gridByColumn, row or column layout 必須是 gridByRow、gridByColumn、row 或 column +@msg leading must be a number or "auto" leading 必須是數字或 "auto" +@msg left/right must be non-negative widths left/right 必須是非負的寬度 +@msg level `{t}`: 2 or 3 level `{t}`:應為 2 或 3 +@msg line {line}: more than {MAX_CSV_COLS} columns 第 {line} 行:超過 {MAX_CSV_COLS} 欄 +@msg line {line}: unclosed quote 第 {line} 行:引號未結束 +@msg line {line}: value for `{var}` must match its variable kind 第 {line} 行:`{var}` 的值必須符合其變數種類 +@msg lineEndings `{other}`: lf or crlf lineEndings `{other}`:應為 lf 或 crlf +@msg loading profiles from disk isn't available in the browser 瀏覽器中無法從磁碟載入描述檔 +@msg margin: a {m} pt margin leaves no imageable area on the paper margin:{m} pt 的邊界使紙張上沒有可列印區域 +@msg matrix must be finite and invertible, depth finite matrix 必須是有限且可逆的矩陣,depth 必須是有限值 +@msg matte: {e} matte:{e} +@msg member is for order front, forward, backward or back member 用於 order 為 front、forward、backward 或 back 的情況 +@msg missing `artboards` 未提供 `artboards` +@msg missing `at` [x, y] 未提供 `at` [x, y] +@msg missing `attrs` 未提供 `attrs` +@msg missing `color` or `opacity` 未提供 `color` 或 `opacity` +@msg missing `colors` 未提供 `colors` +@msg missing `commands` 未提供 `commands` +@msg missing `destinationFolder` 未提供 `destinationFolder` +@msg missing `effect` id 未提供 `effect` ID +@msg missing `family` 未提供 `family` +@msg missing `find` 未提供 `find` +@msg missing `gid` (a glyph id, or null for the default glyph) 未提供 `gid` (字符 ID,或以 null 表示預設字符) +@msg missing `group` 未提供 `group` +@msg missing `id` 未提供 `id` +@msg missing `id`: give one, or select one type object 未提供 `id`:請提供 ID,或選取一個文字物件 +@msg missing `index` (a point index, or null to clear) 未提供 `index` (點的索引,或以 null 清除) +@msg missing `index` (a stop index, or null to clear) 未提供 `index` (色標索引,或以 null 清除) +@msg missing `index` (an item index or null) 未提供 `index` (項目索引或 null) +@msg missing `item` 未提供 `item` +@msg missing `library` 未提供 `library` +@msg missing `library` (see graphicStyle.libraries) 未提供 `library` (請參閱 graphicStyle.libraries) +@msg missing `library` (see swatch.library.list) 未提供 `library` (請參閱 swatch.library.list) +@msg missing `map` (rows [{from, to}] or {current}) 未提供 `map` (列 [{from, to}] 或 {current}) +@msg missing `matrix` [a,b,c,d,e,f] 未提供 `matrix` [a,b,c,d,e,f] +@msg missing `name` (see gradient.presets.list) 未提供 `name` (請參閱 gradient.presets.list) +@msg missing `offset` (a distance in points) 未提供 `offset` (以點為單位的距離) +@msg missing `path` 未提供 `path` +@msg missing `path` (a path object id) 未提供 `path` (路徑物件 ID) +@msg missing `rule` 未提供 `rule` +@msg missing `source` id 未提供 `source` ID +@msg missing `start` (the byte offset of a character) 未提供 `start` (字元的位元組偏移) +@msg missing `status`: linked, embedded, missing or modified 未提供 `status`:應為 linked、embedded、missing 或 modified +@msg missing `target` id 未提供 `target` ID +@msg missing `text` 未提供 `text` +@msg missing `to` 未提供 `to` +@msg missing `to` (an index) 未提供 `to` (索引) +@msg missing `to`: a non-negative integer 未提供 `to`:應為非負整數 +@msg missing `type` 未提供 `type` +@msg missing `value` 未提供 `value` +@msg missing `{key}` 未提供 `{key}` +@msg missing `{k}` 未提供 `{k}` +@msg missing anchor 未提供錨點 +@msg missing anchors 未提供 anchors +@msg missing anchors [[subpath, anchor]…] 未提供 anchors [[subpath, anchor]…] +@msg missing array `{key}` 未提供陣列 `{key}` +@msg missing case 未提供 case +@msg missing color 未提供顏色 +@msg missing commands 未提供 commands +@msg missing destination folder 未提供目的地資料夾 +@msg missing from 未提供 from +@msg missing group 未提供 group +@msg missing id or ids 未提供 id 或 ids +@msg missing ids 未提供 ids +@msg missing indexes 未提供 indexes +@msg missing matrix [a,b,c,d,e,f] 未提供 matrix [a,b,c,d,e,f] +@msg missing name 未提供名稱 +@msg missing op 未提供 op +@msg missing or invalid `color` `color` 未提供或無效 +@msg missing or unknown `tool` `tool` 未提供或未知 +@msg missing point 未提供點 +@msg missing point [x,y] 未提供點 [x,y] +@msg missing point `{key}` ([x, y]) 未提供點 `{key}` ([x, y]) +@msg missing points 未提供 points +@msg missing points [[x,y]…] 未提供 points [[x,y]…] +@msg missing segment 未提供線段 +@msg missing stops 未提供色標 +@msg missing subpaths 未提供 subpaths +@msg missing target 未提供 target +@msg missing to 未提供 to +@msg missing x, y 未提供 x、y +@msg mode is set, add or toggle, not `{other}` mode 是 set、add 或 toggle,而非 `{other}` +@msg mode must be "cmyk" or "rgb" mode 必須是 "cmyk" 或 "rgb" +@msg mode must be area|onPath, got {o} mode 必須是 area|onPath,收到 {o} +@msg more than 10000 linked files: package dependencies in smaller parts 連結的檔案超過 10000 個:請分成較小的部分封裝相依檔案 +@msg more than 256 commands 超過 256 個指令 +@msg more than {MAX_BATCH_FILES} data sets 超過 {MAX_BATCH_FILES} 個資料集 +@msg more than {MAX_BATCH_FILES} files 超過 {MAX_BATCH_FILES} 個檔案 +@msg more than {MAX_CSV_ROWS} data rows 超過 {MAX_CSV_ROWS} 個資料列 +@msg more than {MAX_FILES} images 超過 {MAX_FILES} 個影像 +@msg more than {MAX_IMPORT} presets 超過 {MAX_IMPORT} 個預設集 +@msg moved must be [[x,y]…] moved 必須是 [[x,y]…] +@msg name (a toolbar's name) is required 必須提供 name (工具列的名稱) +@msg name (a toolbar's name) must be a string name (工具列的名稱) 必須是字串 +@msg name must be a toolbar's name name 必須是工具列的名稱 +@msg names is empty names 為空 +@msg names must be an array of symbol names names 必須是符號名稱的陣列 +@msg need `anchor` or `segment` + `t` 需要 `anchor`,或 `segment` + `t` +@msg need at least one anchor 至少需要一個錨點 +@msg need at least one point 至少需要一個點 +@msg need at least two points 至少需要兩個點 +@msg needs points 需要 points +@msg nineSlice must be true or false nineSlice 必須是 true 或 false +@msg nineSliceGuides must be [left, top, right, bottom], each -16..16, with left + right < 1 and top + bottom < 1 nineSliceGuides 必須是 [left, top, right, bottom],各為 -16..16,且 left + right < 1、top + bottom < 1 +@msg no PDF preset named `{n}` 沒有名為 `{n}` 的 PDF 預設集 +@msg no action set is current 目前沒有使用中的動作組 +@msg no active data set 沒有使用中的資料集 +@msg no appearance item {index} 沒有外觀項目 {index} +@msg no artboard {_1} 沒有工作區域 {_1} +@msg no artboard {artboard} (0-based; the document has {_1}) 沒有工作區域 {artboard} (從 0 起算;文件有 {_1} 個) +@msg no asset {id} 沒有資產 {id} +@msg no asset {id} (see assets.list) 沒有資產 {id} (請參閱 assets.list) +@msg no assets to export 沒有可匯出的資產 +@msg no assets yet: collect art for export first (assets.add) 尚無資產:請先收集要匯出的圖稿 (assets.add) +@msg no brush named `{n}` 沒有名為 `{n}` 的筆刷 +@msg no character at byte {start} 位元組 {start} 處沒有字元 +@msg no colour 沒有顏色 +@msg no colour group `{group}` 沒有顏色群組 `{group}` +@msg no colour group `{name}` 沒有顏色群組 `{name}` +@msg no data sets 沒有資料集 +@msg no dataset named `{from}` 沒有名為 `{from}` 的資料集 +@msg no dataset named `{name}` 沒有名為 `{name}` 的資料集 +@msg no datasets 沒有資料集 +@msg no design named `{name}` 沒有名為 `{name}` 的設計 +@msg no design named `{n}` 沒有名為 `{n}` 的設計 +@msg no design named `{old}` 沒有名為 `{old}` 的設計 +@msg no encoder for {_1} yet 尚無 {_1} 的編碼器 +@msg no export preset `{name}` (see document.exportPresets.list) 沒有匯出預設集 `{name}` (請參閱 document.exportPresets.list) +@msg no folder: pass `path` or set Preferences › Plug-ins & Scratch Disks › Additional Plug-ins Folder 沒有資料夾:請傳入 `path`,或設定「偏好設定 › 增效模組 & 暫存磁碟 › 額外的增效模組資料夾」 +@msg no fonts to look for: they are all available 沒有需要尋找的字體:所有字體都可使用 +@msg no formats to export 沒有可匯出的格式 +@msg no gradient preset `{name}` (see gradient.presets.list) 沒有漸層預設集 `{name}` (請參閱 gradient.presets.list) +@msg no graphic style `{n}` in `{_1}` `{_1}` 中沒有繪圖樣式 `{n}` +@msg no graphic style library `{key}` (see graphicStyle.libraries) 沒有繪圖樣式資料庫 `{key}` (請參閱 graphicStyle.libraries) +@msg no guide selected 未選取參考線 +@msg no guide selected (or give an index) 未選取參考線 (或請提供索引) +@msg no guide {i} 沒有參考線 {i} +@msg no images in the folder 資料夾中沒有影像 +@msg no item at index {_1} 索引 {_1} 處沒有項目 +@msg no item at index {from} 索引 {from} 處沒有項目 +@msg no item at one of the indices {idx} 索引 {idx} 中有一個沒有對應的項目 +@msg no layer 沒有圖層 +@msg no layer {id} (see layer.list) 沒有圖層 {id} (請參閱 layer.list) +@msg no layers to export 沒有可匯出的圖層 +@msg no library `{key}` 沒有資料庫 `{key}` +@msg no metafile format 沒有中繼檔格式 +@msg no object {_1} 沒有物件 {_1} +@msg no objects 沒有物件 +@msg no parent layer 沒有父圖層 +@msg no perspective grid preset named `{b}` (see perspective.presets.list) 沒有名為 `{b}` 的透視格點預設集 (請參閱 perspective.presets.list) +@msg no perspective grid preset named `{n}` 沒有名為 `{n}` 的透視格點預設集 +@msg no point selected (give `index`) 未選取任何點 (請提供 `index`) +@msg no preset called `{from}` (see file.newPresets) 沒有名為 `{from}` 的預設集 (請參閱 file.newPresets) +@msg no preset called `{name}` (see file.newPresets) 沒有名為 `{name}` 的預設集 (請參閱 file.newPresets) +@msg no preset named `{n}` 沒有名為 `{n}` 的預設集 +@msg no print preset named `{b}` (see print.presets.list) 沒有名為 `{b}` 的列印預設集 (請參閱 print.presets.list) +@msg no print preset named `{name}` (presets: {_1}) 沒有名為 `{name}` 的列印預設集 (預設集:{_1}) +@msg no print preset named `{n}` 沒有名為 `{n}` 的列印預設集 +@msg no profile named `{name}` 沒有名為 `{name}` 的描述檔 +@msg no readable files in the folder 資料夾中沒有可讀取的檔案 +@msg no recovery copy `{f}` (see file.recovery.list) 沒有復原副本 `{f}` (請參閱 file.recovery.list) +@msg no rows 沒有列 +@msg no saved PDF preset named `{name}` 沒有名為 `{name}` 的已儲存 PDF 預設集 +@msg no saved export preset `{name}` 沒有已儲存的匯出預設集 `{name}` +@msg no saved gradient preset called {name} 沒有名為 {name} 的已儲存漸層預設集 +@msg no saved gradient presets 沒有已儲存的漸層預設集 +@msg no saved preset called `{name}` 沒有名為 `{name}` 的已儲存預設集 +@msg no saved presets to export (name [Default] in `names` to export it) 沒有可匯出的已儲存預設集 (若要匯出 [Default],請在 `names` 中指定它) +@msg no saved presets to export (name built-in ones in `names`) 沒有可匯出的已儲存預設集 (內建預設集請在 `names` 中指定) +@msg no saved print preset named `{name}` 沒有名為 `{name}` 的已儲存列印預設集 +@msg no saved profile called {name} 沒有名為 {name} 的已儲存描述檔 +@msg no saved selection `{name}` 沒有已儲存的選取範圍 `{name}` +@msg no saved theme called {name} (see colorTheme.list) 沒有名為 {name} 的已儲存主題 (請參閱 colorTheme.list) +@msg no saved views 沒有已儲存的檢視 +@msg no series {i} 沒有數列 {i} +@msg no slice {n} in the image (see slice.list) 影像中沒有切片 {n} (請參閱 slice.list) +@msg no source art 沒有來源圖稿 +@msg no stop {i} (the gradient has {n}) 沒有色標 {i} (漸層有 {n} 個) +@msg no style `{name}` 沒有樣式 `{name}` +@msg no such assets (see assets.list) 沒有這些資產 (請參閱 assets.list) +@msg no such frame anchor, or the frame would reach past the canvas 沒有這個文字框錨點,或文字框會超出畫布 +@msg no such objects 沒有這些物件 +@msg no such path anchor, or the path would reach past the canvas 沒有這個路徑錨點,或路徑會超出畫布 +@msg no such rows 沒有這些列 +@msg no swatch `{keep}` 沒有色票 `{keep}` +@msg no swatch `{n}` 沒有色票 `{n}` +@msg no swatch `{n}` (swatches and colour groups move separately) 沒有色票 `{n}` (色票和顏色群組要分開移動) +@msg no swatch library `{key}` (see swatch.library.list) 沒有色票資料庫 `{key}` (請參閱 swatch.library.list) +@msg no swatch library `{key}` (see swatch.library.list; "document": the document's swatches) 沒有色票資料庫 `{key}` (請參閱 swatch.library.list;"document":文件的色票) +@msg no swatch library `{key}` (see swatch.library.list; "{DOCUMENT_SWATCHES}": the document's swatches) 沒有色票資料庫 `{key}` (請參閱 swatch.library.list;"{DOCUMENT_SWATCHES}":文件的色票) +@msg no swatch named `{n}` 沒有名為 `{n}` 的色票 +@msg no swatch or colour group `{n}` 沒有色票或顏色群組 `{n}` +@msg no swatch or colour group `{n}` in `{_1}` `{_1}` 中沒有色票或顏色群組 `{n}` +@msg no symbol named `{name}` 沒有名為 `{name}` 的符號 +@msg no text objects selected 未選取文字物件 +@msg no toolbar named `{_1}` 沒有名為 `{_1}` 的工具列 +@msg no toolbar named `{name}` 沒有名為 `{name}` 的工具列 +@msg no tracing preset `{preset}` (see imageTrace.presets) 沒有描圖預設集 `{preset}` (請參閱 imageTrace.presets) +@msg no user library folder here (save with a path, or without one to get the data) 這裡沒有使用者資料庫資料夾 (請以路徑儲存,或不提供路徑以取得資料) +@msg no variable named `{from}` 沒有名為 `{from}` 的變數 +@msg no variable named `{name}` 沒有名為 `{name}` 的變數 +@msg no variable named `{var}` 沒有名為 `{var}` 的變數 +@msg no variable named `{v}` 沒有名為 `{v}` 的變數 +@msg no view named `{name}` 沒有名為 `{name}` 的檢視 +@msg node {_1} is not a graph 節點 {_1} 不是圖表 +@msg node {_1} is not an image 節點 {_1} 不是影像 +@msg node {_1} is not type 節點 {_1} 不是文字 +@msg not a PDF presets file (format `{_1}`) 不是 PDF 預設集檔案 (格式為 `{_1}`) +@msg not a PDF presets file: {e} 不是 PDF 預設集檔案:{e} +@msg not a Word document: its WordDocument stream doesn't start with a file information block 不是 Word 文件:其 WordDocument 資料流的開頭不是檔案資訊區塊 +@msg not a Word document: its compound file has no WordDocument stream 不是 Word 文件:其複合檔案沒有 WordDocument 資料流 +@msg not a Word document: its main part is not a WordprocessingML document 不是 Word 文件:其主要部分不是 WordprocessingML 文件 +@msg not a Word document: its package has no main document part 不是 Word 文件:其封裝沒有主要文件部分 +@msg not a closed path 不是封閉路徑 +@msg not a flattener presets file (format `{_1}`) 不是平面化預設集檔案 (格式為 `{_1}`) +@msg not a flattener presets file: {e} 不是平面化預設集檔案:{e} +@msg not a layer or group 不是圖層或群組 +@msg not a library file: {e} 不是資料庫檔案:{e} +@msg not a mesh envelope point 不是網格封套的點 +@msg not a perspective grid presets file (format `{_1}`) 不是透視格點預設集檔案 (格式為 `{_1}`) +@msg not a perspective grid presets file: {e} 不是透視格點預設集檔案:{e} +@msg not a print presets file (format `{_1}`) 不是列印預設集檔案 (格式為 `{_1}`) +@msg not a print presets file: {e} 不是列印預設集檔案:{e} +@msg not a stored or deflated central record 不是以儲存或 deflate 方式寫入的中央目錄記錄 +@msg not a valid SVGZ file: {e} 不是有效的 SVGZ 檔案:{e} +@msg not an RTF file: it doesn't start with {\rtf 不是 RTF 檔案:開頭不是 {\rtf +@msg not an image VectorCraft reads (see document.formats) 不是 VectorCraft 可讀取的影像 (請參閱 document.formats) +@msg not area type (text in a frame) outside perspective 不是透視以外的區域文字 (文字框中的文字) +@msg not editing an opacity mask 目前不在編輯不透明度遮色片 +@msg not type on a path outside perspective 不是透視以外的路徑文字 +@msg nothing prints 沒有可列印的內容 +@msg nothing to bind 沒有可綁定的內容 +@msg nothing to change 沒有要變更的內容 +@msg nothing to change: give dx, dy, hScale, vScale or rotation 沒有要變更的內容:請提供 dx、dy、hScale、vScale 或 rotation +@msg nothing to crop 沒有可裁切的內容 +@msg nothing to export 沒有可匯出的內容 +@msg nothing to export: the document has no visible art 沒有可匯出的內容:文件中沒有可見的圖稿 +@msg nothing to mark 沒有可標記的內容 +@msg nothing to print: every artboard picked is blank 沒有可列印的內容:選擇的工作區域全都是空白 +@msg nothing to print: the document has no art that prints 沒有可列印的內容:文件中沒有會列印的圖稿 +@msg object is not a path 物件不是路徑 +@msg object transparency cannot be sampled onto highlighted characters; disable Transparency in Eyedropper Options or select the whole object 物件透明度無法取樣到反白標示的字元上;請在「滴管選項」中停用「透明度」,或選取整個物件 +@msg object {_1} can't be set as point type 物件 {_1} 無法設為點狀文字 +@msg object {_1} has lost its file's contents: relink it 物件 {_1} 已遺失其檔案的內容:請重新連結 +@msg object {_1} has no path 物件 {_1} 沒有路徑 +@msg object {_1} has no size 物件 {_1} 沒有大小 +@msg object {_1} is hidden or locked, or on a locked artboard 物件 {_1} 已隱藏或鎖定,或位於鎖定的工作區域上 +@msg object {_1} is not a placed document 物件 {_1} 不是置入的文件 +@msg object {_1} is not an Intertwine group 物件 {_1} 不是交織群組 +@msg object {_1} is not an image 物件 {_1} 不是影像 +@msg object {_1} is not an image or a linked file 物件 {_1} 不是影像或連結的檔案 +@msg object {_1} is not an image or a placed document 物件 {_1} 不是影像或置入的文件 +@msg object {_1} is not in this Intertwine group 物件 {_1} 不在此交織群組中 +@msg object {_1} needs a 3D effect at index {index} 物件 {_1} 在索引 {index} 處需要 3D 效果 +@msg object {id} has anchors 0–{_1} for `corners`, not {past} 物件 {id} 可用於 `corners` 的錨點為 0–{_1},沒有 {past} +@msg object {id} has {n} anchors, so no anchor {past} 物件 {id} 有 {n} 個錨點,因此沒有錨點 {past} +@msg objects must be none, move or copy objects 必須是 none、move 或 copy +@msg objects were left out 有物件已略過 +@msg offset out of range 偏移超出範圍 +@msg on must be true or false on 必須是 true 或 false +@msg only groups, layers, type and images have a Contents (Characters) row 只有群組、圖層、文字和影像有「內容 (字元)」列 +@msg only interior mesh lines can be deleted 只能刪除內部的網格線 +@msg only solid colours can be added (not gradients or patterns) 只能加入純色 (不能加入漸層或圖樣) +@msg only solid-colour swatches can be spot colours 只有純色色票可以是特別色 +@msg only this Affinity file's embedded preview could be read: use File › Open to see it with its warning, or export SVG or PDF from Affinity first 只能讀取此 Affinity 檔案的內嵌預視:請使用「檔案 › 開啟」查看它及其警告,或先從 Affinity 匯出 SVG 或 PDF +@msg only this Affinity file's embedded preview could be read; use File › Open to see it with its warning 只能讀取此 Affinity 檔案的內嵌預視;請使用「檔案 › 開啟」查看它及其警告 +@msg onto, above, below, icon and a column place belong to window.panel.float and window.panel.dock onto、above、below、icon 和欄位置屬於 window.panel.float 和 window.panel.dock +@msg onto, above, below, icon and a column place take no anchor, side, zone or before onto、above、below、icon 和欄位置不接受 anchor、side、zone 或 before +@msg onto, above, below, icon and a column place take no x, y, width or height onto、above、below、icon 和欄位置不接受 x、y、width 或 height +@msg open a document to look for its linked files 請開啟文件以尋找其連結的檔案 +@msg options must be an object (see file.formatOptions) options 必須是物件 (請參閱 file.formatOptions) +@msg order must be leftToRight or rightToLeft order 必須是 leftToRight 或 rightToLeft +@msg orientation must be portrait or landscape, not `{o}` orientation 必須是 portrait 或 landscape,而非 `{o}` +@msg outlineText {v}: true or false outlineText {v}:應為 true 或 false +@msg output intent profile: {e} 輸出目的描述檔:{e} +@msg output.destination: no RGB or CMYK profile is called “{name}” output.destination:沒有名為「{name}」的 RGB 或 CMYK 描述檔 +@msg output.destination: {_1} files are CMYK, and “{name}” is an RGB profile output.destination:{_1} 檔案為 CMYK,而「{name}」是 RGB 描述檔 +@msg output.destination: {e} output.destination:{e} +@msg output.inks: no ink is set to print output.inks:沒有任何油墨設定為列印 +@msg output.outputIntent: no profile is called “{name}”, and a {std} output intent embeds its profile output.outputIntent:沒有名為「{name}」的描述檔,而 {std} 輸出目的會內嵌其描述檔 +@msg output.outputIntent: no profile is called “{name}”: a {std} output intent embeds a profile, or names a registered printing condition (outputConditionId and registry) output.outputIntent:沒有名為「{name}」的描述檔:{std} 輸出目的會內嵌描述檔,或指定已註冊的印刷條件 (outputConditionId 和 registry) +@msg output.outputIntent: {std} files print in CMYK, and “{name}” is an RGB profile output.outputIntent:{std} 檔案以 CMYK 列印,而「{name}」是 RGB 描述檔 +@msg output.outputIntent: “{name}” is a grey profile, which can't be a {std} output intent output.outputIntent:「{name}」是灰階描述檔,不能作為 {std} 輸出目的 +@msg overlap: {o} pt is half a tile or more overlap:{o} pt 已達拼貼的一半以上 +@msg overlapping Shaper paths must be in the same layer or group 重疊的 Shaper 路徑必須位於同一個圖層或群組 +@msg overlapping edits 編輯範圍重疊 +@msg page art conflicts with image data for {key} 頁面圖稿與 {key} 的影像資料衝突 +@msg page art conflicts with pattern {name} 頁面圖稿與圖樣 {name} 衝突 +@msg page art conflicts with swatch {name} 頁面圖稿與色票 {name} 衝突 +@msg page art is missing image data for {key} 頁面圖稿沒有 {key} 的影像資料 +@msg page art is missing pattern {name} 頁面圖稿沒有圖樣 {name} +@msg page art is missing swatch {name} 頁面圖稿沒有色票 {name} +@msg page must be a whole number from 1 page 必須是從 1 起算的整數 +@msg page thumbnail: {e} 頁面縮圖:{e} +@msg page {page} of the PDF has no objects PDF 的第 {page} 頁沒有物件 +@msg page {page}: `{file}` has {n} {artboards} 第 {page} 頁:`{file}` 有 {n} {artboards} +@msg page {page}: `{name}` has {n} {pages} 第 {page} 頁:`{name}` 有 {n} {pages} +@msg pages must be a range such as "2-3" or a page number, not {v} pages 必須是 "2-3" 這類範圍或頁碼,而非 {v} +@msg pages: {e} pages:{e} +@msg panel position must be finite 面板位置必須是有限值 +@msg parameters must be an object 參數必須是物件 +@msg params must be an object params 必須是物件 +@msg passwords can have up to {MAX_PASSWORD} bytes 密碼最多 {MAX_PASSWORD} 位元組 +@msg path has no open end 路徑沒有開放的端點 +@msg paths must be strings paths 必須是字串 +@msg pdfCompatible: false needs every artboard to keep the editable artwork pdfCompatible: false 需要所有工作區域才能保留可編輯的圖稿 +@msg pdfs `{m}`: single or multiple pdfs `{m}`:應為 single 或 multiple +@msg pickColorFrom is "artwork" or "swatches", not {v} pickColorFrom 是 "artwork" 或 "swatches",而非 {v} +@msg pins and moved must be non-empty lists of the same length pins 和 moved 必須是長度相同的非空清單 +@msg pins must be [[x,y]…] pins 必須是 [[x,y]…] +@msg pins must be finite pins 必須是有限值 +@msg place is above, below or inside, not `{other}` place 是 above、below 或 inside,而非 `{other}` +@msg plane must be left|right|ground plane 必須是 left|right|ground +@msg plane must be left|right|ground|none plane 必須是 left|right|ground|none +@msg point is outside the mesh 點位於網格之外 +@msg points must be [t, left, right] with non-negative widths points 必須是寬度為非負值的 [t, left, right] +@msg points must be a non-empty [[x,y,pressure?]…] list points 必須是非空的 [[x,y,pressure?]…] 清單 +@msg points must be a non-empty list of finite [x,y] points 必須是由有限 [x,y] 組成的非空清單 +@msg points must be an array or null points 必須是陣列或 null +@msg points must be finite points 必須是有限值 +@msg points must be finite [x,y] pairs points 必須是有限的 [x,y] 配對 +@msg points must contain 1–4096 coordinates points 必須包含 1–4096 個座標 +@msg position must be normal, superscript or subscript position 必須是 normal、superscript 或 subscript +@msg position must be topLeft, topRight, bottomLeft or bottomRight position 必須是 topLeft、topRight、bottomLeft 或 bottomRight +@msg positions must be between 0 and 100000 pt positions 必須介於 0 到 100000 pt 之間 +@msg ppi must be a positive number, not {ppi} ppi 必須是正數,而非 {ppi} +@msg ppi must be between 1 and 2400 ppi 必須介於 1 和 2400 之間 +@msg preserve `{v}` is not transforms|bounds|fileDimensions|fit|fill preserve `{v}` 不是 transforms|bounds|fileDimensions|fit|fill +@msg preserveShape must be clippingMask|transparency preserveShape 必須是 clippingMask|transparency +@msg preset `{id}`: mobile or density preset `{id}`:應為 mobile 或 density +@msg preset must be standard, diffuse, topLeft or right preset 必須是 standard、diffuse、topLeft 或 right +@msg preset must be the name of a print preset preset 必須是列印預設集的名稱 +@msg previewMode must be default, pixel or overprint previewMode 必須是 default、pixel 或 overprint +@msg print settings: {e} 列印設定:{e} +@msg procedures nest too deeply 程序的巢狀層次過深 +@msg procedures nested too deeply 程序的巢狀層次過深 +@msg quotes must be {double?, single?} quotes 必須是 {double?, single?} +@msg quotes.{k} must be an opening and a closing quote, e.g. "“”" quotes.{k} 必須是一個前引號和一個後引號,例如 "“”" +@msg rasterEffectsPpi must be 1–2400 (72 screen, 150 medium, 300 high) rasterEffectsPpi 必須是 1–2400 (72 螢幕、150 中、300 高) +@msg rating must be a whole number from 0 to {MAX_RATING} rating 必須是 0 到 {MAX_RATING} 之間的整數 +@msg rect and {k} contradict each other: give the area or the artboards rect 和 {k} 互相矛盾:請提供區域或工作區域 +@msg rect applies to raster formats, not {_1} rect 適用於點陣格式,不適用於 {_1} +@msg rect is [x, y, width, height] in points rect 是以點為單位的 [x, y, width, height] +@msg rect must be [x, y, width, height] rect 必須是 [x, y, width, height] +@msg rect must be [x, y, width, height] with a positive width and height rect 必須是寬度和高度為正值的 [x, y, width, height] +@msg rect needs finite numbers and a positive width and height rect 需要有限的數字,以及正值的寬度和高度 +@msg redraw needs id redraw 需要 id +@msg redraw within must be a finite distance of 0 or more redraw 的 within 必須是大於或等於 0 的有限距離 +@msg registration must be 0..8 registration 必須是 0..8 +@msg release a layer or a group 請釋放圖層或群組 +@msg replace keeps the replaced object's place and transform: drop template, at and rect replace 會保留被取代物件的位置和變形:請不要提供 template、at 和 rect +@msg replace: select the one object to replace replace:請選取要取代的那一個物件 +@msg resolution must be a number or screen|medium|high resolution 必須是數字或 screen|medium|high +@msg resolution must be between 1 and 2400 ppi resolution 必須介於 1 到 2400 ppi 之間 +@msg rotation must be a number of degrees rotation 必須是以度為單位的數字 +@msg rotation must be finite rotation 必須是有限值 +@msg rows and cols must be 1..50 rows 和 cols 必須是 1..50 +@msg rows and columns must be 1..500 rows 和 columns 必須是 1..500 +@msg rows of objects whose appearances differ can't be reordered together 外觀不同的物件,其列無法一起重新排序 +@msg save the document first: Package collects a saved document 請先儲存文件:「封裝」會收集已儲存的文件 +@msg save the document first: copy puts the file in its folder 請先儲存文件:copy 會將檔案放入文件的資料夾 +@msg savedPreset: {e} savedPreset:{e} +@msg scale `{s}`: a factor such as 2x, a width (100w), a height (100h) or a resolution (72ppi) scale `{s}`:應為 2x 這類倍數、寬度 (100w)、高度 (100h) 或解析度 (72ppi) +@msg scale must be a number above 0, at most 64 scale 必須是大於 0 且不超過 64 的數字 +@msg scale must be non-zero scale 不能為零 +@msg scope must be selection or all (got {other}) scope 必須是 selection 或 all (收到 {other}) +@msg scribble is too long 塗抹筆跡過長 +@msg segment does not exist 線段不存在 +@msg select a Shaper group 請選取 Shaper 群組 +@msg select a blend to set easing or color shift 請選取漸變物件以設定緩動或顏色偏移 +@msg select a compound shape 請選取複合形狀 +@msg select a graph 請選取圖表 +@msg select a group or layer with visible, unlocked members 請選取含有可見且未鎖定成員的群組或圖層 +@msg select a layer 請選取圖層 +@msg select a text object 請選取文字物件 +@msg select an image (or an Image Trace group) 請選取影像 (或影像描圖群組) +@msg select an image, or pass id 請選取影像,或傳入 id +@msg select an object (or pass `id`) 請選取物件 (或傳入 `id`) +@msg select an object with a freeform gradient 請選取具有任意形狀漸層的物件 +@msg select an object with an opacity mask 請選取具有不透明度遮色片的物件 +@msg select area type 請選取區域文字 +@msg select area type (text in a frame) 請選取區域文字 (文字框中的文字) +@msg select area type and closed paths (at least one area type object) 請選取區域文字和封閉路徑 (至少一個區域文字物件) +@msg select area type whose first line can fit its frame 請選取第一行可容納於文字框的區域文字 +@msg select artwork to add its colours 請選取圖稿以加入其顏色 +@msg select artwork to make a group of its colours 請選取圖稿以將其顏色建立為群組 +@msg select artwork to recolour, or give a colour `group` 請選取要重新上色的圖稿,或提供顏色 `group` +@msg select exactly two path ends to join 請剛好選取兩個要連接的路徑端點 +@msg select members of a compound shape 請選取複合形狀的成員 +@msg select objects or give ids 請選取物件或提供 ids +@msg select objects to align to the guide 請選取要對齊參考線的物件 +@msg select one Intertwine group 請選取一個交織群組 +@msg select one image or pass id 請選取一個影像或傳入 id +@msg select paths 請選取路徑 +@msg select paths or compound paths 請選取路徑或複合路徑 +@msg select rows or objects to collect 請選取要收集的列或物件 +@msg select something to export 請選取要匯出的內容 +@msg select something to export (or turn off selectedOnly) 請選取要匯出的內容 (或關閉 selectedOnly) +@msg select text to redefine the style from 請選取用來重新定義樣式的文字 +@msg select the art and, on top of it, the mask object 請選取圖稿,以及位於其上方的遮色片物件 +@msg select the art for the design 請選取設計要使用的圖稿 +@msg select the art for the pattern tile 請選取圖樣拼貼要使用的圖稿 +@msg select the art to add first 請先選取要加入的圖稿 +@msg select the art to collect (or give its ids) 請選取要收集的圖稿 (或提供其 ids) +@msg select the content and a path on top 請選取內容以及位於上方的路徑 +@msg select the images to relink, or pass ids 請選取要重新連結的影像,或傳入 ids +@msg select the images, or pass ids 請選取影像,或傳入 ids +@msg select the linked images or placed documents, or pass ids 請選取連結的影像或置入的文件,或傳入 ids +@msg select the object to copy from 請選取要從中複製的物件 +@msg select the objects (or give their ids) 請選取物件 (或提供其 ids) +@msg select the objects to attach to the path 請選取要附加到路徑的物件 +@msg select the objects to bind 請選取要綁定的物件 +@msg select two or more objects to intertwine 請選取兩個以上要交織的物件 +@msg select two or more slices to combine 請選取兩個以上要合併的切片 +@msg select type on a path 請選取路徑文字 +@msg selection `{m}`: one or each selection `{m}`:應為 one 或 each +@msg settings is an object of document.exportForScreens params settings 是 document.exportForScreens 參數的物件 +@msg settings must be an object settings 必須是物件 +@msg show `{show}`: all, missing, modified or embedded show `{show}`:應為 all、missing、modified 或 embedded +@msg show must be true or false show 必須是 true 或 false +@msg size must be "small", "medium", "large" or a number of points over 0 up to {_1} size 必須是 "small"、"medium"、"large",或大於 0 且不超過 {_1} 的點數 +@msg size must be positive size 必須是正值 +@msg sizeMode is "fixed" or "pressure", not `{other}` sizeMode 是 "fixed" 或 "pressure",而非 `{other}` +@msg sizeMode is "fixed" or "pressure", not {other} sizeMode 是 "fixed" 或 "pressure",而非 {other} +@msg sizeVariation must be 0 or more sizeVariation 必須大於或等於 0 +@msg smallCaps must be true or false smallCaps 必須是 true 或 false +@msg sort `{x}`: name, kind or status sort `{x}`:應為 name、kind 或 status +@msg source paths are too large for Shaper 來源路徑對 Shaper 而言過大 +@msg spot, mode and group apply to solid colours only spot、mode 和 group 只適用於純色 +@msg status `{s}`: linked, embedded, missing or modified status `{s}`:應為 linked、embedded、missing 或 modified +@msg steps must be 1..1000 steps 必須是 1..1000 +@msg steps must be 1..{MAX_STEPS} steps 必須是 1..{MAX_STEPS} +@msg stop {i}: `plates` must be four numbers from 0 to 1 (C, M, Y, K) 色標 {i}:`plates` 必須是四個 0 到 1 之間的數字 (C、M、Y、K) +@msg stopped before the archive was finished 在封存檔完成之前已停止 +@msg strokeMode must be within|along|across, got {m} strokeMode 必須是 within|along|across,收到 {m} +@msg strokeOptions must be an object of stroke.set options strokeOptions 必須是 stroke.set 選項的物件 +@msg strokeWidth must be a positive number of pixels strokeWidth 必須是正的像素數 +@msg subpath {si} is not an open subpath 子路徑 {si} 不是開放的子路徑 +@msg subpaths required when joining the same path 連接同一條路徑時必須提供 subpaths +@msg swatchConflict must be "merge" or "add", not {v} swatchConflict 必須是 "merge" 或 "add",而非 {v} +@msg text must be {characterSet?, platform?, removeLineReturns?, removeParagraphReturns?, replaceSpaces?} text 必須是 {characterSet?, platform?, removeLineReturns?, removeParagraphReturns?, replaceSpaces?} +@msg text transform is collapsed or unrepresentable 文字變形已塌陷或無法表示 +@msg text.replaceSpaces must be a whole number from 2 to 100 text.replaceSpaces 必須是 2 到 100 之間的整數 +@msg text.{key} `{v}`: use "{_1}" or "{_2}" text.{key} `{v}`:請使用 "{_1}" 或 "{_2}" +@msg textureImage: give {path} or {name, dataBase64} of an image file, or a texture as effect.list gives it textureImage:請提供影像檔案的 {path} 或 {name, dataBase64},或 effect.list 所提供的紋理 +@msg textureImage: {e} textureImage:{e} +@msg that makes more than {MAX_PIECES} slices 這會產生超過 {MAX_PIECES} 個切片 +@msg that object is not in the overlap 該物件不在重疊處 +@msg the Affinity document has no page with a size Affinity 文件中沒有具有大小的頁面 +@msg the CMYK image couldn't be written 無法寫入 CMYK 影像 +@msg the PDF security settings were saved without their passwords: give openPassword or permissionsPassword again, or security without passwordRequired to export unprotected PDF 安全性設定儲存時未包含密碼:請再次提供 openPassword 或 permissionsPassword,或提供不含 passwordRequired 的 security 以匯出不受保護的檔案 +@msg the RTF file has too many paragraphs or formatting changes to place as type (at most {MAX_PARAGRAPHS} paragraphs and {MAX_RUNS} runs) RTF 檔案的段落或格式變更過多,無法置入為文字 (最多 {MAX_PARAGRAPHS} 個段落和 {MAX_RUNS} 個連續格式區段) +@msg the RTF file is too large to place as type (at most {_1} MB) RTF 檔案過大,無法置入為文字 (最多 {_1} MB) +@msg the SVG expands to more than {0} nested SVG images SVG 展開後超過 {0} 個巢狀 SVG 影像 +@msg the SVG expands to more than {0} objects SVG 展開後超過 {0} 個物件 +@msg the SVG has no drawable objects SVG 中沒有可繪製的物件 +@msg the SVGZ file unpacks to more than {_1} MB SVGZ 檔案解壓縮後超過 {_1} MB +@msg the Word document has more than {MAX_PAGES} pages of properties, too many to place Word 文件的屬性超過 {MAX_PAGES} 頁,數量過多而無法置入 +@msg the Word document has more than {MAX_RUNS} runs of character or paragraph properties, too many to place Word 文件的字元或段落屬性超過 {MAX_RUNS} 個連續格式區段,數量過多而無法置入 +@msg the Word document has more than {_1} MB of formatting properties, too many to place Word 文件的格式屬性超過 {_1} MB,數量過多而無法置入 +@msg the Word document has too much text or formatting to place as type (at most {MAX_PARAGRAPHS} paragraphs, {MAX_RUNS} runs and {_1} MB of text) Word 文件的文字或格式過多,無法置入為文字 (最多 {MAX_PARAGRAPHS} 個段落、{MAX_RUNS} 個連續格式區段和 {_1} MB 的文字) +@msg the Word document has too much text to place as type (at most {_1} MB) Word 文件的文字過多,無法置入為文字 (最多 {_1} MB) +@msg the Word document is encrypted or protected with a password; save it without one to place it Word 文件已加密或受密碼保護;請儲存為沒有密碼的檔案再置入 +@msg the Word document is too large to place (its {name} stream holds more than {_1} MB) Word 文件過大,無法置入 (其 {name} 資料流超過 {_1} MB) +@msg the Word document was last saved with fast save, which VectorCraft doesn't read; save it again with fast save turned off Word 文件上次是以快速儲存方式儲存,VectorCraft 無法讀取;請關閉快速儲存後再儲存一次 +@msg the Word document was saved by Word 6.0 or Word 95, which VectorCraft doesn't read; save it as a Word 97-2003 document Word 文件是由 Word 6.0 或 Word 95 儲存,VectorCraft 無法讀取;請儲存為 Word 97-2003 文件 +@msg the Word document's text is made of more than {MAX_PIECES} pieces, too many to place Word 文件的文字由超過 {MAX_PIECES} 個片段組成,數量過多而無法置入 +@msg the action set ids are not a list 動作組 ID 不是清單 +@msg the active paint is not a gradient 作用中的上色不是漸層 +@msg the artboards don't fit on the canvas: fewer artboards, less spacing or a smaller size 工作區域無法容納於畫布:請減少工作區域、縮小間距或縮小尺寸 +@msg the character's size can't be measured 無法測量字元的大小 +@msg the compound shape is too complex to expand 複合形狀過於複雜,無法展開 +@msg the container of the listed objects is gone 所列物件的容器已不存在 +@msg the copy `{user_id}` can't be read as a library 複本 `{user_id}` 無法讀取為資料庫 +@msg the copy would leave the canvas 複本會超出畫布 +@msg the cut cannot be made on this art: {e} 無法在此圖稿上進行切割:{e} +@msg the data isn't an EMF or WMF picture 資料不是 EMF 或 WMF 圖片 +@msg the data isn't an EPS or PostScript picture 資料不是 EPS 或 PostScript 圖片 +@msg the deferred paste is no longer available 延後的貼上已無法使用 +@msg the design is too big to draw at every data point of this graph 設計過大,無法在此圖表的每個資料點繪製 +@msg the design is too big to draw in every column of this graph 設計過大,無法在此圖表的每個直條中繪製 +@msg the dialog it was opened over is no longer open 它開啟時所在的對話框已不再開啟 +@msg the dictionary stack overflowed 字典堆疊溢位 +@msg the editing data's hash has no place 編輯資料的雜湊值沒有存放位置 +@msg the entities the document declares expand to too much text 文件宣告的實體展開後的文字過多 +@msg the envelope's content has no bounds 封套的內容沒有邊界 +@msg the envelope's mesh is malformed 封套的網格格式不正確 +@msg the file holds no `variableSets` element 檔案中沒有 `variableSets` 元素 +@msg the file is larger than {_1} MB 檔案大於 {_1} MB +@msg the file is too large 檔案過大 +@msg the file was updated or encrypted already 檔案已經更新或加密 +@msg the first character of a line has no character before it to kern: it moves only up and down (dy) 一行的第一個字元前面沒有可調整字距的字元:它只能上下移動 (dy) +@msg the font {_1} is not available 無法使用字體 {_1} +@msg the format has no file extension 此格式沒有副檔名 +@msg the graphic can't be read: {e} 無法讀取圖形:{e} +@msg the graphic is empty 圖形為空 +@msg the graphic's data is damaged 圖形的資料已損毀 +@msg the graphic's document has no artboard 圖形的文件沒有工作區域 +@msg the header `{cell}` for `{name}` would read back as the variable `{other}`: rename one of them `{name}` 的標題 `{cell}` 讀回時會成為變數 `{other}`:請重新命名其中一個 +@msg the image `{path}` isn't followed: {r} 未跟隨影像 `{path}` 的連結:{r} +@msg the image has no embedded pixels 影像沒有內嵌的像素 +@msg the image is empty 影像為空 +@msg the image is fully transparent 影像完全透明 +@msg the image is not on an artboard; pass rect 影像不在工作區域上;請傳入 rect +@msg the image's pixels are missing 影像的像素遺失 +@msg the image's pixels aren't in the document 影像的像素不在文件中 +@msg the image's pixels can't be read: {e} 無法讀取影像的像素:{e} +@msg the image's transparency doesn't fit it 影像的透明度資料與影像不相符 +@msg the job would print more than {MAX_PAGES} pages 此工作會列印超過 {MAX_PAGES} 頁 +@msg the job would print more than {_1} pages 此工作會列印超過 {_1} 頁 +@msg the layers hold no art to mask 圖層中沒有可套用遮色片的圖稿 +@msg the layout moved 版面已移動 +@msg the library has a group `{name}` already 資料庫中已有群組 `{name}` +@msg the library has no group `{name}` 資料庫中沒有群組 `{name}` +@msg the library has no item `{item}` 資料庫中沒有項目 `{item}` +@msg the library has no item `{other}` 資料庫中沒有項目 `{other}` +@msg the library holds {MAX_GROUPS} groups already 資料庫已有 {MAX_GROUPS} 個群組 +@msg the library holds {MAX_ITEMS} items of this kind already 資料庫已有 {MAX_ITEMS} 個這類項目 +@msg the name is empty 名稱為空 +@msg the object has no fill, stroke or effect 物件沒有填色、筆畫或效果 +@msg the object has no graphic style (pass `name`) 物件沒有繪圖樣式 (請傳入 `name`) +@msg the objects don't match the plan 物件與計畫不相符 +@msg the open and permissions passwords must differ 開啟密碼和權限密碼必須不同 +@msg the operand stack overflowed 運算元堆疊溢位 +@msg the page has no area 頁面沒有面積 +@msg the page's type in an unread object's box isn't in its page art 頁面中位於未讀取物件方框內的文字不在其頁面圖稿中 +@msg the paint behind the proxy is not a gradient 代理所代表的上色不是漸層 +@msg the parent must be a layer or sublayer 父項必須是圖層或子圖層 +@msg the path can't be extended 路徑無法延伸 +@msg the path can't be inside one of the objects to attach 路徑不能位於要附加的物件之內 +@msg the path has no segments to measure 路徑沒有可測量的線段 +@msg the path is empty 路徑為空 +@msg the path is too short to shorten that much 路徑過短,無法縮短這麼多 +@msg the picture has no objects 圖片中沒有物件 +@msg the program runs too long 程式執行時間過長 +@msg the program uses too much memory 程式使用過多記憶體 +@msg the rectangle must have a width and a height 矩形必須有寬度和高度 +@msg the rectangle needs a size and must lie on the canvas 矩形需要有大小,而且必須位於畫布上 +@msg the selected art has no width 所選圖稿沒有寬度 +@msg the selection draws nothing 選取範圍沒有繪製任何內容 +@msg the selection has no area 選取範圍沒有面積 +@msg the selection has no art to export 選取範圍中沒有可匯出的圖稿 +@msg the selection has no bounds 選取範圍沒有邊界 +@msg the selection has no graphic style 選取範圍沒有繪圖樣式 +@msg the slice would leave the canvas 切片會超出畫布 +@msg the spot colour couldn't be added 無法加入特別色 +@msg the subpath has no ends to extend (it is closed or a single point) 子路徑沒有可延伸的端點 (它是封閉路徑或單一的點) +@msg the symbols are nested too deeply to expand their instances 符號的巢狀層次過深,無法展開其範例 +@msg the text file is too large to place as type (at most {_1} MB) 文字檔案過大,無法置入為文字 (最多 {_1} MB) +@msg the text is empty 文字為空 +@msg the text is over {_1} MB 文字超過 {_1} MB +@msg the top object must be a path 最上方的物件必須是路徑 +@msg the trace was cancelled 描圖已取消 +@msg the trailer has no size 檔尾沒有大小 +@msg the type object is flattened to nothing 文字物件平面化後沒有任何內容 +@msg the value of axis `{tag}` must be a number or null 軸 `{tag}` 的值必須是數字或 null +@msg the variable library declares more than {MAX_LIBRARY_DATASETS} data sets 變數資料庫宣告了超過 {MAX_LIBRARY_DATASETS} 個資料集 +@msg the variable library declares more than {MAX_LIBRARY_ENTITIES} entities 變數資料庫宣告了超過 {MAX_LIBRARY_ENTITIES} 個實體 +@msg the variable library declares more than {MAX_LIBRARY_VARIABLES} variables 變數資料庫宣告了超過 {MAX_LIBRARY_VARIABLES} 個變數 +@msg the variable library declares no variables 變數資料庫未宣告任何變數 +@msg the variable library is larger than {MAX_LIBRARY_BYTES} bytes 變數資料庫大於 {MAX_LIBRARY_BYTES} 位元組 +@msg the variable library is not UTF-8 變數資料庫不是 UTF-8 +@msg the variable library is not well-formed XML: {e} 變數資料庫不是格式正確的 XML:{e} +@msg the variable library nests elements more than {MAX_LIBRARY_NESTING} deep 變數資料庫的元素巢狀層次超過 {MAX_LIBRARY_NESTING} 層 +@msg the variable library's document type declaration holds something other than entities of plain text 變數資料庫的文件類型宣告包含純文字實體以外的內容 +@msg the variable library's entities expand to more than {MAX_LIBRARY_BYTES} bytes 變數資料庫的實體展開後超過 {MAX_LIBRARY_BYTES} 位元組 +@msg the window has no dock 視窗沒有停駐區 +@msg the written PDF has no catalog 已寫入的 PDF 沒有目錄 +@msg the written PDF has no cross-reference table 已寫入的 PDF 沒有交互參照表 +@msg the written PDF's metadata can't be edited 無法編輯已寫入 PDF 的中繼資料 +@msg there are no colour swatches to draw 沒有可繪製的顏色色票 +@msg there is already a design named `{name}` 已有名為 `{name}` 的設計 +@msg there is already a design named `{to}` 已有名為 `{to}` 的設計 +@msg there is already a toolbar named `{name}` 已有名為 `{name}` 的工具列 +@msg there is already a toolbar named `{to}` 已有名為 `{to}` 的工具列 +@msg there is no library: create one first 沒有資料庫:請先建立一個 +@msg these paths are too degenerate for Shaper 這些路徑過於退化,Shaper 無法處理 +@msg thumbnail: no page {v} (the {what} has {count}) thumbnail:沒有頁面 {v} ({what} 有 {count}) +@msg tileRange of {what}: {e} {what} 的 tileRange:{e} +@msg title can't be empty title 不能為空 +@msg to (the new name) is required 必須提供 to (新名稱) +@msg to must be fill or stroke to 必須是 fill 或 stroke +@msg to must be smooth or corner to 必須是 smooth 或 corner +@msg too large for a zip archive: package to a folder 對 zip 封存檔而言過大:請封裝到資料夾 +@msg too many Shaper edits Shaper 編輯過多 +@msg too many `points` (at most 100000) `points` 過多 (最多 100000 個) +@msg too many characters: at most {MAX_CHARS} 字元過多:最多 {MAX_CHARS} 個 +@msg too many dots for this size: lower the frequency 此尺寸的網點過多:請降低頻率 +@msg too many filters over one file 單一檔案上的濾鏡過多 +@msg too many overlapping paths for Shaper 重疊的路徑過多,Shaper 無法處理 +@msg too many saved clips 已儲存的剪裁過多 +@msg too many saved graphics states 已儲存的圖形狀態過多 +@msg toolbar (a toolbar's name) must be a string toolbar (工具列的名稱) 必須是字串 +@msg toolbar name can't be empty 工具列名稱不能為空 +@msg transparentImages {v}: "flatten" (the default) or "omit" transparentImages {v}:應為 "flatten" (預設值) 或 "omit" +@msg two saved selections would be named `{_1}` 會有兩個已儲存的選取範圍都名為 `{_1}` +@msg type dimension cannot be represented with this text transform 文字尺寸無法以此文字變形表示 +@msg type dimension must be finite 文字尺寸必須是有限值 +@msg unexpected resources 非預期的資源 +@msg unknown CMYK profile `{name}` 未知的 CMYK 描述檔 `{name}` +@msg unknown File Info field `{k}` 未知的「檔案資訊」欄位 `{k}` +@msg unknown OpenType feature `{t}` in featureChanges (the tags `features` takes) featureChanges 中有未知的 OpenType 功能 `{t}` (應為 `features` 接受的標籤) +@msg unknown PDF preset `{name}` (presets: {_1}) 未知的 PDF 預設集 `{name}` (預設集:{_1}) +@msg unknown Warp style 未知的彎曲樣式 +@msg unknown alignToPath `{a}` 未知的 alignToPath `{a}` +@msg unknown arrowhead {v} 未知的箭頭 {v} +@msg unknown artboardLayout key `{k}` (layout, columns, spacing, rightToLeft) 未知的 artboardLayout 鍵 `{k}` (layout、columns、spacing、rightToLeft) +@msg unknown attribute `{attribute}` 未知的屬性 `{attribute}` +@msg unknown attribute `{k}` 未知的屬性 `{k}` +@msg unknown axis `{other}` (vertical|horizontal|free) 未知的軸 `{other}` (vertical|horizontal|free) +@msg unknown blend mode `{b}` 未知的混合模式 `{b}` +@msg unknown blend mode {b} 未知的混合模式 {b} +@msg unknown brush type `{o}` 未知的筆刷類型 `{o}` +@msg unknown category `{c}` 未知的類別 `{c}` +@msg unknown category `{c}` ({_1}) 未知的類別 `{c}` ({_1}) +@msg unknown character `{c}` 未知的字元 `{c}` +@msg unknown character style number field 未知的字元樣式數字欄位 +@msg unknown effect `{e}` 未知的效果 `{e}` +@msg unknown end {e} 未知的端點 {e} +@msg unknown flattenerPreset `{name}` (High Resolution, Medium Resolution, Low Resolution or a saved one: see flattener.presets.list) 未知的 flattenerPreset `{name}` (High Resolution、Medium Resolution、Low Resolution 或已儲存的預設集:請參閱 flattener.presets.list) +@msg unknown format `{f}` (vcswatches, gpl, ase or css) 未知的格式 `{f}` (vcswatches、gpl、ase 或 css) +@msg unknown from {f} 未知的 from {f} +@msg unknown graph type `{t}` 未知的圖表類型 `{t}` +@msg unknown grid colours `{name}` (one of {_1}) 未知的格點顏色 `{name}` (應為 {_1} 其中之一) +@msg unknown gridType `{t}` 未知的 gridType `{t}` +@msg unknown highlight `{v}` 未知的 highlight `{v}` +@msg unknown intent `{i}` 未知的色彩比對方式 `{i}` +@msg unknown issue kind {id} 未知的問題種類 {id} +@msg unknown issue kind {v} 未知的問題種類 {v} +@msg unknown knockout state {k} 未知的去底狀態 {k} +@msg unknown language `{language}` (one of {_1}) 未知的語言 `{language}` (應為 {_1} 其中之一) +@msg unknown language `{l}` (one of {_1}) 未知的語言 `{l}` (應為 {_1} 其中之一) +@msg unknown method `{m}` ({_1}) 未知的方法 `{m}` ({_1}) +@msg unknown mode `{other}` (gray, rgb, hsb, lab, cmyk or web) 未知的模式 `{other}` (gray、rgb、hsb、lab、cmyk 或 web) +@msg unknown mode `{other}` (mono|cmyk) 未知的模式 `{other}` (mono|cmyk) +@msg unknown mode `{other}` (rgb|cmyk|gray|global) 未知的模式 `{other}` (rgb|cmyk|gray|global) +@msg unknown mode `{other}` (set, add, subtract) 未知的模式 `{other}` (set、add、subtract) +@msg unknown mode `{o}` 未知的模式 `{o}` +@msg unknown mode {m} 未知的模式 {m} +@msg unknown model `{other}` 未知的 model `{other}` +@msg unknown model `{other}` (keep, new or document) 未知的 model `{other}` (keep、new 或 document) +@msg unknown op {o} 未知的 op {o} +@msg unknown order `{o}`: toggle, front, forward, backward or back 未知的 order `{o}`:應為 toggle、front、forward、backward 或 back +@msg unknown overprints `{v}` (preserve, simulate or discard) 未知的 overprints `{v}` (preserve、simulate 或 discard) +@msg unknown panel 未知的面板 +@msg unknown pieLegend `{v}` (none, standard or wedges) 未知的 pieLegend `{v}` (none、standard 或 wedges) +@msg unknown piePosition `{v}` (even, ratio or stacked) 未知的 piePosition `{v}` (even、ratio 或 stacked) +@msg unknown pieSort `{v}` (none, all or first) 未知的 pieSort `{v}` (none、all 或 first) +@msg unknown plate `{n}` 未知的色版 `{n}` +@msg unknown preference `{k}` 未知的偏好設定 `{k}` +@msg unknown profile {id} (see stroke.widthProfile.list) 未知的描述檔 {id} (請參閱 stroke.widthProfile.list) +@msg unknown proof target `{t}` 未知的校樣目標 `{t}` +@msg unknown quotes key `{k}` (double, single) 未知的 quotes 鍵 `{k}` (double、single) +@msg unknown resolution `{v}` 未知的解析度 `{v}` +@msg unknown rule `{rule}` ({_1}) 未知的規則 `{rule}` ({_1}) +@msg unknown rule `{r}` (see color.harmony) 未知的規則 `{r}` (請參閱 color.harmony) +@msg unknown setting `{k}` 未知的設定 `{k}` +@msg unknown shape `{v}` (circle|ellipse|square|diamond|line) 未知的形狀 `{v}` (circle|ellipse|square|diamond|line) +@msg unknown spacing `{o}` (smooth|steps|distance) 未知的 spacing `{o}` (smooth|steps|distance) +@msg unknown tileType `{t}` ({_1}) 未知的 tileType `{t}` ({_1}) +@msg unknown units 未知的單位 +@msg unknown units `{u}` 未知的單位 `{u}` +@msg unknown value axis `{v}` (left, right or both) 未知的數值軸 `{v}` (left、right 或 both) +@msg unknown variation `{v}` (tintsShades|warmCool|vividMuted) 未知的 variation `{v}` (tintsShades|warmCool|vividMuted) +@msg unknown warp style `{s}` 未知的彎曲樣式 `{s}` +@msg unknown {key} `{v}` (none, short or full) 未知的 {key} `{v}` (none、short 或 full) +@msg unknown {key} profile `{n}` 未知的 {key} 描述檔 `{n}` +@msg unknown {k} key `{key}` (size, position) 未知的 {k} 鍵 `{key}` (size、position) +@msg unreadable object 無法讀取的物件 +@msg unsafe destination file name 目的地檔案名稱不安全 +@msg use paths or compound paths 請使用路徑或複合路徑 +@msg useArtboards must be true or false, not {v} useArtboards 必須是 true 或 false,而非 {v} +@msg value for `{var}` must match its variable kind `{var}` 的值必須符合其變數種類 +@msg variable `{_1}` is already defined 變數 `{_1}` 已定義 +@msg variable `{name}` has no `trait` 變數 `{name}` 沒有 `trait` +@msg variable `{name}` is already defined 變數 `{name}` 已定義 +@msg variable `{name}` is declared twice 變數 `{name}` 宣告了兩次 +@msg variable `{to}` already exists 變數 `{to}` 已存在 +@msg view is required 必須提供 view +@msg view must be one of {_1} view 必須是 {_1} 其中之一 +@msg warpStyle can only edit an applied Warp effect warpStyle 只能編輯已套用的彎曲效果 +@msg width and height must be more than 0 and at most {limit} 寬度和高度必須大於 0 且不超過 {limit} +@msg width factors must be finite 寬度係數必須是有限值 +@msg width must be positive width 必須是正值 +@msg width out of range 寬度超出範圍 +@msg width/height must be > 0 width/height 必須 > 0 +@msg x and y must be finite numbers x 和 y 必須是有限的數字 +@msg x and y must be given together x 和 y 必須一起提供 +@msg zone needs an anchor: dock beside a panel with anchor, or in a new dock column with side (Start or End) zone 需要 anchor:請以 anchor 停駐在面板旁,或以 side (Start 或 End) 停駐在新的停駐欄 +@msg zoom must be positive zoom 必須是正值 +@msg {C}: no effect at index {list} {C}:索引 {list} 處沒有效果 +@msg {DEFAULT_PRESET} is protected and stays {DEFAULT_PRESET} 受到保護,會保留 +@msg {DEFAULT_PRESET} is protected: save the settings under another name {DEFAULT_PRESET} 受到保護:請以其他名稱儲存設定 +@msg {LABEL} produced an empty result {LABEL} 產生了空的結果 +@msg {_1} MB of document, at most {_2} MB 文件為 {_1} MB,上限為 {_2} MB +@msg {_1} MB of images, at most {_2} MB 影像為 {_1} MB,上限為 {_2} MB +@msg {_1} bytes of RGBA data for a {width} × {height} image {width} × {height} 影像的 RGBA 資料為 {_1} 位元組 +@msg {_1} can't be read, or changed since it was read: relink or update it first {_1} 無法讀取,或在讀取後已變更:請先重新連結或更新 +@msg {_1} can't go into {into} {_1} 不能放入 {into} +@msg {_1} can't limit printing to low resolution: choose PDF 1.4 or later, or allow high-resolution printing {_1} 無法將列印限制為低解析度:請選擇 PDF 1.4 以上版本,或允許高解析度列印 +@msg {_1} files can't be opened yet 尚無法開啟 {_1} 檔案 +@msg {_1} files can't be password-protected: remove the passwords or choose no standard {_1} 檔案不能以密碼保護:請移除密碼或不要選擇標準 +@msg {_1} files can't be {_2} {_1} 檔案不能 {_2} +@msg {_1} files can't carry editing data: turn off preserveEditing {_1} 檔案不能包含編輯資料:請關閉 preserveEditing +@msg {_1} files can't have PDF layers: turn off createLayers {_1} 檔案不能有 PDF 圖層:請關閉 createLayers +@msg {_1} files need a creation date, and this platform has no clock to give one {_1} 檔案需要建立日期,而此平台沒有可提供日期的時鐘 +@msg {_1} isn't a path {_1} 不是路徑 +@msg {_1} options: {e} {_1} 選項:{e} +@msg {_1} paints nothing to rasterize {_1} 沒有繪製任何可點陣化的內容 +@msg {_1} passwords can have up to {MAX_LEGACY_PASSWORD} ASCII characters (PDF 1.7 and later take any) {_1} 密碼最多 {MAX_LEGACY_PASSWORD} 個 ASCII 字元 (PDF 1.7 以上版本接受任何字元) +@msg {_1} with linked images or an image map writes several files: use document.export 含有連結影像或影像地圖的 {_1} 會寫入多個檔案:請使用 document.export +@msg {_1} writes one file per artboard here: use document.export, or name one artboard {_1} 在這裡會為每個工作區域寫入一個檔案:請使用 document.export,或指定一個工作區域 +@msg {_1} × {_2} pixels is too large for {_3} (at most {max} pixels a side): lower the scale {_1} × {_2} 像素對 {_3} 而言過大 (每邊最多 {max} 像素):請降低縮放比例 +@msg {_1}: belongs to another account {_1}:屬於另一個帳戶 +@msg {_1}: not a folder of its own {_1}:不是獨立的資料夾 +@msg {_1}: not a plain file {_1}:不是一般檔案 +@msg {dest}: {e} {dest}:{e} +@msg {doc} has no folder {doc} 沒有資料夾 +@msg {file} isn't linked {file} 不是連結的檔案 +@msg {folder} is not a package folder {folder} 不是封裝資料夾 +@msg {folder}: more than {max} files and folders {folder}:超過 {max} 個檔案和資料夾 +@msg {folder}: {e} {folder}:{e} +@msg {g} is not a Live Paint group {g} 不是即時上色群組 +@msg {id} is not a slice {id} 不是切片 +@msg {key} must be 0–{MAX_ADD_AROUND} pt {key} 必須是 0–{MAX_ADD_AROUND} pt +@msg {key} must be [x,y] {key} 必須是 [x,y] +@msg {key} must be a percentage {min}..100 {key} 必須是 {min}..100 的百分比 +@msg {key} must be a positive number, not {n} {key} 必須是正數,而非 {n} +@msg {key} must be a positive number, not {v} {key} 必須是正數,而非 {v} +@msg {key} must be one of {_1} {key} 必須是 {_1} 其中之一 +@msg {key} must be {_1}, got {s} {key} 必須是 {_1},收到 {s} +@msg {key} must name a floating panel {key} 必須指定浮動面板 +@msg {key} must name a panel in another group {key} 必須指定另一個群組中的面板 +@msg {key} must name a panel that shows {key} 必須指定顯示中的面板 +@msg {key} must name a registered panel {key} 必須指定已註冊的面板 +@msg {kind} files have no transparency, and the file would have {what}: flatten it first (object.flattenTransparency) {kind} 檔案沒有透明度,而檔案中會有 {what}:請先將它平面化 (object.flattenTransparency) +@msg {kind} images can't be opened (see document.formats) 無法開啟 {kind} 影像 (請參閱 document.formats) +@msg {k} `{v}` is not one of the choices {k} `{v}` 不是選項之一 +@msg {k} has control characters{_1} {k} 含有控制字元{_1} +@msg {k} is too long (at most {MAX_TEXT} characters) {k} 過長 (最多 {MAX_TEXT} 個字元) +@msg {k} must be > 0 {k} 必須 > 0 +@msg {k} must be a number (pt) or a length such as "210 mm" {k} 必須是數字 (pt) 或 "210 mm" 這類長度 +@msg {k} must be a number from {min} to {max} {k} 必須是 {min} 到 {max} 之間的數字 +@msg {k} must be a number or "auto" {k} 必須是數字或 "auto" +@msg {k} must be a string {k} 必須是字串 +@msg {k} must be text {k} 必須是文字 +@msg {k} must be true or false {k} 必須是 true 或 false +@msg {k} must be {{size?, position?}} {k} 必須是 {{size?, position?}} +@msg {k}: can't read `{s}` as a length {k}:無法將 `{s}` 讀取為長度 +@msg {label} must be a number at most {max} {label} 必須是不超過 {max} 的數字 +@msg {label} must be a number from -1296 to 1296 {label} 必須是 -1296 到 1296 之間的數字 +@msg {label} must be a number from 1 to 10000 {label} 必須是 1 到 10000 之間的數字 +@msg {name} `{s}`: {ids} {name} `{s}`:{ids} +@msg {name} is built in and can't be deleted {name} 是內建項目,無法刪除 +@msg {name} must be {lo}–{hi}{unit} (got {v}) {name} 必須是 {lo}–{hi}{unit} (收到 {v}) +@msg {name}: CRC or size mismatch {name}:CRC 或大小不相符 +@msg {name}: only this Affinity file's embedded preview could be read; use File › Open to see it with its warning, or export SVG or PDF from Affinity before placing {name}:只能讀取此 Affinity 檔案的內嵌預視;請使用「檔案 › 開啟」查看它及其警告,或在置入前先從 Affinity 匯出 SVG 或 PDF +@msg {name}: {e} {name}:{e} +@msg {native}; its embedded preview can't be read either ({e}) {native};其內嵌預視也無法讀取 ({e}) +@msg {std} files are CMYK, and the file would have colours in {_1} {std} 檔案為 CMYK,而檔案中會有 {_1} 的顏色 +@msg {std} files embed their fonts, and the file would have one that isn't {std} 檔案會內嵌字體,而檔案中會有一個未內嵌的字體 +@msg {target} is the file this document was read from, and reading it left things out ({what}): writing over it would lose them for good. Write another file instead, or pass acknowledgeLoss: true to replace it anyway {target} 是讀取此文件的來源檔案,而讀取時略過了部分內容 ({what}):覆寫它會永久失去這些內容。請改為寫入另一個檔案,或傳入 acknowledgeLoss: true 以強制取代 +@msg {ty} brushes need selected art (or params.{k}) {ty} 筆刷需要選取的圖稿 (或 params.{k}) +@msg {v} is not an asset id {v} 不是資產 ID +@msg {what} can't be intertwined {what} 無法交織 +@msg {what} doesn't fit the paper with its bleed and marks {what} 連同出血和標記無法容納於紙張 +@msg {what} would print on more than {MAX_TILES} tiles: scale it down {what} 會列印在超過 {MAX_TILES} 個拼貼上:請縮小 diff --git a/crates/ui-egui/src/panels/character.rs b/crates/ui-egui/src/panels/character.rs index 44ae643e86..1e6ca2c8d5 100644 --- a/crates/ui-egui/src/panels/character.rs +++ b/crates/ui-egui/src/panels/character.rs @@ -2,6 +2,7 @@ //! scale, baseline shift, character rotation, the anti-aliasing method and the All Caps, Small Caps, //! Superscript, Subscript, Underline and Strikethrough toggles and the Language menu. +use std::collections::HashSet; use std::sync::{Mutex, OnceLock}; use egui::{Key, Ui, vec2}; @@ -99,8 +100,8 @@ pub(crate) fn shared_text_flag(app: &VectorcraftApp, f: impl Fn(&vectorcraft_doc } /// `f` of the character styles the panels act on: the runs the Type tool's selection covers (the -/// caret's style at a caret), else every run of the selected type, groups' included. `None` (a -/// blank field) where they differ, or with no type. +/// caret's style at a caret), else every run of every frame of the selected stories +/// ([`selected_stories`]). `None` (a blank field) where they differ, or with no type. pub(crate) fn shared(app: &VectorcraftApp, f: impl Fn(&CharStyle) -> T) -> Option { shared_styles(app, |_, _, style, _| Some(f(style))) } @@ -162,12 +163,8 @@ fn shared_styles( None => each_paragraph_run(t, Some((a, b)), |para, style, inline| acc.add(f(t, para, style, inline))), } } else { - for n in st.selection.objects.iter().filter_map(|id| st.doc.node(*id)) { - n.walk(&mut |c| { - if let NodeKind::Text(t) = &c.kind { - each_paragraph_run(t, None, |para, style, inline| acc.add(f(t, para, style, inline))); - } - }); + for t in selected_story_texts(app) { + each_paragraph_run(t, None, |para, style, inline| acc.add(f(t, para, style, inline))); } } acc.value().flatten() @@ -243,9 +240,12 @@ pub(crate) fn format(app: &mut VectorcraftApp, p: Value) { /// [`format`] that returns the command's result: `text.setRangeStyle` on the range the Type tool /// has selected (the whole text when nothing is selected) while it edits text, else -/// `text.setFormat` on the selected text objects. +/// `text.setFormat` on the selected stories ([`selected_stories`]). pub(crate) fn run_format(app: &mut VectorcraftApp, mut p: Value) -> Result { - let Some((id, a, b)) = text_editing(app) else { return app.run("text.setFormat", p) }; + let Some((id, a, b)) = text_editing(app) else { + target_selected_stories(app, &mut p); + return app.run("text.setFormat", p); + }; if let Some(first) = text_story(app).and_then(|story| story.first().copied()) { return story_style(app, first, p); } @@ -283,9 +283,11 @@ pub(crate) fn shared_warichu(app: &VectorcraftApp) -> SharedWarichu { } /// Apply character attributes: to the selected range while the Type tool edits text (the whole -/// object when nothing is selected), else to the selected text objects. -fn char_cmd(app: &mut VectorcraftApp, cmd: &str, p: Value) { +/// object when nothing is selected), else to every frame of the selected stories +/// ([`selected_stories`]). +fn char_cmd(app: &mut VectorcraftApp, cmd: &str, mut p: Value) { if text_editing(app).is_none() { + target_selected_stories(app, &mut p); app.run(cmd, p).ok(); return; } @@ -546,6 +548,55 @@ pub(crate) fn text_story(app: &VectorcraftApp) -> Option> { (ids.len() >= 2).then_some(ids) } +/// The type objects the panels act on with the Selection tool: the selected type objects and those +/// in selected groups, each with every frame of its threaded story (locked and hidden frames +/// included), each once, the frames of a story in thread order. +pub(crate) fn selected_stories(app: &VectorcraftApp) -> Vec { + let Some(st) = app.session.active() else { return Vec::new() }; + let mut frames = Vec::new(); + let mut taken = HashSet::new(); + for selected in st.selection.objects.iter().filter_map(|id| st.doc.node(*id)) { + selected.walk(&mut |child| { + if matches!(child.kind, NodeKind::Text(_)) && !taken.contains(&child.id) { + for id in st.doc.story_of(child.id) { + if taken.insert(id) { + frames.push(id); + } + } + } + }); + } + frames +} + +/// The type objects of [`selected_stories`]. +pub(crate) fn selected_story_texts(app: &VectorcraftApp) -> Vec<&vectorcraft_doc::TextObject> { + let Some(st) = app.session.active() else { return Vec::new() }; + selected_stories(app) + .into_iter() + .filter_map(|id| match st.doc.node(id).map(|n| &n.kind) { + Some(NodeKind::Text(t)) => Some(t.as_ref()), + _ => None, + }) + .collect() +} + +/// Give the command parameters `p` the `ids` of [`selected_stories`], so a command run with the +/// Selection tool sets every frame of each selected story. `p` stays as it is when it names its +/// targets, with no type selected, and while an object of a symbol instance's art is selected, +/// which the commands refuse. +pub(crate) fn target_selected_stories(app: &VectorcraftApp, p: &mut Value) { + if p.get("ids").is_some() || p.get("id").is_some() || app.session.active().is_none_or(|st| st.selection.symbol_part.is_some()) { + return; + } + let ids = selected_stories(app); + if let Some(params) = p.as_object_mut() + && !ids.is_empty() + { + params.insert("ids".into(), json!(ids.iter().map(|id| id.0).collect::>())); + } +} + /// `text.setRangeStyle` with `p` on all the text of every frame of the story that `first` is a /// frame of, as one undo step. fn story_style(app: &mut VectorcraftApp, first: NodeId, mut p: Value) -> Result { @@ -910,7 +961,8 @@ fn anti_alias_method(app: &mut VectorcraftApp, ui: &mut Ui, width: f32) { } /// The anti-aliasing method of the type objects the panel acts on: the one the Type tool edits, -/// else the selected type (groups' included). `None` where they differ, or with no type. +/// else every frame of the selected stories ([`selected_stories`]). `None` where they differ, or +/// with no type. fn shared_anti_alias(app: &VectorcraftApp) -> Option { let st = app.session.active()?; let mut acc = Shared::None; @@ -921,12 +973,8 @@ fn shared_anti_alias(app: &VectorcraftApp) -> Option { } } None => { - for n in st.selection.objects.iter().filter_map(|id| st.doc.node(*id)) { - n.walk(&mut |c| { - if let NodeKind::Text(t) = &c.kind { - acc.add(t.anti_alias); - } - }); + for t in selected_story_texts(app) { + acc.add(t.anti_alias); } } } @@ -934,12 +982,14 @@ fn shared_anti_alias(app: &VectorcraftApp) -> Option { } /// Set the anti-aliasing method `m` of the frame the Type tool edits, whatever part of its text -/// is selected, else the selected type objects (`text.setFormat {antiAlias}`). +/// is selected, else every frame of the selected stories (`text.setFormat {antiAlias}`). fn set_anti_alias(app: &mut VectorcraftApp, m: TypeAntiAlias) { let mut p = json!({"antiAlias": m.id()}); if let Some((id, _, _)) = text_editing(app) { end_typing(app); p["ids"] = json!([id.0]); + } else { + target_selected_stories(app, &mut p); } app.run("text.setFormat", p).ok(); } @@ -1160,7 +1210,11 @@ fn axes_cmd(app: &mut VectorcraftApp, axes: Value, phase: widgets::Live) { } super::live_run(app, "Character", "text.setRangeStyle", q, phase); } - None => super::live_run(app, "Character", "text.setFormat", json!({ "fontAxes": axes }), phase), + None => { + let mut p = json!({ "fontAxes": axes }); + target_selected_stories(app, &mut p); + super::live_run(app, "Character", "text.setFormat", p, phase); + } } } diff --git a/crates/ui-egui/src/panels/character/tests.rs b/crates/ui-egui/src/panels/character/tests.rs index 7a2a96efb2..56472c59b0 100644 --- a/crates/ui-egui/src/panels/character/tests.rs +++ b/crates/ui-egui/src/panels/character/tests.rs @@ -1741,3 +1741,141 @@ fn story_changes_take_in_locked_and_hidden_frames() { assert_eq!(story_sizes(&app, id).iter().filter(|s| (**s - 9.0).abs() > 1e-9).count(), 0, "frame {id} takes the size"); } } + +/// [`three_frame_story`] with its second frame locked and its third hidden, a type object of its own +/// below it, and the first frame selected with the Selection tool → the app, the frames and the +/// other type object. +fn story_selected_in_its_first_frame() -> (VectorcraftApp, [u64; 3], u64) { + let (mut app, a, b, c) = three_frame_story(60); + let other = app.run("text.create", json!({"x": 10, "y": 250, "text": "Other", "size": 12})).unwrap()["id"].as_u64().unwrap(); + app.run("select.set", json!({"ids": [b]})).unwrap(); + app.run("object.lock", json!({})).unwrap(); + app.run("select.set", json!({"ids": [c]})).unwrap(); + app.run("object.hide", json!({})).unwrap(); + app.run("select.set", json!({"ids": [a]})).unwrap(); + assert_eq!(text_editing(&app), None); + (app, [a, b, c], other) +} + +fn undo_steps(app: &VectorcraftApp) -> usize { + app.session.active().unwrap().history.undo.len() +} + +/// With the Selection tool, a selected frame of a threaded story stands for the whole story: the +/// panel's changes reach its locked and hidden frames, each in one undo step, and leave other type +/// alone. +#[test] +fn selection_tool_changes_reach_every_frame_of_the_story() { + let (mut app, frames, other) = story_selected_in_its_first_frame(); + assert_eq!(selected_stories(&app), frames.map(NodeId).to_vec()); + + let steps = undo_steps(&app); + style(&mut app, json!({"size": 9})); + assert_eq!(undo_steps(&app), steps + 1, "one undo step"); + for id in frames { + assert!(story_sizes(&app, id).iter().all(|s| (*s - 9.0).abs() < 1e-9), "frame {id} takes the size"); + } + assert!(story_sizes(&app, other).iter().all(|s| (*s - 12.0).abs() < 1e-9), "other type keeps its size"); + app.run("edit.undo", json!({})).unwrap(); + for id in frames { + assert!(story_sizes(&app, id).iter().all(|s| (*s - 12.0).abs() < 1e-9), "undo gives frame {id} its size back"); + } + + format(&mut app, json!({"underline": true})); + for id in frames { + assert!(story_frame(&app, id).runs.iter().all(|r| r.style.underline), "frame {id} is underlined"); + } + assert!(story_frame(&app, other).runs.iter().all(|r| !r.style.underline)); + + // Tate-chu-yoko Settings and Warichu Settings set their values through `run_format`. + run_format(&mut app, json!({"tcyUpDown": 2})).unwrap(); + for id in frames { + assert!(story_frame(&app, id).runs.iter().all(|r| (r.style.tcy_up_down - 2.0).abs() < 1e-9), "frame {id} takes Up/Down"); + } + assert!(story_frame(&app, other).runs.iter().all(|r| r.style.tcy_up_down.abs() < 1e-9)); +} + +/// With the Selection tool the anti-aliasing method goes to every frame of the selected story. +#[test] +fn selection_tool_anti_aliasing_reaches_every_frame_of_the_story() { + let (mut app, frames, other) = story_selected_in_its_first_frame(); + set_anti_alias(&mut app, TypeAntiAlias::Strong); + for id in frames { + assert_eq!(story_frame(&app, id).anti_alias, TypeAntiAlias::Strong, "frame {id}"); + } + assert_eq!(story_frame(&app, other).anti_alias, TypeAntiAlias::Sharp); + assert_eq!(shared_anti_alias(&app), Some(TypeAntiAlias::Strong)); +} + +/// With the Selection tool a Variable Font slider sets the axis on every frame of the selected +/// story, in one undo step. +#[test] +fn selection_tool_font_axes_reach_every_frame_of_the_story() { + use vectorcraft_text::test_fonts::{TWO_AXIS_FAMILY, two_axis_font}; + vectorcraft_text::FontDb::global().add_font(two_axis_font().unwrap()); + let (mut app, frames, _) = story_selected_in_its_first_frame(); + app.run("text.setStyle", json!({"ids": frames, "font": TWO_AXIS_FAMILY})).unwrap(); + app.run("select.set", json!({"ids": [frames[0]]})).unwrap(); + let steps = undo_steps(&app); + axes_cmd(&mut app, json!({"wght": 700}), widgets::Live::Released); + assert_eq!(undo_steps(&app), steps + 1, "one undo step"); + for id in frames { + let t = story_frame(&app, id); + assert!(t.runs.iter().all(|r| r.style.font_axes.get("wght") == Some(&700.0)), "frame {id}: {:?}", t.runs[0].style.font_axes); + } +} + +/// With the Selection tool a font family picked in the font menu, and its preview, go to every +/// frame of the selected story, in one undo step. +#[test] +fn selection_tool_font_family_reaches_every_frame_of_the_story() { + let (mut app, frames, other) = story_selected_in_its_first_frame(); + let family = |app: &VectorcraftApp, id: u64| story_frame(app, id).runs.iter().map(|r| r.style.font_family.clone()).collect::>(); + let before = family(&app, other); + let ctx = egui::Context::default(); + crate::font_menu::apply(&mut app, &ctx, crate::font_menu::FontPick::Preview("Source Serif 4".into(), None)); + for id in frames { + assert!(family(&app, id).iter().all(|f| f == "Source Serif 4"), "the preview shows on frame {id}"); + } + let steps = undo_steps(&app); + crate::font_menu::apply(&mut app, &ctx, crate::font_menu::FontPick::Chosen("Source Serif 4".into(), None)); + assert_eq!(undo_steps(&app), steps + 1, "one undo step"); + for id in frames { + assert!(family(&app, id).iter().all(|f| f == "Source Serif 4"), "frame {id} takes the family"); + } + assert_eq!(family(&app, other), before, "other type keeps its family"); +} + +/// The fields show a value only when every frame of the selected story has it: a hidden frame that +/// differs leaves them blank. +#[test] +fn selection_tool_fields_read_every_frame_of_the_story() { + let (mut app, [a, b, c], _) = story_selected_in_its_first_frame(); + assert_eq!(shared(&app, |s| s.size), Some(12.0)); + assert_eq!(shared_anti_alias(&app), Some(TypeAntiAlias::Sharp)); + app.run("text.setStyle", json!({"ids": [c], "size": 20})).unwrap(); + app.run("text.setFormat", json!({"ids": [b], "antiAlias": TypeAntiAlias::Crisp.id()})).unwrap(); + app.run("select.set", json!({"ids": [a]})).unwrap(); + assert_eq!(shared(&app, |s| s.size), None, "the hidden frame's size differs"); + assert_eq!(shared_anti_alias(&app), None, "the locked frame's anti-aliasing differs"); +} + +/// Two frames of one story, or a frame in a selected group, count once; an unthreaded type +/// object is a story of its own. +#[test] +fn selected_stories_list_each_frame_once() { + let (mut app, [a, b, c], other) = story_selected_in_its_first_frame(); + app.run("object.unlockAll", json!({})).unwrap(); + app.run("select.set", json!({"ids": [b, a]})).unwrap(); + assert_eq!(selected_stories(&app), [a, b, c].map(NodeId).to_vec(), "thread order, each once"); + app.run("select.set", json!({"ids": [other, a]})).unwrap(); + let group = app.run("object.group", json!({})).unwrap()["id"].as_u64().unwrap(); + app.run("select.set", json!({"ids": [group]})).unwrap(); + let mut listed = selected_stories(&app); + listed.sort_by_key(|id| id.0); + let mut expected = [a, b, c, other].map(NodeId).to_vec(); + expected.sort_by_key(|id| id.0); + assert_eq!(listed, expected); + app.run("select.set", json!({"ids": []})).unwrap(); + assert!(selected_stories(&app).is_empty()); +} diff --git a/crates/ui-egui/src/panels/paragraph.rs b/crates/ui-egui/src/panels/paragraph.rs index ab53932f80..e02d81e14c 100644 --- a/crates/ui-egui/src/panels/paragraph.rs +++ b/crates/ui-egui/src/panels/paragraph.rs @@ -28,8 +28,9 @@ pub const ALIGNMENTS: [(Justify, &str, &str, &str); 7] = [ (Justify::JustifyAll, "dc-para-justify-all", "Justify all lines", "justifyAll"), ]; -/// Paragraph attributes apply to the selected text objects' paragraphs or, while the Type tool -/// edits text, to the paragraphs its selection (or caret) touches (ending its typing session). +/// Paragraph attributes apply to the paragraphs of every frame of the selected stories or, while +/// the Type tool edits text, to the paragraphs its selection (or caret) touches (ending its typing +/// session). fn format(app: &mut VectorcraftApp, p: Value) { para_cmd(app, "text.setFormat", p); } @@ -75,8 +76,16 @@ fn para_cmd(app: &mut VectorcraftApp, cmd: &str, p: Value) { run_on_paragraphs(app, cmd, p).ok(); } -/// Run `cmd` on the paragraphs the Paragraph panel acts on ([`format`]) and return its result. -pub(crate) fn run_on_paragraphs(app: &mut VectorcraftApp, cmd: &str, mut p: Value) -> Result { +/// Run `cmd` on the paragraphs the Paragraph panel acts on ([`format`]) and return its result. With +/// the Selection tool these are the paragraphs of every frame of the selected stories +/// ([`super::character::selected_stories`]). +pub(crate) fn run_on_paragraphs(app: &mut VectorcraftApp, cmd: &str, p: Value) -> Result { + run_on(app, cmd, p, true) +} + +/// [`run_on_paragraphs`], with the Selection tool on the selected type objects alone unless +/// `stories`. +fn run_on(app: &mut VectorcraftApp, cmd: &str, mut p: Value, stories: bool) -> Result { if let Some((id, a, b)) = super::character::text_editing(app) { super::character::end_typing(app); match super::character::text_story(app) { @@ -88,6 +97,8 @@ pub(crate) fn run_on_paragraphs(app: &mut VectorcraftApp, cmd: &str, mut p: Valu p["end"] = json!(b); } } + } else if stories { + super::character::target_selected_stories(app, &mut p); } app.run(cmd, p) } @@ -208,14 +219,10 @@ fn visit_paragraphs(app: &VectorcraftApp, mut f: impl FnMut(&ParaStyle)) { } return; } - for node in st.selection.objects.iter().filter_map(|id| st.doc.node(*id)) { - node.walk(&mut |c| { - if let NodeKind::Text(t) = &c.kind { - for i in 0..t.paragraph_count() { - f(t.para_at(i)); - } - } - }); + for t in super::character::selected_story_texts(app) { + for i in 0..t.paragraph_count() { + f(t.para_at(i)); + } } } @@ -328,18 +335,8 @@ fn selected_paragraph_direction(app: &VectorcraftApp, fallback: &ParaStyle) -> O { return if collect_text_direction(text, Some((a, b)), &mut shared) { shared.or(default) } else { None }; } - fn collect(node: &vectorcraft_doc::Node, shared: &mut Option) -> bool { - if let NodeKind::Text(text) = &node.kind { - return collect_text_direction(text, None, shared); - } - node.children().is_none_or(|children| children.iter().all(|child| collect(child, shared))) - } - for node in st.selection.objects.iter().filter_map(|id| st.doc.node(*id)) { - if !collect(node, &mut shared) { - return None; - } - } - shared.or(default) + let texts = super::character::selected_story_texts(app); + if texts.into_iter().all(|t| collect_text_direction(t, None, &mut shared)) { shared.or(default) } else { None } } /// A hyphenation option shared by every paragraph in scope, or `None` when they differ. @@ -365,18 +362,8 @@ fn selected_alignment(app: &VectorcraftApp, fallback: &ParaStyle) -> Option) -> bool { - if let NodeKind::Text(text) = &node.kind { - return collect_text_alignment(text, None, shared); - } - node.children().is_none_or(|children| children.iter().all(|child| collect(child, shared))) - } - for node in st.selection.objects.iter().filter_map(|id| st.doc.node(*id)) { - if !collect(node, &mut shared) { - return None; - } - } - shared.or(default) + let texts = super::character::selected_story_texts(app); + if texts.into_iter().all(|t| collect_text_alignment(t, None, &mut shared)) { shared.or(default) } else { None } } /// The seven alignment buttons shared by Paragraph and Properties; no button is selected @@ -492,7 +479,7 @@ pub(crate) fn number_sample(style: vectorcraft_doc::text::NumberStyle, n: u32) - /// the Type tool's anchor and caret past the characters inserted at or before them). pub(crate) fn convert_list_to_text(app: &mut VectorcraftApp) -> Result { text_style(app).ok_or("select some type first")?; - run_on_paragraphs(app, "text.convertListToText", json!({})) + run_on(app, "text.convertListToText", json!({}), false) } /// The Bullets button and the arrow beside it (Paragraph panel). The button makes the paragraphs diff --git a/crates/ui-egui/src/panels/paragraph/tests.rs b/crates/ui-egui/src/panels/paragraph/tests.rs index 50c17001db..180f0b1fa1 100644 --- a/crates/ui-egui/src/panels/paragraph/tests.rs +++ b/crates/ui-egui/src/panels/paragraph/tests.rs @@ -1035,3 +1035,58 @@ fn reset_panel_leaves_an_undo_group_open_in_another_document() { app.run("edit.undoGroup.end", json!({})).unwrap(); assert_eq!(steps(app.session.active().unwrap()), a_steps, "the later edit is part of the Batch step"); } + +/// With the Selection tool a selected frame of a threaded story stands for the whole story: the +/// Paragraph panel's changes and Reset Panel reach its locked and hidden frames, each in one undo +/// step, other type keeps its paragraphs, and the alignment buttons read every frame. +#[test] +fn selection_tool_paragraph_changes_reach_every_frame_of_the_story() { + let mut app = VectorcraftApp::new(Session::new(), Default::default()); + app.run("file.new", json!({"width": 900, "height": 300})).unwrap(); + let story = "The quick brown fox jumps over the lazy dog.\n".repeat(12); + let area = json!({"x": 10, "y": 10, "text": story, "size": 12, "area": {"width": 150, "height": 60}}); + let a = app.run("text.create", area).unwrap()["id"].as_u64().unwrap(); + let b = app.run("text.thread.add", json!({"from": a, "rect": [200, 10, 150, 60]})).unwrap()["id"].as_u64().unwrap(); + let c = app.run("text.thread.add", json!({"from": b, "rect": [400, 10, 150, 200]})).unwrap()["id"].as_u64().unwrap(); + let other = app.run("text.create", json!({"x": 10, "y": 250, "text": "Other", "size": 12})).unwrap()["id"].as_u64().unwrap(); + app.run("select.set", json!({"ids": [b]})).unwrap(); + app.run("object.lock", json!({})).unwrap(); + app.run("select.set", json!({"ids": [c]})).unwrap(); + app.run("object.hide", json!({})).unwrap(); + app.run("select.set", json!({"ids": [a]})).unwrap(); + let paragraphs = |app: &VectorcraftApp, id: u64| match &app.session.active().unwrap().doc.node(NodeId(id)).unwrap().kind { + NodeKind::Text(t) => (0..t.paragraph_count()).map(|i| t.para_at(i).clone()).collect::>(), + _ => panic!("not text"), + }; + let undo_steps = |app: &VectorcraftApp| app.session.active().unwrap().history.undo.len(); + for id in [a, b, c] { + assert!(!paragraphs(&app, id).is_empty(), "frame {id} holds text"); + } + + let steps = undo_steps(&app); + format(&mut app, json!({"spaceBefore": 4})); + assert_eq!(undo_steps(&app), steps + 1, "one undo step"); + for id in [a, b, c] { + assert!(paragraphs(&app, id).iter().all(|p| (p.space_before - 4.0).abs() < 1e-9), "frame {id} takes the space"); + } + assert!(paragraphs(&app, other).iter().all(|p| p.space_before.abs() < 1e-9), "other type keeps its paragraphs"); + assert_eq!(shared_para_field(&app, |p| p.space_before), Some(4.0)); + + align(&mut app, "center").unwrap(); + for id in [a, b, c] { + assert!(paragraphs(&app, id).iter().all(|p| p.justify == Justify::Center), "frame {id} is centered"); + } + assert!(paragraphs(&app, other).iter().all(|p| p.justify != Justify::Center)); + assert_eq!(selected_alignment(&app, &ParaStyle::default()), Some(Justify::Center)); + // A hidden frame aligned otherwise leaves no alignment button on. + app.run("text.setStyle", json!({"ids": [c], "justify": "right"})).unwrap(); + app.run("select.set", json!({"ids": [a]})).unwrap(); + assert_eq!(selected_alignment(&app, &ParaStyle::default()), None); + + let steps = undo_steps(&app); + reset_panel(&mut app); + assert_eq!(undo_steps(&app), steps + 1, "Reset Panel is one undo step"); + for id in [a, b, c] { + assert!(paragraphs(&app, id).iter().all(|p| p.space_before.abs() < 1e-9 && p.justify == Justify::Auto), "frame {id} is reset"); + } +} diff --git a/crates/ui-egui/src/panels/tabs.rs b/crates/ui-egui/src/panels/tabs.rs index bc1f9352c3..00814646c5 100644 --- a/crates/ui-egui/src/panels/tabs.rs +++ b/crates/ui-egui/src/panels/tabs.rs @@ -419,7 +419,9 @@ fn stops_json(stops: &[TabStop]) -> Value { ) } -/// Run `text.tabs.set` with `stops` on the text the panel acts on. Returns false when it fails. +/// Run `text.tabs.set` with `stops` on the text the panel acts on: with the Selection tool, every +/// frame of the selected stories ([`super::character::selected_stories`]). Returns false when it +/// fails. fn apply(app: &mut VectorcraftApp, stops: &[TabStop]) -> bool { if let Some((id, a, b)) = super::character::text_editing(app) { super::character::end_typing(app); @@ -430,7 +432,9 @@ fn apply(app: &mut VectorcraftApp, stops: &[TabStop]) -> bool { }; app.run("text.tabs.set", p).is_ok() } else { - app.run("text.tabs.set", json!({"stops": stops_json(stops)})).is_ok() + let mut p = json!({"stops": stops_json(stops)}); + super::character::target_selected_stories(app, &mut p); + app.run("text.tabs.set", p).is_ok() } } @@ -727,6 +731,20 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { resp.on_hover_text(tl!("Click to add a tab stop, drag to move it, drag it off the ruler to delete it")); } +/// Whether a paragraph of the whole story Clear All Tabs acts on has tab stops: after Select All in +/// threaded text, every frame of the edited story; with the Selection tool, every frame of the +/// selected stories ([`super::character::selected_stories`]). +fn story_has_tabs(app: &VectorcraftApp) -> bool { + let has_tabs = |t: &TextObject| (0..t.paragraph_count()).any(|i| !t.para_at(i).tabs.is_empty()); + match (super::character::text_editing(app), super::character::text_story(app), app.session.active()) { + (Some(_), Some(story), Some(st)) => { + story.iter().any(|id| matches!(st.doc.node(*id).map(|n| &n.kind), Some(NodeKind::Text(t)) if has_tabs(t))) + } + (Some(_), _, _) => false, + (None, _, _) => super::character::selected_story_texts(app).into_iter().any(has_tabs), + } +} + pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) { let Some((_, para, _)) = current_para(app) else { ui.add_enabled(false, egui::Button::new(tl!("Select text")).frame(false)); @@ -742,7 +760,7 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) { if sel >= stops.len() { sel = stops.len().saturating_sub(1); } - if menu_item(ui, tl!("Clear All Tabs"), !stops.is_empty(), false) + if menu_item(ui, tl!("Clear All Tabs"), !stops.is_empty() || story_has_tabs(app), false) && let Err(e) = super::paragraph::run_on_paragraphs(app, "text.tabs.clear", json!({})) { app.status(e); diff --git a/crates/ui-egui/src/panels/tabs/tests.rs b/crates/ui-egui/src/panels/tabs/tests.rs index 6472b1017b..e260db70ab 100644 --- a/crates/ui-egui/src/panels/tabs/tests.rs +++ b/crates/ui-egui/src/panels/tabs/tests.rs @@ -642,6 +642,43 @@ fn text_of(app: &VectorcraftApp, id: u64) -> vectorcraft_doc::TextObject { } } +/// With the Selection tool, tab stops set in the panel go to every paragraph of every frame of a +/// selected threaded story, its locked and hidden frames included. +#[test] +fn selection_tool_tab_stops_reach_every_frame_of_the_story() { + let (mut app, frames) = split_story_app(); + app.run("select.set", json!({"ids": [frames[1]]})).unwrap(); + app.run("object.lock", json!({})).unwrap(); + app.run("select.set", json!({"ids": [frames[2]]})).unwrap(); + app.run("object.hide", json!({})).unwrap(); + app.run("select.set", json!({"ids": [frames[0]]})).unwrap(); + let stop = TabStop { position: 36.0, align: Default::default(), leader: String::new(), align_on: '.' }; + assert!(apply(&mut app, std::slice::from_ref(&stop))); + for id in frames { + let t = text_of(&app, id); + assert!((0..t.paragraph_count()).all(|i| t.para_at(i).tabs == [stop.clone()]), "frame {id} takes the stop"); + } +} + +/// With the Selection tool, Clear All Tabs is on when only another frame of the selected story has +/// tab stops, and clears them there. +#[test] +fn clear_all_tabs_is_on_when_another_frame_of_the_story_has_stops() { + let (mut app, [a, b, c]) = split_story_app(); + app.run("text.tabs.set", json!({"ids": [c], "stops": [{"position": 36}]})).unwrap(); + app.run("select.set", json!({"ids": [c]})).unwrap(); + app.run("object.hide", json!({})).unwrap(); + app.run("select.set", json!({"ids": [a]})).unwrap(); + assert!(current(&app).unwrap().1.is_empty(), "the selected frame has no stops"); + assert!(story_has_tabs(&app)); + super::super::paragraph::run_on_paragraphs(&mut app, "text.tabs.clear", json!({})).unwrap(); + for id in [a, b, c] { + let t = text_of(&app, id); + assert!((0..t.paragraph_count()).all(|i| t.para_at(i).tabs.is_empty()), "frame {id} has no stops"); + } + assert!(!story_has_tabs(&app)); +} + /// Each paragraph of the story of `frames` by its first word, with its left indent and first-line /// position, counted once; each piece of a paragraph split between frames has the same values. fn story_paragraphs(app: &VectorcraftApp, frames: &[u64]) -> Vec<(String, f64, f64)> { diff --git a/crates/ui-egui/src/tests/font_menu.rs b/crates/ui-egui/src/tests/font_menu.rs index 2c600d1aa3..ff249bbed4 100644 --- a/crates/ui-egui/src/tests/font_menu.rs +++ b/crates/ui-egui/src/tests/font_menu.rs @@ -1040,6 +1040,22 @@ fn open_menu_with(id: &str, left: f32, width: f32, screen: egui::Vec2, look: Men assert!(frames < 1000, "the menu's samples are still rendering after {frames} frames"); shapes = frame(vec![]); } + // egui places the menu by the size it had the frame before. When a name measured late (a face + // added for its script, a font found in the background) widens it on that frame, the menu sits + // where the narrower one fit until the next: draw until it stays put. + let filter_at = |shapes: &[egui::epaint::ClippedShape]| { + shapes.iter().find_map(|s| match &s.shape { + egui::Shape::Text(t) if t.galley.text() == crate::i18n::t("Any Kind") => Some(t.pos), + _ => None, + }) + }; + for _ in 0..100 { + let before = filter_at(&shapes); + shapes = frame(vec![]); + if filter_at(&shapes) == before && !crate::font_menu::wait_for_samples(&ctx) { + break; + } + } let mut texts = vec![]; let mut samples = vec![]; let mut tints = vec![]; diff --git a/docs/localization-parity.md b/docs/localization-parity.md index 6cbad8f5e3..ca5906af9e 100644 --- a/docs/localization-parity.md +++ b/docs/localization-parity.md @@ -49,7 +49,7 @@ plus review. Native-speaker review is human work and isn't in the hours. | Language | Code | Translated | Status | |---|---|---|---| -| Traditional Chinese (Taiwan) | `zh-hant` | 4,892 rows, 790 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted (80% overall) | partial | +| Traditional Chinese (Taiwan) | `zh-hant` | 8,820 rows, 3,438 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it; menus, `tl!` literals and messages were complete when counted on 2026-10-21 (80% overall) | partial | | Italian | `it` | 8,757 rows, 3,422 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it | full | | Dutch | `nl` | 7,299 rows, 1,609 of them `@msg` and 47 `@msgplural` (counted 2026-11-13 on `main` at `9a1a158a3`): in `COMPLETE_MESSAGES`, and the untranslated report lists the same missing messages for it as for German; one/other plurals | full | | Danish | `da` | 5,279 rows, 750 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial; one/other plurals | full | @@ -58,7 +58,7 @@ plus review. Native-speaker review is human work and isn't in the hours. | Hungarian | `hu` | 5,253 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one plural form | full | | Polish | `pl` | 9,044 rows, 3,439 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 46 missing messages for it, and 47 menu strings, 26 `tl!` literals, 11 undo labels and 45 swatch names; one/few/many plurals | full; native review pending | | Finnish | `fi` | 5,318 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one/other plurals, 797 `@msg` rows | full; AI-assisted, native proofreading pending | -| Czech | `cs` | 5,240 catalog entries, including 795 `@msg` rows (counted 2026-10-21); menus, literals and messages complete when counted | catalog complete; render-site gaps reduced; native review pending | +| Czech | `cs` | 9,155 rows, 3,445 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it | catalog complete; render-site gaps reduced; native review pending | | Bosnian | `bs` | 5,841 rows (counted 2026-10-30): menus, `tl!` literals and messages complete when counted; one/few/other plurals | full; AI-assisted, native review pending | | Swedish | `sv` | 5,251 rows, 795 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one/other plurals | full; native review welcome | | Bulgarian | `bg` | 5,245 rows, 763 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial | full; AI-drafted, native review pending | diff --git a/docs/mcp.md b/docs/mcp.md index f756bc8c97..c770611d76 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -2991,7 +2991,8 @@ already walks Image Trace. Short agent entry points: a symbol with guides keeps its corners at their size, and `symbol.breakLink` gives its art as it draws; dragging a guide on the canvas in symbol editing mode sends `nineSliceGuides` in one undo step; `type` is Symbol Type, `static` by default for the command and `dynamic` by default in the Symbol Options dialog), - `symbol.place {name?, x?, y?}`, `symbol.breakLink {ids?}` (the art keeps the instance's opacity mask; a hidden or locked instance's + `symbol.place {name?, x?, y?}`, `symbol.breakLink {ids?}` (the art keeps the instance's opacity mask and its bounding box, square after + `object.resetBoundingBox`; a hidden or locked instance's art stays hidden or locked and is not selected), `symbol.replace`, `symbol.edit {id?, ids?, name?, x?, y?, artboard?, viewCenter?}` (symbol editing mode: the symbol's art on a temporary isolated layer, where the instance `id` shows it or centered on (x, y), by default on the center of artboard @@ -7379,8 +7380,8 @@ restore the selection that was cleared. While the slices are locked or hidden, a ``` The Slice tool (`slice`, Shift+K) and the Slice Selection tool (`sliceSelection`) reduce to commands: -`object.slice.create {x, y, width, height}` (the Slice tool's drag; it snaps to ruler guides), `object.slice.select -{slices?, toggle?}`, `object.slice.move {slices?, dx, dy}` (an object slice moves its object), +`object.slice.create {x, y, width, height}` (the Slice tool's drag; it snaps as drawn points do, then to ruler guides), +`object.slice.select {slices?, toggle?}`, `object.slice.move {slices?, dx, dy}` (an object slice moves its object), `object.slice.setRect {id, x, y, width, height}` (user slices) and `object.slice.delete {slices?}`. Slice ids are user slice ids and the ids of objects with an object slice. `object.slice.select` with `slices` left out or null deselects the slices. @@ -8129,7 +8130,9 @@ square to the page. `object.resetBoundingBox` squares the box again without movi object inside the selected ones: the children of groups, compound paths, clip groups, blends, envelopes, repeats and intertwines, and the art of linked opacity masks (an unlinked mask's art keeps its angle). Ungroup, Release Clipping Mask, Release Compound Path, Blend Expand, Release Envelope, Release Repeat, Release Intertwine and Release Opacity Mask -then bring back boxes square to the page. +then bring back boxes square to the page. `symbol.breakLink` and `object.expand` give a symbol instance's art the +instance's own box: after a reset the art stands square to the page, and an object turned inside the symbol keeps its +angle relative to the instance's box. ```json {"name":"run_command","arguments":{"command":"object.rotate","params":{"angle":45,"absolute":true}}} @@ -10723,7 +10726,8 @@ Tools: centre (move), the box's lower right corner (size; Shift keeps the proportions), a handle above the top (rotation; Shift: 45° steps), a dot on the top edge (corner radius) and one of the kind's own (a star's or ring's inner radius, a gear's tooth height, an arrow's head, a cross's bar, a heart's notch, a bubble's tail tip); each drag runs - `addon.pathtools.shape.set`. A double-click on the canvas places a shape with the last settings. Options + `addon.pathtools.shape.set`. A double-click on the canvas places a shape with the last settings. A new shape's + center and the point dragged out from it snap as drawn points do. Options (`tool.setOption`, or the panel with no shape selected) are the next shape's numbers, as the commands take them. - **Corner Tool** (`cornerTool`, or the UI command `addon.pathtools.cornerTool`, which also shows the Anchor Inspector panel with its Corners section): edits the app's Live Corners on any path, selected or not. Over an anchor where two diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 296bd84b2b..c71db37c33 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -1,6 +1,6 @@ # Parity with Adobe Illustrator -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-13 · **Change:** minor (Snap to Point with Smart Guides off draws no Smart Guides labels or lines, #7250; previously: 3D: the seams of Extrude & Bevel, Inflate and Rotate under a white light, and of the faces of Extrude & Bevel (Classic), Revolve (Classic) and Rotate (Classic), went from miter to round joins, so white-light 3D output is expected to differ from the 2026-10-17 comparison at facet corners (not measured: the scenes were not exported again); previously: `.ai` and EPS import: in layers that don't draw as the page, art that differs away from an envelope of type no longer costs it its editable type; it keeps its drawn art where, in the pixels it and its drawn art ink, the layers with it differ from the page more than its own check allows, or past the envelopes' share of the page check, #7141; Character panel: the Set Font Height Reference dropdown shows an icon before each reference, #6304; scores and estimates unchanged; previously: Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter, so a top object saved with its sides' curves in pieces draws as its `.ai` drawn art, #7097; scores and estimates unchanged; previously: Graphic Styles list fills a taller panel, #2992; scores and estimates unchanged; previously: PDF import: glyphs in a span with an empty ActualText come in as outlines, #6971; scores and estimates unchanged; previously: library panels' lists fill a taller panel, #2992; scores and estimates unchanged; previously: Swatches list fills a taller panel, #1638; scores and estimates unchanged; previously minor: Object › Rasterize with the Grayscale or Bitmap colour model makes a grayscale image, #6969; scores and estimates unchanged; previously minor: `.ai` and EPS import: type in an envelope with Distort Appearance is also tried mapped from the box of what it paints, miter tips and moved strokes included, after its glyphs grown by half its strokes' weight (#6824; #6617: Swatches panel menu: Show Recent Colors; scores unchanged; previously minor: icon-strip flyouts also resize from the top edge and the canvas-side top corner, keeping the moved top in workspaces (storytold/craft-libs#1094); scores and estimates unchanged; previously: #6865: explicitly requested oversized editing artboard; macOS: the canvas cursor stays after the pointer moves, #6362; scores and estimates unchanged; previously minor: Type tool: kerning at a caret at the start of a line moves the character after it, #5111; scores and estimates unchanged; previously minor: Rulers: the zero point dragged out of the rulers' corner snaps as a drawn point does; previously minor: Live Paint Bucket fills faces crossed in one drag (#6373); previously: #6404: transform-aware Eyedropper character copying; scores and estimates unchanged; previously: Envelopes: with Distort Appearance, type's strokes paint along the bent glyph outlines at their own weight, as users' `.ai` files draw them, which changes how VectorCraft's own envelopes of stroked type draw (#6644; scores and estimates unchanged); previously minor: G5: Energy Beams brush library; bundled content ~44% → ~46%; previously minor: G5: Skill Icons symbol library; bundled content ~42% → ~44%; previously minor: `.ai` and EPS import: an envelope saved in Edit Contents whose mesh lies away from its drawn art by a move opens live on that art (#6570; scores and estimates unchanged); previously minor: ruler double-click adds a guide at the pointer, #5239; G5: Status Effects graphic style library; bundled content ~40% → ~42%; MCP symbol libraries list UI Frames and Map Markers; previously minor: G5: Inventory Icons built-in symbol library; bundled content ~38% → ~40%; previously minor: `.ai` and EPS import: stroked type in an envelope maps from its glyphs grown by half its stroke (#3179; scores and estimates unchanged); previously minor: `.ai` and EPS import: warps of type open as mesh envelopes on their saved grid where VectorCraft's warp doesn't draw as their drawn art (#3179; scores and estimates unchanged); G5: Game Trails brush library; bundled content ~36% → ~38%; previously minor: Edit › Edit Custom Dictionary…: its dialog adds, deletes and changes the custom dictionary's words, #4936; previously minor: `.ai` and EPS import: envelopes of type open live where they draw as their drawn art and the layers with them draw as the page (#3179; scores and estimates unchanged); G5: Game HUD graphic style library; bundled content ~34% → ~36%; previously minor: Line Arrow arrowhead (#5421; scores and estimates unchanged); G5: Map Markers built-in symbol library; bundled content ~32% → ~34%; previously minor: right-click on type: Spelling › Auto Spell Check, with its check mark, #4936; previously minor: right-click on a word Auto Spell Check underlined: its suggestions, Ignore All and Add to Dictionary, #4936; previously minor: Canvas: a 3D effect changed on type or a group redraws where its solid was; Fit to Artwork Bounds and per-artboard SVG export build each solid once for all artboards; previously minor: Effect Gallery: a thumbnail for each filter and a preview area inside the dialog, on an original drawing; Raster effects 52% → 55%, hours 1–2 → none; headline numbers unchanged; Auto Spell Check: `edit.autoSpellCheck` underlines the unknown words, #4936; previously minor: PDF editable import preserves authored ActualText once, including empty/nested spans and authored ordering (#6165); cross-line/style layout remains approximate; scores and estimates unchanged; PDF marked-text export (#6309): compatible glyphs stay on one layout line with per-glyph offsets; scores and estimates unchanged; G5: UI Frames built-in symbol library with default 9-slice; bundled content ~32%; previously minor: G5: dynamic symbol part on-canvas opacity/blend/gradient/pattern; strokes remaining no longer lists Overlap/auto corners; symbols ~88%; previously minor: interim macOS cursor delivery, #2292; native validation pending; scores and estimates unchanged; previously minor: harakat paint fallback clarified; previously minor: current Guides feature-area rows consolidated using existing ruler evidence; scores and estimates unchanged; previously minor: Control bar › Snapping includes the existing Snap to Glyph and Alignment Guides toggles (#6164); scores and estimates unchanged; previously minor: G5 docs: Art brush Overlap and Pattern brush auto corners removed from strokes remaining; symbols remaining lists dynamic on-canvas beyond solid and guides outside the art; previously minor: custom dictionary and Ignore All: `text.spelling.addWord`, `removeWord`, `changeWord`, `dictionary` and `ignoreAll`, #4936; previously minor: EPS import: embedded fonts (composite, Type 42, CID-keyed, Type 1, CFF FontSet) draw their glyphs; spell check engine: `text.spelling.check` and `text.spelling.suggest` on craft-proof, #4936; previously minor: floating tab groups collapse into the side icon rail and opened rail panels fold back into it, #5925 in part; `.ai`/EPS type keeps its tab stops, and right-aligned lines with tabs lay out as the file's page, #6147; `.ai`/EPS type from the text document lays its lines out closer to the file's page, within limits, #6137; `.ai` and EPS import: older Art brush objects read; numeric fields step on wheel hover without taking keyboard focus, and a panel wheel turn cannot seed a canvas zoom glide, #5949; Character Styles panel: a double-click on a style's row opens its Character Style Options; the dialog keeps a fixed width and scrolls its sections, so its buttons stay on screen; Tools stays beside the canvas with left-side panels; new gradients follow document color mode; Selection QoL: marquee modes and visible feedback, #5313; SVG CSS classes survive export and repeated import in all four styling modes (#2480); current-main integration retains event attributes and scripts; #3380 deletion-only review follow-up: independent survivors keep gradient placement, owned subpaths avoid discarded copies, and contracts/status/evidence are clarified; endpoint highlighting remains open; scores and estimates unchanged; the canvas keeps selection outlines and anchors between frames; Indian-language hyphenation review and license allowlist, #4947; Stroke gradients: an arrowhead aligned to the tip is painted to the corners of its base, #5964; Drop Shadow and glow dialogs: spinner arrows, #5367, #5368; Stroke Weight Up and Down shortcuts, #5797; Hindi catalog and contributor loanword preferences; full wording review in progress; Properties in Edit Artboards: a Transform section with the reference point above the Artboards section, #5219; the Control bar's Stroke: and Opacity: links scrub their fields, #4088; an image zoomed in on is separated, colorized or proofed only where it shows (#4155); a document's first frame renders on the render worker, so opening a heavy file no longer freezes the window, #4155; Control bar Paragraph section with type selected, #5372; translating unchanged type reuses its glyph and character-stroke outlines; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026; Units › East Asian Type acts, with Q and Ha units; scores unchanged) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-14 · **Change:** minor (a closed Pencil stroke closes with a straight segment; previously: Snap to Point with Smart Guides off draws no Smart Guides labels or lines, #7250; previously: 3D: the seams of Extrude & Bevel, Inflate and Rotate under a white light, and of the faces of Extrude & Bevel (Classic), Revolve (Classic) and Rotate (Classic), went from miter to round joins, so white-light 3D output is expected to differ from the 2026-10-17 comparison at facet corners (not measured: the scenes were not exported again); previously: `.ai` and EPS import: in layers that don't draw as the page, art that differs away from an envelope of type no longer costs it its editable type; it keeps its drawn art where, in the pixels it and its drawn art ink, the layers with it differ from the page more than its own check allows, or past the envelopes' share of the page check, #7141; Character panel: the Set Font Height Reference dropdown shows an icon before each reference, #6304; scores and estimates unchanged; previously: Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter, so a top object saved with its sides' curves in pieces draws as its `.ai` drawn art, #7097; scores and estimates unchanged; previously: Graphic Styles list fills a taller panel, #2992; scores and estimates unchanged; previously: PDF import: glyphs in a span with an empty ActualText come in as outlines, #6971; scores and estimates unchanged; previously: library panels' lists fill a taller panel, #2992; scores and estimates unchanged; previously: Swatches list fills a taller panel, #1638; scores and estimates unchanged; previously minor: Object › Rasterize with the Grayscale or Bitmap colour model makes a grayscale image, #6969; scores and estimates unchanged; previously minor: `.ai` and EPS import: type in an envelope with Distort Appearance is also tried mapped from the box of what it paints, miter tips and moved strokes included, after its glyphs grown by half its strokes' weight (#6824; #6617: Swatches panel menu: Show Recent Colors; scores unchanged; previously minor: icon-strip flyouts also resize from the top edge and the canvas-side top corner, keeping the moved top in workspaces (storytold/craft-libs#1094); scores and estimates unchanged; previously: #6865: explicitly requested oversized editing artboard; macOS: the canvas cursor stays after the pointer moves, #6362; scores and estimates unchanged; previously minor: Type tool: kerning at a caret at the start of a line moves the character after it, #5111; scores and estimates unchanged; previously minor: Rulers: the zero point dragged out of the rulers' corner snaps as a drawn point does; previously minor: Live Paint Bucket fills faces crossed in one drag (#6373); previously: #6404: transform-aware Eyedropper character copying; scores and estimates unchanged; previously: Envelopes: with Distort Appearance, type's strokes paint along the bent glyph outlines at their own weight, as users' `.ai` files draw them, which changes how VectorCraft's own envelopes of stroked type draw (#6644; scores and estimates unchanged); previously minor: G5: Energy Beams brush library; bundled content ~44% → ~46%; previously minor: G5: Skill Icons symbol library; bundled content ~42% → ~44%; previously minor: `.ai` and EPS import: an envelope saved in Edit Contents whose mesh lies away from its drawn art by a move opens live on that art (#6570; scores and estimates unchanged); previously minor: ruler double-click adds a guide at the pointer, #5239; G5: Status Effects graphic style library; bundled content ~40% → ~42%; MCP symbol libraries list UI Frames and Map Markers; previously minor: G5: Inventory Icons built-in symbol library; bundled content ~38% → ~40%; previously minor: `.ai` and EPS import: stroked type in an envelope maps from its glyphs grown by half its stroke (#3179; scores and estimates unchanged); previously minor: `.ai` and EPS import: warps of type open as mesh envelopes on their saved grid where VectorCraft's warp doesn't draw as their drawn art (#3179; scores and estimates unchanged); G5: Game Trails brush library; bundled content ~36% → ~38%; previously minor: Edit › Edit Custom Dictionary…: its dialog adds, deletes and changes the custom dictionary's words, #4936; previously minor: `.ai` and EPS import: envelopes of type open live where they draw as their drawn art and the layers with them draw as the page (#3179; scores and estimates unchanged); G5: Game HUD graphic style library; bundled content ~34% → ~36%; previously minor: Line Arrow arrowhead (#5421; scores and estimates unchanged); G5: Map Markers built-in symbol library; bundled content ~32% → ~34%; previously minor: right-click on type: Spelling › Auto Spell Check, with its check mark, #4936; previously minor: right-click on a word Auto Spell Check underlined: its suggestions, Ignore All and Add to Dictionary, #4936; previously minor: Canvas: a 3D effect changed on type or a group redraws where its solid was; Fit to Artwork Bounds and per-artboard SVG export build each solid once for all artboards; previously minor: Effect Gallery: a thumbnail for each filter and a preview area inside the dialog, on an original drawing; Raster effects 52% → 55%, hours 1–2 → none; headline numbers unchanged; Auto Spell Check: `edit.autoSpellCheck` underlines the unknown words, #4936; previously minor: PDF editable import preserves authored ActualText once, including empty/nested spans and authored ordering (#6165); cross-line/style layout remains approximate; scores and estimates unchanged; PDF marked-text export (#6309): compatible glyphs stay on one layout line with per-glyph offsets; scores and estimates unchanged; G5: UI Frames built-in symbol library with default 9-slice; bundled content ~32%; previously minor: G5: dynamic symbol part on-canvas opacity/blend/gradient/pattern; strokes remaining no longer lists Overlap/auto corners; symbols ~88%; previously minor: interim macOS cursor delivery, #2292; native validation pending; scores and estimates unchanged; previously minor: harakat paint fallback clarified; previously minor: current Guides feature-area rows consolidated using existing ruler evidence; scores and estimates unchanged; previously minor: Control bar › Snapping includes the existing Snap to Glyph and Alignment Guides toggles (#6164); scores and estimates unchanged; previously minor: G5 docs: Art brush Overlap and Pattern brush auto corners removed from strokes remaining; symbols remaining lists dynamic on-canvas beyond solid and guides outside the art; previously minor: custom dictionary and Ignore All: `text.spelling.addWord`, `removeWord`, `changeWord`, `dictionary` and `ignoreAll`, #4936; previously minor: EPS import: embedded fonts (composite, Type 42, CID-keyed, Type 1, CFF FontSet) draw their glyphs; spell check engine: `text.spelling.check` and `text.spelling.suggest` on craft-proof, #4936; previously minor: floating tab groups collapse into the side icon rail and opened rail panels fold back into it, #5925 in part; `.ai`/EPS type keeps its tab stops, and right-aligned lines with tabs lay out as the file's page, #6147; `.ai`/EPS type from the text document lays its lines out closer to the file's page, within limits, #6137; `.ai` and EPS import: older Art brush objects read; numeric fields step on wheel hover without taking keyboard focus, and a panel wheel turn cannot seed a canvas zoom glide, #5949; Character Styles panel: a double-click on a style's row opens its Character Style Options; the dialog keeps a fixed width and scrolls its sections, so its buttons stay on screen; Tools stays beside the canvas with left-side panels; new gradients follow document color mode; Selection QoL: marquee modes and visible feedback, #5313; SVG CSS classes survive export and repeated import in all four styling modes (#2480); current-main integration retains event attributes and scripts; #3380 deletion-only review follow-up: independent survivors keep gradient placement, owned subpaths avoid discarded copies, and contracts/status/evidence are clarified; endpoint highlighting remains open; scores and estimates unchanged; the canvas keeps selection outlines and anchors between frames; Indian-language hyphenation review and license allowlist, #4947; Stroke gradients: an arrowhead aligned to the tip is painted to the corners of its base, #5964; Drop Shadow and glow dialogs: spinner arrows, #5367, #5368; Stroke Weight Up and Down shortcuts, #5797; Hindi catalog and contributor loanword preferences; full wording review in progress; Properties in Edit Artboards: a Transform section with the reference point above the Artboards section, #5219; the Control bar's Stroke: and Opacity: links scrub their fields, #4088; an image zoomed in on is separated, colorized or proofed only where it shows (#4155); a document's first frame renders on the render worker, so opening a heavy file no longer freezes the window, #4155; Control bar Paragraph section with type selected, #5372; translating unchanged type reuses its glyph and character-stroke outlines; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026; Units › East Asian Type acts, with Q and Ha units; scores unchanged) > > Oversized artboard import update (2026-11-12): Explicit editing-data import retains a single artboard beyond a capped 14,400 pt PDF page (#6865). > @@ -56,6 +56,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard | Date | Change | Summary | |---|---|---| +| 2026-11-14 | minor | Pencil and Paintbrush: a closed stroke (Alt at the release, or ending within Close Paths When Ends Are Within of its start) is fitted as the open stroke would be and closed by a straight segment back to its start, instead of curving on past both ends (`pencil_alt_closes_a_stroke_straight_back_to_its_start` in `crates/engine/src/tests/draw2.rs`). Scores and estimates unchanged. | | 2026-11-13 | minor | Snap to Point: with Smart Guides off it still pulls drawn and dragged points onto anchors and ruler guides, but draws none of the Smart Guides labels ("anchor") or lines (#7250; `guides::tests::snap_to_point_without_smart_guides_shows_no_guides`). Scores and estimates unchanged. | | 2026-11-13 | minor | Graphic Styles: in a panel made taller the list fills the space above the footer instead of stopping at 220 pt (#2992; `the_list_fills_a_tall_panel_above_its_footer` in `crates/ui-egui/src/panels/graphic_styles.rs`). Scores and estimates unchanged. | | 2026-11-13 | minor | PDF import: glyphs inside a marked-content span with an empty `ActualText` come in as outlines in their fill and stroke instead of being left out, adding no text (#6971; `empty_actual_text_keeps_the_glyphs_art` in `crates/pdf/src/tests/actual_text.rs`). Scores and estimates unchanged. | @@ -895,6 +896,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - The status bar translates the limits a plug-in run can exceed (its instruction, time and memory budgets and its output size) and the error of a plug-in removal that leaves the plug-in's grant in the plug-in store, in every language that translates every message. The untranslated-strings report also lists messages that an error or a status takes from a `&str` constant (`plugin_limit_errors_are_translated`, `message_scan_reads_messages_held_in_constants`). - The status bar translates the plug-in host's other errors (manifest, module and run checks, the output an importer, exporter or effect returns, and the approval a plug-in's permissions need) in every language that translates every message. A JSON object or array inside a message stays as written, and a message that wraps another one, such as `plug-in manifest: {0}`, is matched by its own row before a row that starts with a placeholder. The reasons inside these errors (what is wrong with a parameter's spec or dialog keys, the value a parameter needs, what is wrong with an object, stroke, paint or effect in a plug-in's output) are translated with them, and the untranslated-strings report lists the reasons the plug-in host's error helpers take (`plugin_messages_are_translated_in_every_complete_catalog`, `plugin_errors_translate_with_their_values`, `plugin_error_reasons_are_translated_with_the_error`, `message_scan_reads_plugin_helpers`, `templates_that_start_with_text_match_first`). - The status bar translates the errors a script's `File` and `Folder` objects, `vc.run`, `$.evalFile`, the `$` object's properties and functions, `alert`, `confirm` and `prompt`, `vc.document` and `vc.log` raise, the limits a run can pass, and the errors of Drop Script Engine, and the line for a run that fails (a syntax error, a thrown error, a limit, a stop or an internal error, with the script's name, the line and column, the included file it is in and the files left written), in every language that translates every message. The script's name, paths, numbers, command ids and the text a script throws itself are shown as they are. A failure with no line and column, such as an error in code `eval` compiled, is shown with one colon after the script's name (`an_error_without_a_place_names_the_script_and_kind`). A message template that names a value twice matches only when both places hold the same text, so the line for a failed run is not taken for the message inside it (`a_repeated_placeholder_matches_the_same_text`). The untranslated-strings report also lists the messages the script host's `fail`, `value` and `over` helpers take and the errors the script interpreter throws, and a constant's text comes from the file or crate that declares it, so the Scripts menu's headers are not listed as messages (`script_errors_are_translated`, `script_host_errors_are_translated`, `message_scan_reads_script_interpreter_errors`, `message_scan_reads_constants_of_the_file_and_its_crate`, `message_scan_skips_test_modules_with_any_test_cfg`). + - The Traditional Chinese catalog (`crates/ui-egui/src/i18n/zh-hant.tsv`) has an `@msg` row for the status and error messages the untranslated report (`untranslated_report`) finds in the sources, 3,438 `@msg` rows in all: the errors of commands, scripts, file import and export and plug-ins. The report lists 40 Traditional Chinese messages: open #7211, #7116 and #7330 add the rows for 38 of them, and the other 2 have no row in any catalog. A message with two placeholders in a row (`Template::parse` in `crates/ui-egui/src/i18n/catalog.rs`) is still shown in English. - Localised UI: menus (in-window and native), panels, dialogs, toolbar and Preferences read from per-language catalogs (`crates/ui-egui/src/i18n`, see `docs/development.md`); Traditional Chinese (Taiwan), Simplified Chinese (mainland), Japanese, Korean, Vietnamese, German, Spanish, French, Italian, Polish, Brazilian Portuguese, Russian, Ukrainian, Georgian and Catalan ship complete, and Czech covers every menu label (and more), with system-locale detection on macOS, Windows, Linux and the web (the browser's languages, or `?lang=`), a Language preference and, on macOS, a VectorCraft ▸ Language menu. Names are never translated (fonts and their styles, layers, artboards, saved presets, user libraries, custom workspaces, recent files, plug-ins). The counts that Package's status and question, the folder search of Missing Fonts and Find Linked Files, the modified and missing linked file prompts and the CSS Properties panel's notes show use the interface language's plural forms instead of a fixed "(s)" form. Evidence: `the_missing_links_note_uses_each_count_form` in `crates/ui-egui/src/dialogs/tests_package.rs`, `the_modified_links_question_uses_each_count_form` in `crates/ui-egui/src/dialogs/missing_links.rs`, `search_counts_use_each_count_form` in `crates/ui-egui/src/dialogs/missing_fonts/tests.rs` and `the_unnamed_objects_note_uses_each_count_form` in `crates/ui-egui/src/panels/tests_css_properties.rs`. The status bar's messages for relinked, replaced, updated and embedded images, broken links, linked files that can't be read or changed on disk, images that can't be decoded, added and unavailable fonts, copied CSS, downloads and exports with their notes name one item in the singular and more in the plural, in English and in each language's plural forms (`counted_status_messages_take_the_plural_form` in `crates/ui-egui/src/i18n/tests.rs`). @@ -909,6 +911,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - The Transform panel menu's Transform Object Only, Transform Pattern Only and Transform Both (`transformPanelPatterns`) choose whether the fields, flips and menu flips of the Transform panel and the Properties panel's Transform section move the object and leave its pattern tiles, move the tiles alone, or both (until a choice they follow General › Transform Pattern Tiles, as before); Use Registration Point for Symbol (`useRegistrationPointForSymbol`) measures and transforms one selected symbol instance from its symbol's registration point, where the instance's flips, rotations and shears put it ([Transform panel overview](https://helpx.adobe.com/illustrator/desktop/manage-objects/reshape-transform-objects/transform-panel-overview.html); `panels::transform::tests::the_menu_chooses_whether_the_object_its_pattern_or_both_transform`, `use_registration_point_for_symbol_measures_an_instance_from_its_registration_point`, `use_registration_point_for_symbol_follows_a_transformed_instance`, `tests_prefs::transform_panel_patterns_defaults_to_following_the_general_preference`). - The Transform panel's Align to Pixel Grid checkbox (`object.setPixelAligned`) gives paths and compound paths a pixel-aligned property, saved in the native file: their horizontal and vertical straight segments sit on whole points (half points under an odd centered stroke) with whole stroke weights, and every move, scale, rotation, reflection, Transform Each, Align move, Transform panel change, move of direct-selected anchors or of one anchor, move of a compound path's path on its own, artboard move, resize or copy that carries the art, Duplicate or paste that moves a copy, stroke edit and appearance edit that adds, removes, hides, repaints or reweighs a stroke snaps them again, while diagonal segments and curves keep their shape; a compound path made from an aligned path or compound path is aligned and snaps its paths with its own stroke; the box shows a dash for a mixed selection and is unavailable for type, images and groups ([Pixel-aligned property](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/pixel-preview-mode-for-web-graphics.html); `tests::pixelalign::turning_it_on_snaps_the_path_in_one_undo_step`, `it_stays_aligned_through_transforms`, `it_stays_aligned_when_its_artboard_moves`, `diagonal_segments_and_curves_keep_their_shape`, `type_and_images_cannot_be_aligned`, `the_property_is_saved_and_read_back`, `stroke_edits_keep_it_aligned`, `a_compound_path_of_aligned_paths_is_aligned`, `a_compound_path_of_an_aligned_compound_path_is_aligned`, `a_stroke_without_paint_snaps_to_whole_points`, `moving_direct_selected_anchors_keeps_it_aligned`, `moving_one_anchor_keeps_it_aligned`, `moving_a_path_of_an_aligned_compound_path_keeps_it_aligned`, `artboard_options_and_artboard_copies_keep_it_aligned`, `appearance_edits_keep_it_aligned`, `placed_gradients_follow_the_snapped_path`, `duplicates_and_pastes_keep_it_aligned`, `paths_added_to_or_moved_in_an_aligned_compound_path_keep_it_aligned`, `the_art_of_a_linked_opacity_mask_keeps_it_aligned`, `a_linked_opacity_mask_follows_a_snap`, `aligning_direct_selected_anchors_keeps_it_aligned`, `global_edit_keeps_its_members_aligned`, `a_path_with_live_corners_snaps_its_inner_edges`, `geometry_edits_keep_it_aligned`, `other_path_edits_keep_it_aligned`, `panels::transform::tests::align_to_pixel_grid_shows_and_sets_the_property`). - Align New Objects to Pixel Grid (`document.setup {alignNewObjectsToPixelGrid}`, a checkbox in New Document's Advanced Options and a checked item in the Transform panel menu) gives every path and compound path drawn in the document, the paths of a new grid or flare included, the pixel-aligned property, snapped in the step that draws it; it is on in the Mobile and Web presets and off in the others, saved presets and Recent keep it, and the document saves it. Type, images and groups do not take it, and art already in the document, pasted, duplicated or placed keeps its own property (VectorCraft's own rules) ([Pixel-aligned property](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/pixel-preview-mode-for-web-graphics.html); `tests::pixelalign::align_new_objects_makes_new_paths_pixel_aligned`, `align_new_objects_reaches_grids_flares_and_add_on_shapes`, `align_new_objects_is_saved_and_read_back`, `tests::newdoc::align_new_objects_to_pixel_grid_follows_the_preset`, `panels::transform::tests::align_new_objects_menu_item_toggles_the_active_document`, `dialogs::new_document::tests::align_new_objects_checkbox_follows_the_preset_and_reaches_the_document`). + - Break Link to Symbol and Object › Expand give a symbol instance's art the instance's own bounding box: after Reset Bounding Box the art stands square to the page, an object turned inside the symbol keeps its angle relative to the instance's box, a group added for the instance's opacity takes the instance's box, and the clip groups of 9-slice art take the angle of their cell. Compound shapes and Pathfinder receive an instance's art with the same angles (VectorCraft's own behavior; `bboxrotate::reset_bounding_box_then_expand_symbol_instance`, `reset_bounding_box_then_expand_keeps_the_angles_inside_the_symbol`, `expanding_a_faded_symbol_instance_gives_its_group_the_instance_box`, `expanding_a_reflected_symbol_instance_keeps_its_box`, `symbol_nine_slice::break_link_turns_the_cells_of_a_sliced_instance_with_its_box`, effects `outline_object_turns_an_instances_art_with_its_box`). - Object › Transform › Reset Bounding Box squares the box of every object inside the selected ones as well: the children of groups, compound paths, clip groups, blends, envelopes, repeats and intertwines, and the art of linked opacity masks. Ungroup and the release commands then bring back boxes square to the page (VectorCraft's own behavior; `bboxrotate::reset_bounding_box_squares_the_objects_inside_a_group`, `reset_bounding_box_squares_the_turned_members_of_a_square_group`, `reset_bounding_box_then_release_clipping_mask` and the other `reset_bounding_box_then_*` tests, `reset_bounding_box_leaves_the_art_of_an_unlinked_opacity_mask`). - After a rotation the Free Transform tool shows and drags the same turned bounding box as the Selection tool: its handles, their cursors and its rotate zone sit on the selection's own sides, a handle scales along those sides from the opposite handle ([the help page](https://helpx.adobe.com/illustrator/desktop/manage-objects/reshape-transform-objects/scale-objects.html)), Cmd/Ctrl on a side handle shears along that side, and Perspective Distort and Free Distort start from the turned box's corners (`object.distort` takes `angle` with `from`). The Scale and Reflect tools, their dialogs and commands, and the Transform panel's flips keep the page's axes (VectorCraft's own rule; `bboxrotate::free_transform_handles_turn_with_the_object_and_scale_along_its_axes`, `free_transform_shears_along_the_turned_side`, `free_transform_distort_starts_from_the_turned_box`, `xform::distort_reads_from_in_a_turned_frame_and_rejects_a_bad_angle`, tools `xform::free::tests::the_box_and_its_handles_turn_with_the_selection`). - Perspective Distort and Free Distort (`object.distort`) turn each warped object's bounding box as the warp turns the object at its own center, the objects inside groups, compound paths and clip groups and the art of linked opacity masks included, so the next Selection or Free Transform drag uses the tilted box; Object › Transform › Reset Bounding Box squares it again, and corners left where they are add no undo step (VectorCraft's own rule; `bboxrotate::distort_turns_an_upright_box_with_the_warp_at_its_center`, `distort_turns_each_member_and_linked_mask_by_its_own_warp`, `mirrored_and_collapsing_distorts_keep_valid_angles`, `distort_angles_undo_redo_and_reopen_together`, `xform::unchanged_distort_records_no_history`). @@ -996,6 +999,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - With the whole story of threaded text selected by Select All, Remove Line Breaks, Remove Paragraph Breaks and Type › Bullets and Numbering › Convert to Text act on the text of every frame as one undo step, and the story stays selected after Convert to Text; a selection inside one frame changes only that frame (VectorCraft's own behavior; `textedit::remove_breaks_takes_the_whole_story_that_select_all_selected`, `textedit::convert_to_text_takes_the_whole_story_that_select_all_selected`). - With the whole story of threaded text selected by Select All, the Character, Paragraph, OpenType, Tabs and Text Styles panels, the Justification dialog and the font menu change the frames that are in the edited frame's thread at the time of the change, locked and hidden frames included. A frame that has left the thread is not changed, and a frame added to the thread is (VectorCraft's own behavior; `panels::character::tests::story_changes_follow_the_edited_frames_thread_after_the_first_saved_frame_leaves`, `story_changes_leave_out_a_frame_that_left_and_take_in_a_frame_that_joined`, `story_changes_stay_in_the_edited_frame_once_its_thread_is_removed`, `story_changes_take_in_locked_and_hidden_frames`, `panels::tabs::tests::indent_markers_after_select_all_keep_each_story_paragraphs_indents`, `dialogs::justification::tests::justification_dialog_follows_the_story_thread_at_ok`). - With the whole story of threaded text selected by Select All, the Character, Paragraph, OpenType, Tabs and Text Styles panels, the Justification dialog and the font menu change the frames that are in the edited frame's thread at the time of the change, locked and hidden frames included. A frame that has left the thread is not changed, and a frame added to the thread is (VectorCraft's own behavior; `panels::character::tests::story_changes_follow_the_edited_frames_thread_after_the_first_saved_frame_leaves`, `story_changes_leave_out_a_frame_that_left_and_take_in_a_frame_that_joined`, `story_changes_stay_in_the_edited_frame_once_its_thread_is_removed`, `story_changes_take_in_locked_and_hidden_frames`). + - With the Selection tool, a Character or Paragraph panel change to a selected frame of threaded text changes every frame of its story, locked and hidden frames included, as one undo step. The anti-aliasing method, Variable Font axes, the Tabs panel's tab stops and both panels' Reset Panel change the whole story too, and the panels show a value only when every frame of the story has it. A story selected through several of its frames or through a group is changed once, and other type keeps its formatting (VectorCraft's own behavior; `panels::character::tests::selection_tool_changes_reach_every_frame_of_the_story`, `selection_tool_fields_read_every_frame_of_the_story`, `selected_stories_list_each_frame_once`, `panels::paragraph::tests::selection_tool_paragraph_changes_reach_every_frame_of_the_story`, `panels::tabs::tests::selection_tool_tab_stops_reach_every_frame_of_the_story`). - Switching from a Type tool to the Eyedropper keeps a whole story selected by Select All: a pick applies to the text of every frame as one undo step, and switching back restores the story selection (VectorCraft's own behavior; `textedit::switching_to_the_eyedropper_keeps_the_whole_story_selected`). - While the Type tool edits text, a character typed with AltGr is typed and runs no command. Firefox on Windows reports AltGr as Ctrl and Alt held, so in the web build AltGr+L (ł on a Polish layout) does not also open Layer Options for a new layer, and AltGr+Q (@ on a German layout) does not also run Reset Tracking and Kerning. A Ctrl+Alt chord that types no character runs its command. - On a layout without Latin letters, a one-key shortcut goes by the position of the key that typed the character, in the web build too, where the character arrives before its key press: on a Russian layout the P key (`з`) chooses the Pen, and two keys pressed in one frame each run their own shortcut. @@ -1188,8 +1192,8 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur Distance Guides: with Smart Guides on (View › Smart Guides and Preferences › Smart Guides › Invoke Distance Guides, on by default), something selected and the Selection tool, holding Alt/Option over another object shows the distances between the selection's bounds and that object's: on an axis on which they lie apart, one line across the gap between their facing edges; on one on which they overlap, the offsets of their left and right (top and bottom) edges, each line running across the middle of where they overlap, with a dashed line out to the other object's edge when it passes beside it. Over an empty part of an artboard it shows the selection's distances from the artboard's left, right, top and bottom edges. Each line has ticks at its ends and its length in a pill of the smart guide colour, in the General unit; letting Alt go, pressing (a pan or zoom press too), moving off them, leaving the canvas or a floating panel, menu or dialog over the pointer takes them away, and with the pointer still they follow what lies under it as the view scrolls, zooms or turns, as the document, the tab or the selection changes, and when the Selection tool is switched to. Behaviour from the public [Use Distance Guides for accurate placement](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/use-distance-guides-for-accurate-placement.html) and [Smart Guides options](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/smart-guides-options.html) pages, which describe hovering only: nothing shows while moving or nudging. Tests: `select::tests::alt_over_*`, `select::tests::distance_guides_need_alt_a_selection_and_smart_guides`, `tests_prefs::invoke_distance_guides_measures_the_selection_to_the_object_under_alt`, `canvas::tests::alt_over_another_object_draws_the_distance_guide_label`, `canvas::tests::distance_guides_go_when_the_hover_ends`, `canvas::tests::distance_guides_follow_what_lies_under_a_still_pointer`. A move pressed on a path's stroke, or within 6 px of its outline away from its anchors and center, is held by the nearest point of that path, with the Selection, Group Selection or Direct Selection tool, and a straight segment Direct Selection drags is held by its own nearest point. That point is what snaps, so the path lands exactly on a ruler guide (with "align") instead of the pressed spot landing there and the path a few pixels beside it, an offset that showed only zoomed far in (#3701). A press in the middle of a fill still snaps the pressed spot: the public [Align objects with guides](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/align-graphic-objects-with-guides.html) page has Snap to Point align the point under the pointer, which is placed exactly where the object should meet the guide. A bounding-box handle dragged with the Selection or Free Transform tool snaps what it moves as a dragged point snaps (#2054). With View › Snap to Grid on, it snaps to the nearest gridline, and with Snap to Pixel on, it snaps to whole pixels. With Smart Guides off and Snap to Point on, it snaps to the other objects' anchors and the ruler guides within the Snap to Point distance. With Smart Guides and Snap to Point both on, it lines up with the ruler guides as well as the other objects. Shift still keeps the proportions, and Alt still scales about the center. - A user slice's edge or corner handle dragged with the Slice Selection tool snaps as the Slice tool's drag does. With View › Snap to Grid on, it snaps to the nearest gridline, and with Snap to Pixel on, it snaps to whole pixels. Otherwise, with Smart Guides on, it lands on or lines up with the anchors, centers and edges of the art and the artboards, and with Smart Guides off and Snap to Point on, it snaps to the art's anchors and the ruler guides within the Snap to Point distance. Then a ruler guide within 5 px, shown and unlocked, moves the side or corner onto it. Shift still keeps the proportions, and Alt still resizes about the center. - View › Snap to Glyph: with Smart Guides on, a point drawn near a single line of live type lands on its glyphs' anchor points and lines up with its baseline, its x-height and the edges of each character's advance width (proximity guides), as well as the glyph bounds: each glyph's box gives edge guides and four corners a point lands on, even where its outline curves (the right of `B`), and the box follows the glyph's size, scaling and rotation (#5112). In rotated type these guides run at the type's angle, and type of one glyph also has angular guides along its slanted straight segments. A paragraph shows glyph bounds only. + A user slice's edge or corner handle dragged with the Slice Selection tool snaps as a bounding-box handle does. With View › Snap to Grid on, it snaps to the nearest gridline, and with Snap to Pixel on, it snaps to whole pixels. Otherwise, with Smart Guides on, it lands on or lines up with the anchors, centers and edges of the art and the artboards, and with Smart Guides off and Snap to Point on, it snaps to the art's anchors and the ruler guides within the Snap to Point distance. Then a ruler guide within 5 px, shown and unlocked, moves the side or corner onto it. Shift still keeps the proportions, and Alt still resizes about the center. + View › Snap to Glyph: with Smart Guides on, a point drawn near a single line of live type lands on its glyphs' anchor points and lines up with its baseline, its x-height and the edges of each character's advance width (proximity guides), as well as the glyph bounds: each glyph's box gives edge guides and four corners a point lands on, even where its outline curves (the right of `B`), and the box follows the glyph's size, scaling and rotation (#5112). In rotated type these guides run at the type's angle, and type of one glyph also has angular guides along its slanted straight segments. A paragraph shows glyph bounds only. A Parametric Shape's center (drawn with a drag or placed with a double-click) and the point dragged out from it, and the corners of a slice drawn with the Slice tool, snap as other drawn points do: to these guides, and to the anchors and segments of paths. Tested in `crates/tools/src/guides/tests.rs`. Snap to Glyph options (#4232, [Snap to Glyph options](https://helpx.adobe.com/illustrator/desktop/design-with-text/special-characters-glyphs/snap-to-glyph-options.html)): the Character panel menu's Show Snap to Glyph Options (Hide Snap to Glyph Options) shows a Snap to Glyph section in the panel, with or without type selected, with a checkbox for each kind of guide: Baseline, x-height, Glyph Bounds, Proximity Guides (the edges of each character's width), Angular Guides and Anchor Point. Each off takes its guides away and leaves the others (`view.snapToGlyph.options`, the `glyphSnap` preference group, all on by default). Angular Guides covers a glyph's slanted strokes and every guide of rotated type, which runs at its angle; the boxes are dimmed while View › Snap to Glyph is off, and the section starts with a Snap to Glyph checkbox for it (VectorCraft choices; the page settles neither). Showing the section scrolls the panel to it, since it comes after every character attribute (#5273). Tested in `crates/tools/src/guides/tests.rs`, `crates/ui-egui/src/panels/character/tests.rs` and `crates/engine/src/tests/prefs.rs`. - **Artboard click-to-fit (#1227):** a plain click fits the topmost editable object or group to a new artboard, including its stroke like Fit to Selected Art, and makes the new artboard active. Art and its selection stay unchanged; creation is one undo step. Handles, modified clicks, drags, Escape and tool changes retain their meaning. Tested inside an artboard and on the pasteboard (`crates/engine/tests/it/artboard_click.rs`); the public [CS6 Printing Guide](https://helpx.adobe.com/content/dam/help/en/indesign/pdf/CS6_PrintGuide.pdf) documents the object-click gesture. This legacy gesture adds evidence without regrading the 2026 canvas controls. - **Rotated views:** with the view rotated, Fit Artboard in Window, Fit All in Window and the status bar's artboard navigator fit the artboard or the art as the view turns it, and a Zoom tool marquee (Animated Zoom or GPU Performance off) zooms to the area dragged across. Ruler guides on no artboard turn with the view. The canvas draws the selection marquee where the tools select, Show Hidden Characters draws the marks of type partly inside the canvas, the Contextual Task Bar stays under the selection, and the Navigator's red box outlines what the window shows. @@ -1470,6 +1474,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - **CSS swatch libraries:** fractional linear and radial gradient stop positions are preserved, so nearby stops such as 12.5% and 12.890625% remain distinct instead of collapsing to 13%. Reference: [CSS Images 3 color stops](https://www.w3.org/TR/css-images-3/#color-stop-syntax). The original synthetic regression is `palette_io::tests::css_preserves_fractional_gradient_stop_positions` in `crates/color/src/palette_io.rs`. Scores and hours are unchanged. - **Swatches:** names follow the colour model and are unique; Swatch Options (process/spot, Global, Gray/RGB/HSB/CMYK/Web, live preview); editing a global or spot swatch recolours every linked fill, stroke and text run in one undo step; multi-select and delete with confirmation; New Swatch and New Color Group dialogs (a group from the selected artwork's colours); swatches in colour groups convert, separate and count like any other. The Swatches panel selects ranges and whole groups, has a find field, and drags swatches to reorder, regroup or paint art; Add Used Colors, Select All Unused, Merge, Ungroup and Sort by Kind; a CMYK document keeps applied colours in CMYK. Swatch libraries: nine generated colour libraries, seven gradient libraries (among them Organic Fades, soft perceptually mixed multi-stop fades that thin out to transparent, and Holographic, seven opaque linear foils of narrow pastel and pearl bands and seven radial glows that fade out to a clear edge) and three pattern libraries (Geometric Patterns; Grit Textures with eight seamless grain, speckle, stipple, scratch and fleck tiles; and Optical Effects with eight of VectorCraft's own seamless wave, ring, warped-check, stripe, chevron and lens tiles; their swatches bring their patterns) in a library panel, saved as `.vcswatches`, `.gpl`, swatch exchange (`.ase`) or CSS, and loaded from `.vcswatches`, `.gpl` and `.ase` files (`.ase` both ways: RGB, CMYK, Lab and Gray; global, spot and process; groups) and from color books (`.acb`, read only: the RGB, CMYK or Lab colors of a book such as a Pantone book a user owns, named with its prefix and suffix, spot unless it says process, #831); `swatch.library.copyToUser` copies a loaded library into the User Defined folder without replacing a file, and a file with the same extension and bytes as a User Defined library opens as that library. Tints of global and spot colours ("Name 40%") stay linked and separate as a percentage of their plate. Spot colours can be defined in Lab (Spot Colors options). A built-in [Registration] swatch prints on every plate. Editing, renaming, deleting or merging a global swatch also changes the colors linked to it in graph designs, the art of brushes and the tile that pattern editing's Cancel puts back, in the same undo step as the rest of the art; Default Swatches with replace unlinks them there too. + A swatch step in `command.batch` (Delete, Swatch Options, Merge, Edit Color Group) changes the fill and stroke for new art as the command run on its own does, so art drawn later in the batch or after it takes the same paint; a batch that fails, and a canceled batch preview, put back the paints it started with, and a canceled Swatch Options preview leaves them as they were. These swatch commands also change the fills and strokes of the appearance new art takes, and Undo and Redo of the command or the batch put the paints for new art back with the swatches. Evidence: `swatch_steps_in_a_batch_change_the_new_art_paints_as_commands_do`, `undo_and_redo_of_a_swatch_edit_put_back_the_new_art_paints`, `swatch_edits_reach_the_paints_of_the_new_art_template`, `a_failed_batch_puts_back_the_new_art_paints_a_swatch_step_changed` and `canceling_a_swatch_options_preview_keeps_the_new_art_paints` in `crates/engine/src/tests/swatches.rs`. Add Used Colors (`swatch.addUsedColors`) and Select All Unused (`swatch.unused`) look colors, swatch names, links, tints and gradients up in hash sets instead of searching every swatch and color for each color or linked paint (New Color Group from artwork too), and New Swatch with several colors (`swatch.new`), New Color Group (`swatch.newGroup`) and Edit Color Group (`swatch.editGroup`) name their new swatches from one set of the names already taken. The new swatches keep their names, order and links, and Select All Unused lists the same swatches. Evidence: `add_used_colors_adds_each_new_color_once_with_free_names`, `add_used_colors_global_links_every_paint_of_a_new_color`, `unused_matches_links_tints_colors_gradients_and_patterns_exactly`, `new_swatches_from_colors_are_numbered_after_names_already_taken`, `new_color_group_numbers_its_colors_after_the_group_and_its_moved_swatches`, `new_color_group_from_artwork_lists_each_color_once_with_free_names` and `edit_color_group_numbers_extra_colors_after_the_names_it_keeps` in `crates/engine/src/tests/swatchcmds.rs`; `free_swatch_names_match_naming_each_swatch_as_it_is_added` and `free_swatch_names_match_new_swatch_names_as_swatches_are_added` in `crates/doc/src/swatches.rs`. - **Colorized images (#1466):** a fill color applied to a selected grayscale or 1-bit image (`paint.setFill`) colorizes it with black, white, a process color or a spot color, and refuses a process color when the image has an alpha channel ([Convert color modes](https://web.archive.org/web/20251220223850/https://helpx.adobe.com/illustrator/desktop/manage-colors/select-and-adjust-colors/convert-color-modes.html), "Colorize Grayscale or 1-bit images"); black and white are accepted there too. The canvas draws each pixel in the color as far as the pixel is dark, with white pixels transparent; PDF export writes the image in the color (a spot color as its ink, Registration in every ink) with the image as its soft mask; Separations Preview and printed separations show it on its color's plates; native files keep the color. SVG writes the fill color through a coverage mask (or a colorized PNG in Tiny 1.2); EPS writes binary coverage as an image mask in the color's ink, and a grayscale image as ink samples scaled by coverage, with white pixels left out at Level 3 and gray midtones written over white. The prompt for deleting several swatches and groups uses the interface language's plural form for the count. Evidence: `deleting_several_swatches_uses_each_count_form` in `crates/ui-egui/src/panels/swatches/tests.rs`. diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c827a1ef74..2c279e36aa 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -204,18 +204,25 @@ fn cmd_layers() -> Result<(), String> { } /// Workspace packages that must build for wasm32: all L0–L5 crates, the egui -/// shell, and the web app (its wasm-only code is compiled by nothing else). -fn wasm_set() -> Result, String> { - let crates = layers::from_metadata(&metadata()?)?; - Ok(crates +/// shell, and the web app (its wasm-only code is compiled by nothing else). Each comes with its +/// package id, which `-p` takes where the name would be ambiguous: craft-libs builds against this +/// repo's geom and pathops by git, so the graph can hold a second, older copy of a workspace crate. +fn wasm_set() -> Result, String> { + let meta = metadata()?; + let ids: std::collections::HashMap<&str, &str> = + meta["packages"].as_array().into_iter().flatten().filter_map(|p| Some((p["name"].as_str()?, p["id"].as_str()?))).collect(); + layers::from_metadata(&meta)? .into_iter() .filter(|c| match layers::classify(&c.name) { Some(layers::Class::Layer(l)) => l <= 5 || layers::short_name(&c.name) == "ui-egui", Some(layers::Class::Standalone) => true, _ => layers::short_name(&c.name) == "web", }) - .map(|c| c.name) - .collect()) + .map(|c| { + let id = ids.get(c.name.as_str()).ok_or_else(|| format!("cargo metadata: no package id for {}", c.name))?.to_string(); + Ok((c.name, id)) + }) + .collect() } /// One `cargo check` over the whole wasm set: the crates share one build, and `--keep-going` @@ -224,10 +231,11 @@ fn cmd_wasm() -> Result<(), String> { let set = wasm_set()?; let mut c = cargo(); c.args(["check", "--target", "wasm32-unknown-unknown", "--keep-going"]); - for pkg in &set { - c.args(["-p", pkg]); + for (_, id) in &set { + c.args(["-p", id]); } - run(c, &format!("cargo check --target wasm32-unknown-unknown --keep-going ({} crates: {})", set.len(), set.join(", "))) + let names: Vec<&str> = set.iter().map(|(name, _)| name.as_str()).collect(); + run(c, &format!("cargo check --target wasm32-unknown-unknown --keep-going ({} crates: {})", set.len(), names.join(", "))) } /// Whether `cargo nextest` is installed.