feat(text): Middle Eastern & South Asian and Standard composers per paragraph (#4935)

Four paragraph composers: the existing Single-line and Every-line (Middle Eastern & South Asian,
complex scripts shaped, the default) and Standard Single-line and Every-line, which break lines the
same way and set Indic, Arabic and Hebrew type glyph by glyph as the font maps it.

Paragraph panel menu, Paragraph Style Options, text.setFormat, native file and paragraph styles.
.ai, EPS and PDF files carry no composer.
This commit is contained in:
Taha-Mahmoodi
2026-11-14 13:15:38 +04:30
parent 2e9c9ab200
commit 9798beef98
48 changed files with 541 additions and 109 deletions
+34 -4
View File
@@ -17,22 +17,52 @@ pub enum Justify {
JustifyAll,
}
/// Paragraph composer (Paragraph panel menu): how lines are broken.
/// Paragraph composer (Paragraph panel menu): how lines are broken, and whether complex scripts
/// (Indic, Arabic, Hebrew) are shaped. `SingleLine` and `EveryLine` are the Middle Eastern & South
/// Asian composers: they shape complex scripts with the font's layout tables, as all type is set
/// here, and are what documents saved before the four composers existed use. The `Standard`
/// composers break lines the same way but set a complex script glyph by glyph as the font maps its
/// characters, with no conjuncts, marks placed or joining forms: what fonts that keep a script's
/// glyphs on Latin character codes (legacy ANSI Indic fonts) need.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Composer {
/// Break each line as soon as it is full.
/// Middle Eastern & South Asian Single-line Composer: break each line as soon as it is full.
SingleLine,
/// Total fit over the whole paragraph (Illustrator's default): justified lines get even word
/// spacing, ragged lines an even rag.
/// Middle Eastern & South Asian Every-line Composer: total fit over the whole paragraph
/// (Illustrator's default): justified lines get even word spacing, ragged lines an even rag.
#[default]
EveryLine,
/// Standard Single-line Composer: [`Composer::SingleLine`]'s breaks, complex scripts not shaped.
StandardSingleLine,
/// Standard Every-line Composer: [`Composer::EveryLine`]'s breaks, complex scripts not shaped.
StandardEveryLine,
}
impl Composer {
fn is_default(&self) -> bool {
*self == Self::default()
}
/// Does this composer break lines one at a time (as opposed to a total fit)?
pub fn is_single_line(self) -> bool {
matches!(self, Self::SingleLine | Self::StandardSingleLine)
}
/// Does this composer shape complex scripts ([`Composer::SingleLine`], [`Composer::EveryLine`])?
pub fn shapes_complex_scripts(self) -> bool {
matches!(self, Self::SingleLine | Self::EveryLine)
}
/// The same shaping with the other line breaking (`single_line`: one line at a time).
pub fn with_breaking(self, single_line: bool) -> Self {
match (single_line, self.shapes_complex_scripts()) {
(true, true) => Self::SingleLine,
(true, false) => Self::StandardSingleLine,
(false, true) => Self::EveryLine,
(false, false) => Self::StandardEveryLine,
}
}
}
/// A paragraph's hyphenation options (Paragraph panel menu › Hyphenation…): which words automatic
File diff suppressed because one or more lines are too long
+24
View File
@@ -1649,6 +1649,30 @@ fn paragraph_style_options_edit_applies_to_users_and_is_one_saved_undo_step() {
}
}
/// A paragraph style can hold a Standard composer: it applies to its paragraphs, redefining and
/// resetting treat it like any attribute, and the style and the paragraphs keep it through a save.
#[test]
fn paragraph_styles_keep_a_standard_composer_through_a_save() {
use vectorcraft_doc::Composer;
let (mut s, id) = session_with_text("One\nTwo");
s.execute("paraStyle.new", &json!({"name": "Legacy", "attrs": {"composer": "standardSingleLine"}})).unwrap();
s.execute("paraStyle.apply", &json!({"name": "Legacy", "id": id, "start": 0, "end": 0})).unwrap();
assert_eq!(paras(&s, id).iter().map(|p| p.composer).collect::<Vec<_>>(), [Composer::StandardSingleLine, Composer::EveryLine]);
let doc = s.doc().unwrap().doc.clone();
let saved = vectorcraft_format::load(&vectorcraft_format::save(&doc, false)).unwrap();
let style = saved.para_styles.iter().find(|d| d.name == "Legacy").unwrap();
assert_eq!(style.attrs["composer"], json!("standardSingleLine"));
let mut composers = vec![];
saved.walk(|n| {
if let vectorcraft_doc::NodeKind::Text(t) = &n.kind {
composers.extend(t.paragraph_styles().iter().map(|p| p.composer));
}
});
assert_eq!(composers, [Composer::StandardSingleLine, Composer::EveryLine]);
s.execute("paraStyle.setAttrs", &json!({"name": "Legacy", "attrs": {"composer": "standardEveryLine"}})).unwrap();
assert_eq!(paras(&s, id)[0].composer, Composer::StandardEveryLine, "an edited style reaches its paragraphs");
}
/// A changed paragraph attribute outside the range `text.setFormat` keeps it to is an error for
/// `paraStyle.edit`, `paraStyle.setAttrs` and `paraStyle.new`, with no change to the document; the
/// ends of each range are accepted, and an out-of-range value the style already has can be kept.
+29
View File
@@ -1624,6 +1624,35 @@ fn text_set_format() {
assert_eq!(t.para.composer, vectorcraft_doc::Composer::EveryLine);
}
/// `text.setFormat {composer}` takes the two Middle Eastern & South Asian and the two Standard
/// composers, each per paragraph and one undo step; any other value is refused and names them all.
#[test]
fn text_set_format_takes_the_four_composers() {
use vectorcraft_doc::Composer;
let mut s = session();
let r = s.execute("text.create", &json!({"x": 10, "y": 100, "text": "One\nTwo"})).unwrap();
let id = NodeId(r["id"].as_u64().unwrap());
let composers = |s: &Session| {
let NodeKind::Text(t) = node(s, id).kind else { panic!() };
[t.para_at(0).composer, t.para_at(1).composer]
};
assert_eq!(composers(&s), [Composer::EveryLine; 2], "new type is ME&SA Every-line");
for (value, want) in [
("singleLine", Composer::SingleLine),
("standardSingleLine", Composer::StandardSingleLine),
("standardEveryLine", Composer::StandardEveryLine),
("everyLine", Composer::EveryLine),
] {
s.execute("text.setFormat", &json!({"ids": [id.0], "composer": value, "start": 4, "end": 4})).unwrap();
assert_eq!(composers(&s), [Composer::EveryLine, want], "{value}: only the second paragraph");
}
s.execute("text.setFormat", &json!({"ids": [id.0], "composer": "standardEveryLine"})).unwrap();
s.execute("edit.undo", &json!({})).unwrap();
assert_eq!(composers(&s), [Composer::EveryLine; 2], "one undo step");
let e = s.execute("text.setFormat", &json!({"ids": [id.0], "composer": "standard"})).unwrap_err().to_string();
assert!(e.contains("standardSingleLine") && e.contains("standardEveryLine"), "{e}");
}
#[test]
fn stroke_advanced_scale_swap_flip() {
let mut s = session();
+38
View File
@@ -212,6 +212,44 @@ fn text_composer_round_trips() {
assert!(!String::from_utf8_lossy(&save(&d2, false)).contains("composer"));
}
/// Every composer reads back as it was saved (the two Standard ones as their own values), and the
/// ME&SA names are the ones files have always used: `everyLine` stays the unwritten default and
/// `singleLine` keeps its spelling, so a document that never picks a Standard composer is unchanged.
#[test]
fn all_four_composers_round_trip() {
use vectorcraft_doc::{TextKind, TextObject};
let one = |c: Composer| {
let mut d = Document::new(200.0, 200.0);
let mut t = TextObject::point(kurbo::Point::ZERO, "ક\u{ACD}ક", Default::default());
t.para.composer = c;
t.kind = TextKind::Point;
let id = d.alloc_id();
d.insert(None, usize::MAX, Node::new(id, NodeKind::Text(Box::new(t)))).unwrap();
d
};
for (c, written) in [
(Composer::SingleLine, Some("singleLine")),
(Composer::EveryLine, None),
(Composer::StandardSingleLine, Some("standardSingleLine")),
(Composer::StandardEveryLine, Some("standardEveryLine")),
] {
let bytes = save(&one(c), false);
let text = String::from_utf8_lossy(&bytes);
match written {
Some(w) => assert!(text.contains(&format!("\"composer\":\"{w}\"")), "{c:?}"),
None => assert!(!text.contains("\"composer\""), "{c:?}"),
}
let back = load(&bytes).unwrap();
let mut got = None;
back.walk(|n| {
if let NodeKind::Text(t) = &n.kind {
got = Some(t.para.composer);
}
});
assert_eq!(got, Some(c));
}
}
/// A document as the first version wrote it (format name `drawcraft`, anchors as maps).
const V1_FILE: &str = r#"{"format":"drawcraft","version":1,"generator":"DrawCraft 0.1.0","document":{"version":1,"title":"Old","artboards":[{"id":1,"name":"Artboard 1","rect":{"x0":0.0,"y0":0.0,"x1":100.0,"y1":80.0}}],
"layers":[{"id":1,"name":"Layer 1","visible":true,"locked":false,"opacity":1.0,"kind":{"type":"layer","children":[
+1 -1
View File
@@ -392,7 +392,7 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
"type.lineComposer",
"Toggle Line Composer",
"Cmd+Alt+Shift+C",
"{} the selected type's paragraphs (or those the Type tool's selection touches) use the Single-line Composer when they all use the Every-line Composer, else the Every-line Composer (text.setFormat {composer}) → \"singleLine\" | \"everyLine\"",
"{} the selected type's paragraphs (or those the Type tool's selection touches) use the Single-line Composer when they all use the Every-line Composer, else the Every-line Composer, each keeping its shaping: Middle Eastern & South Asian or Standard (text.setFormat {composer}) → \"singleLine\" | \"everyLine\" | \"standardSingleLine\" | \"standardEveryLine\"",
),
(
"type.hyphenate",
+5
View File
@@ -52,6 +52,10 @@ pub struct OtFeatures {
pub extra_values: [u16; EXTRA_FEATURES.len()],
/// The value `swsh=N` gives swashes ([`Self::swash`]), as [`Self::extra_values`] for `salt`.
pub swash_value: u16,
/// Set a complex script (Indic, Arabic, Hebrew) glyph by glyph as the font maps its
/// characters, with none of its layout tables: the Standard composers. Set per paragraph by
/// layout from the paragraph's composer, not by a style.
pub unshaped_complex: bool,
}
/// The largest value a `tag=N` feature takes: a font's glyph ids are 16 bits, so is an alternate's
@@ -87,6 +91,7 @@ impl Default for OtFeatures {
extra: 0,
extra_values: [0; EXTRA_FEATURES.len()],
swash_value: 0,
unshaped_complex: false,
}
}
}
+6 -3
View File
@@ -229,11 +229,14 @@ impl Ctx<'_> {
out
}
/// Shape paragraph `r` (its bidi resolution `bidi`).
fn shape_para(&self, r: Range<usize>, bidi: Option<&BidiInfo<'_>>) -> Vec<SGlyph> {
/// Shape paragraph `r` (its bidi resolution `bidi`, its attributes `para`). A Standard composer
/// sets a complex script glyph by glyph ([`OtFeatures::unshaped_complex`]).
fn shape_para(&self, r: Range<usize>, bidi: Option<&BidiInfo<'_>>, para: &ParaStyle) -> Vec<SGlyph> {
let mut v = Vec::with_capacity(r.len());
let levels = bidi.map_or(&[][..], |b| &b.levels);
shape_runs(self.db, self.text, r, &self.runs, &self.inlines, &self.faces, &self.opts.features, levels, &mut v);
let standard = !self.opts.composer.unwrap_or(para.composer).shapes_complex_scripts();
let feats = OtFeatures { unshaped_complex: standard, ..self.opts.features };
shape_runs(self.db, self.text, r, &self.runs, &self.inlines, &self.faces, &feats, levels, &mut v);
self.finish_shaping(&mut v, |g| self.style_at(g.byte));
v
}
+3 -3
View File
@@ -58,7 +58,7 @@ fn compose_para(
// The tab of a list marker is on the first line, with the marker, and has a fixed width.
let has_tab = sg.iter().any(|g| g.ch == '\t' && g.len > 0);
let has_soft_break = sg.iter().any(|g| g.ch == '\u{2028}');
if composer != Composer::EveryLine
if composer.is_single_line()
|| pen.regions.is_none()
|| sg.len() < 2
|| sg.len() > MAX_COMPOSE_GLYPHS
@@ -242,7 +242,7 @@ fn prepare_paragraph<'a, 'text>(
let text = cx.text;
let bidi = para_bidi_with(text.get(pr.clone()).unwrap_or_default(), para.direction, &cx.char_directions(&pr));
let rtl = is_rtl(bidi.as_ref());
let mut sg = cx.shape_para(pr.clone(), bidi.as_ref());
let mut sg = cx.shape_para(pr.clone(), bidi.as_ref(), para);
// Thai, Lao, Khmer and Myanmar break lines between words, not at spaces.
mark_word_ends(text.get(pr.clone()).unwrap_or_default(), pr.start, &mut sg);
// Korean breaks between words, unless Korean Line Break Anywhere lets it break between syllables.
@@ -316,7 +316,7 @@ fn prepare_paragraph<'a, 'text>(
let composed = compose_para(cx, &sg, &flex, &line_end, para, pen, rtl, continued);
// Hyphenation options: the Hyphenation Zone applies with the Single-line Composer, and the
// Hyphen Limit counts the lines in a row that end with a hyphen.
let zone = if cx.opts.composer.unwrap_or(para.composer) == Composer::SingleLine { para.hyphenation.zone } else { 0.0 };
let zone = if cx.opts.composer.unwrap_or(para.composer).is_single_line() { para.hyphenation.zone } else { 0.0 };
let hyphen_limit = usize::try_from(para.hyphenation.hyphen_limit).unwrap_or(usize::MAX);
let mirror = mirrors_indents(para, rtl, cx.vertical);
ParagraphData {
+1 -1
View File
@@ -393,7 +393,7 @@ pub(super) fn on_path(cx: &mut Ctx<'_>, paras: &[Range<usize>], t: &TextObject,
let text = cx.text;
let bidi = para_bidi_with(text.get(pr.clone()).unwrap_or_default(), para.direction, &cx.char_directions(pr));
rtl.get_or_insert(is_rtl(bidi.as_ref()) && !cx.vertical);
let mut glyphs = cx.shape_para(pr.clone(), bidi.as_ref());
let mut glyphs = cx.shape_para(pr.clone(), bidi.as_ref(), t.para_at(pi));
// Bullets and numbers: a list paragraph's text starts after its marker here too, unless
// the paragraph continues from the frame before in its thread.
if pi > 0 || !t.first_para_continues {
+33 -3
View File
@@ -122,6 +122,26 @@ pub(crate) fn joins(script: Script) -> bool {
)
}
/// Is `script` one a Standard composer leaves unshaped: Indic (conjuncts, half forms, marks placed
/// by the font's layout tables), Arabic-like ([`joins`]) and Hebrew?
fn is_complex_script(script: Script) -> bool {
joins(script)
|| matches!(
script,
Script::Hebrew
| Script::Devanagari
| Script::Bengali
| Script::Gurmukhi
| Script::Gujarati
| Script::Oriya
| Script::Tamil
| Script::Telugu
| Script::Kannada
| Script::Malayalam
| Script::Sinhala
)
}
/// How `vpal` and the vertical kerning with it move an upright glyph in vertical type and change
/// its length down the column, in points: `advance` down the column, `dx` and `dy` in glyph space
/// (y down; `dy` is down the column once the glyph stands upright). `proportional`: `vpal` itself
@@ -1374,7 +1394,12 @@ fn shape_segment(text: &str, context: &Range<usize>, seg: &Segment, feats: &OtFe
let source_runs = &(source_runs.start + first..source_runs.start + last);
let text_seg = &text[range.clone()];
// The segment's script: that of its first character of a script of its own.
let cursive = text_seg.chars().map(|c| c.script()).find(|s| !matches!(s, Script::Common | Script::Inherited)).is_some_and(joins);
let first_script = text_seg.chars().map(|c| c.script()).find(|s| !matches!(s, Script::Common | Script::Inherited));
let cursive = first_script.is_some_and(joins);
// A Standard composer sets a complex script glyph by glyph (no layout tables, nominal glyphs).
// shortcut: decided for the whole segment by its first strong script, as `cursive` is; segments
// already split where the script changes.
let unshaped = feats.unshaped_complex && first_script.is_some_and(is_complex_script);
let full = st.size.max(0.0);
// Superscript/subscript and small capitals shrink the glyphs; line metrics keep the full size.
let (_, pos_shift) = st.position.scale_shift(full);
@@ -1453,7 +1478,7 @@ fn shape_segment(text: &str, context: &Range<usize>, seg: &Segment, feats: &OtFe
.and_then(|l| l.parse::<harfrust::Language>().ok());
let mut shaped = Shaped::default();
let Shaped { raw, proportional, vpal, chars } = &mut shaped;
let hb_shaped = face.hb().map(|hb| {
let hb_shaped = face.hb().filter(|_| !unshaped).map(|hb| {
let shaper = face.shaper.shaper(&hb).instance(face.instance.as_ref()).build();
// The baseline and character-level pass use exactly the same resolved features.
// Alternate positioning passes still resolve their own features, with `more` last.
@@ -1558,7 +1583,8 @@ fn shape_segment(text: &str, context: &Range<usize>, seg: &Segment, feats: &OtFe
}
});
if hb_shaped.is_none() {
// Fallback: nominal glyphs and hmtx advances, no shaping.
// Fallback: nominal glyphs and hmtx advances, no shaping (also a complex script under a
// Standard composer).
if let Some(f) = face.skrifa() {
let cmap = f.charmap();
let gm = f.glyph_metrics(Size::unscaled(), face.location());
@@ -1572,6 +1598,10 @@ fn shape_segment(text: &str, context: &Range<usize>, seg: &Segment, feats: &OtFe
raw.push((g.to_u32(), cl, adv.round() as i32, 0, 0));
}
}
// Shaped right-to-left text comes out in visual order, which layout expects.
if unshaped && level.is_rtl() {
raw.reverse();
}
}
}
shaped
+5 -3
View File
@@ -534,7 +534,8 @@ pub fn half_form_font(half: bool) -> Option<Vec<u8>> {
pub const CONJUNCT_FAMILY: &str = "Conjuncttest Sans";
/// A test-only cmap over bundled Source Sans 3: Devanagari Ka uses K, the halant uses a period and
/// the vowel sign I (drawn before its syllable) uses i. The `GSUB` table's `dev2` script has an
/// the vowel sign I (drawn before its syllable) uses i; Gujarati Ka, virama and vowel sign I use the
/// same glyphs. The `GSUB` table's `dev2` and `gjr2` scripts have an
/// `aalt` single substitution of K by k and a `salt` one of K by i, which list k and the vowel
/// sign's glyph as alternates of Ka, and a `half` ligature of K and the period into k (Ka's half
/// form). Family [`CONJUNCT_FAMILY`]. `None` when it can't be built.
@@ -549,7 +550,7 @@ pub fn conjunct_font() -> Option<Vec<u8>> {
const BASE: &[u8] = include_bytes!("../../../assets/fonts/SourceSans3-Regular.ttf");
let font = skrifa::FontRef::new(BASE).ok()?;
let charmap = font.charmap();
let mapping = [('क', 'K'), ('\u{094D}', '.'), ('\u{093F}', 'i')];
let mapping = [('क', 'K'), ('\u{094D}', '.'), ('\u{093F}', 'i'), ('ક', 'K'), ('\u{0ACD}', '.'), ('\u{0ABF}', 'i')];
let mappings = mapping.into_iter().map(|(c, source)| Some((c, write_fonts::types::GlyphId::new(charmap.map(source)?.to_u32()))));
let cmap = Cmap::from_mappings(mappings.collect::<Option<Vec<_>>>()?).ok()?;
let family = CONJUNCT_FAMILY;
@@ -574,7 +575,8 @@ pub fn conjunct_font() -> Option<Vec<u8>> {
SubstitutionLookup::Ligature(Lookup::new(Default::default(), vec![half])),
SubstitutionLookup::Single(Lookup::new(Default::default(), vec![salt.into()])),
]);
let scripts = ScriptList::new(vec![ScriptRecord::new(Tag::new(b"dev2"), Script::new(Some(LangSys::new(vec![0, 1, 2])), vec![]))]);
let langsys = || Script::new(Some(LangSys::new(vec![0, 1, 2])), vec![]);
let scripts = ScriptList::new(vec![ScriptRecord::new(Tag::new(b"dev2"), langsys()), ScriptRecord::new(Tag::new(b"gjr2"), langsys())]);
builder.add_table(&Gsub::new(scripts, features, lookups)).ok()?;
for r in font.table_directory.table_records() {
let tag = Tag::new(&r.tag().to_be_bytes());
+1
View File
@@ -10,6 +10,7 @@ mod bidi;
mod bitmaps;
mod colr;
mod combos;
mod composers;
mod composite;
mod devanagari;
mod embed;
+96
View File
@@ -0,0 +1,96 @@
//! The four composers: the Middle Eastern & South Asian ones shape complex scripts with the font's
//! layout tables, the Standard ones set them glyph by glyph as the font maps their characters.
//! Uses a font built in code ([`conjunct_font`]): Ka K, halant a period and vowel sign I i, in
//! Devanagari and Gujarati, with a `half` ligature of K and the period into k.
use crate::test_fonts::{CONJUNCT_FAMILY, conjunct_font, source_sans_gid};
use crate::*;
use kurbo::Point;
use vectorcraft_doc::{CharStyle, Composer, TextObject};
/// Ka, halant, Ka, vowel sign I in Devanagari, then in Gujarati.
const DEVANAGARI: &str = "क\u{94D}क\u{93F}";
const GUJARATI: &str = "ક\u{ACD}ક\u{ABF}";
fn db() -> FontDb {
let db = FontDb::with_font_dirs(vec![]);
db.add_font(conjunct_font().expect("the test font builds"));
db
}
fn object(text: &str, composer: Composer) -> TextObject {
let st = CharStyle { font_family: CONJUNCT_FAMILY.into(), font_style: "Regular".into(), size: 20.0, ..CharStyle::default() };
let mut t = TextObject::point(Point::ZERO, text, st);
t.para.composer = composer;
t
}
/// The glyph ids drawn for `text` with `composer`, and each glyph's source cluster length.
fn drawn(db: &FontDb, text: &str, composer: Composer) -> Vec<(u32, usize)> {
layout(db, &object(text, composer)).glyphs.iter().map(|g| (g.gid, g.len)).collect()
}
fn g(c: char) -> u32 {
u32::from(source_sans_gid(c).expect("a Source Sans glyph"))
}
/// Under the ME&SA composers the conjunct forms (Devanagari: the vowel sign I drawn before its
/// syllable and Ka's half form; Gujarati: the half form); under the Standard ones each character
/// has its own glyph, in text order, as the font maps it.
#[test]
fn standard_composers_set_indic_text_glyph_by_glyph() {
let db = db();
let ids = |v: Vec<(u32, usize)>| v.into_iter().map(|(gid, _)| gid).collect::<Vec<_>>();
for composer in [Composer::SingleLine, Composer::EveryLine] {
assert_eq!(ids(drawn(&db, DEVANAGARI, composer)), [g('i'), g('k'), g('K')], "{composer:?} Devanagari");
assert_eq!(ids(drawn(&db, GUJARATI, composer)), [g('k'), g('K'), g('i')], "{composer:?} Gujarati");
}
for composer in [Composer::StandardSingleLine, Composer::StandardEveryLine] {
let plain = [g('K'), g('.'), g('K'), g('i')];
let devanagari = drawn(&db, DEVANAGARI, composer);
assert_eq!(ids(devanagari.clone()), plain, "{composer:?} Devanagari");
assert_eq!(ids(drawn(&db, GUJARATI, composer)), plain, "{composer:?} Gujarati");
assert!(devanagari.iter().all(|&(_, len)| len == 3), "each glyph is one character's own cluster: {devanagari:?}");
}
}
/// The composer is per paragraph: of two paragraphs of the same text, each is shaped by its own.
#[test]
fn each_paragraph_follows_its_own_composer() {
let db = db();
let mut t = object(&format!("{DEVANAGARI}\n{DEVANAGARI}"), Composer::EveryLine);
let standard = vectorcraft_doc::ParaStyle { composer: Composer::StandardEveryLine, ..t.para.clone() };
t.set_paragraph_styles(vec![t.para.clone(), standard]);
let l = layout(&db, &t);
let second = DEVANAGARI.len() + 1;
let of = |from: usize, to: usize| l.glyphs.iter().filter(|g| (from..to).contains(&g.byte) && g.len > 0).map(|g| g.gid).collect::<Vec<_>>();
assert_eq!(of(0, second), [g('i'), g('k'), g('K')], "ME&SA paragraph");
assert_eq!(of(second, second + DEVANAGARI.len()), [g('K'), g('.'), g('K'), g('i')], "Standard paragraph");
}
/// Layout's composer override ([`LayoutOptions::composer`]) decides the shaping too.
#[test]
fn the_layout_composer_override_decides_the_shaping() {
let db = db();
let t = object(DEVANAGARI, Composer::EveryLine);
let with = |c| layout_with(&db, &t, &LayoutOptions { composer: Some(c), ..Default::default() }).glyphs.len();
assert_eq!((with(Composer::SingleLine), with(Composer::StandardSingleLine)), (3, 4));
}
/// Standard composers break lines as the ME&SA ones do (`is_single_line`), and old files' composers
/// keep their meaning.
#[test]
fn composers_split_into_breaking_and_shaping() {
use Composer::*;
for (c, single, shapes) in
[(SingleLine, true, true), (EveryLine, false, true), (StandardSingleLine, true, false), (StandardEveryLine, false, false)]
{
assert_eq!((c.is_single_line(), c.shapes_complex_scripts()), (single, shapes), "{c:?}");
assert_eq!(c.with_breaking(single), c, "{c:?}");
assert_eq!(
(c.with_breaking(!single).is_single_line(), c.with_breaking(!single).shapes_complex_scripts()),
(!single, shapes),
"{c:?} toggled"
);
}
assert_eq!(Composer::default(), EveryLine, "new type and old documents are ME&SA Every-line");
}
@@ -361,7 +361,12 @@ pub(crate) fn edited_attrs(d: &Dialog) -> Result<Map<String, Value>, String> {
}
let same = unchanged("composer", "__resetComposition");
keep_or(&mut attrs, "composer", same, choice("composer").filter(|v| matches!(v.as_str(), Some("singleLine" | "everyLine"))));
keep_or(
&mut attrs,
"composer",
same,
choice("composer").filter(|v| matches!(v.as_str(), Some("singleLine" | "everyLine" | "standardSingleLine" | "standardEveryLine"))),
);
let same = unchanged("roman_hanging", "__resetComposition");
keep_or(&mut attrs, "roman_hanging", same, switch("roman_hanging"));
@@ -637,7 +642,9 @@ fn choice(ui: &mut egui::Ui, d: &mut Dialog, key: &str, options: &[(&str, &str)]
let shown = options.iter().find(|(value, _)| *value == selected).map_or("", |(_, label)| *label);
let labels: Vec<&str> = std::iter::once(" ").chain(options.iter().map(|(_, label)| *label)).collect();
ui.add_enabled_ui(enabled, |ui| {
if let Some(i) = crate::widgets::dropdown(ui, (KIND, key), shown, &labels, 190.0) {
// shortcut: 7 pt per character approximates the widest label; measure the text when a label wraps.
let width = (labels.iter().map(|l| l.chars().count()).max().unwrap_or(0) as f32 * 7.0).max(190.0);
if let Some(i) = crate::widgets::dropdown(ui, (KIND, key), shown, &labels, width) {
d.fields.insert(key.into(), if i == 0 { Value::Null } else { options.get(i - 1).map_or(Value::Null, |(value, _)| json!(value)) });
}
});
@@ -842,11 +849,16 @@ pub(crate) fn clear_tabs(d: &mut Dialog) {
d.fields.remove("__tabEdited");
}
/// Composition: the Single-line or Every-line Composer, and Roman Hanging Punctuation.
/// Composition: the Middle Eastern & South Asian or Standard, Single-line or Every-line Composer, and Roman Hanging Punctuation.
pub(crate) fn composition_body(ui: &mut egui::Ui, d: &mut Dialog) {
egui::Grid::new("paragraph-style-composition").num_columns(2).spacing([18.0, 8.0]).show(ui, |ui| {
let row = ui.label(tl!("Composition"));
let composers = [("singleLine", tl!("Single-line Composer")), ("everyLine", tl!("Every-line Composer"))];
let composers = [
("singleLine", tl!("Middle Eastern & South Asian Single-line Composer")),
("everyLine", tl!("Middle Eastern & South Asian Every-line Composer")),
("standardSingleLine", tl!("Standard Single-line Composer")),
("standardEveryLine", tl!("Standard Every-line Composer")),
];
ui.label_inputs_by(row.id, |ui| choice(ui, d, "composer", &composers, true));
ui.end_row();
switch(ui, d, "roman_hanging", tl!("Roman Hanging Punctuation"), true);
@@ -857,7 +869,7 @@ pub(crate) fn composition_body(ui: &mut egui::Ui, d: &mut Dialog) {
/// unset; Hyphenation Zone is also inactive with the Every-line Composer, which does not use it.
pub(crate) fn hyphenation_body(ui: &mut egui::Ui, d: &mut Dialog) {
let on = d.fields.get("hyphenate").and_then(Value::as_bool) == Some(true);
let single_line = d.fields.get("composer").and_then(Value::as_str) == Some("singleLine");
let single_line = matches!(d.fields.get("composer").and_then(Value::as_str), Some("singleLine" | "standardSingleLine"));
egui::Grid::new("paragraph-style-hyphenation").num_columns(2).spacing([18.0, 8.0]).show(ui, |ui| {
switch(ui, d, "hyphenate", tl!("Hyphenation"), true);
for (key, suffix) in [
+5 -2
View File
@@ -1046,7 +1046,8 @@ font-technology Variable Променливи
Every (minutes) На всеки (минути)
Every option is at its default. Всички опции са в състояние по подразбиране.
Every option matches {base}. Всички опции съответстват на {base}.
Every-line Composer Композитор за всеки ред
Middle Eastern & South Asian Every-line Composer Композитор за всеки ред (Близък изток и Южна Азия)
Standard Every-line Composer Стандартен композитор за всеки ред
Exact dash lengths Точни дължини на тиретата
Exceptions (comma separated) Изключения (разделени със запетаи)
Exclude Изключване
@@ -3310,7 +3311,8 @@ digits Malayalam Малаялам
Single Left Quotation Mark Лява единична кавичка
Single Quotes: Единични кавички:
Single Right Quotation Mark Дясна единична кавичка
Single-line Composer Ред по ред композитор
Middle Eastern & South Asian Single-line Composer Ред по ред композитор (Близък изток и Южна Азия)
Standard Single-line Composer Стандартен ред по ред композитор
Toggle Line Composer Превключване на композитора на редове
Sixth Space Шесто разстояние
Size Размер
@@ -6884,3 +6886,4 @@ breakText Glyphs Глифи
Grommets Капси
Grommet Inset Отстъп на капсите от ръба
Diameter Диаметър
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer трябва да е "singleLine", "everyLine", "standardSingleLine" или "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -1998,7 +1998,8 @@ digits Malayalam Malajalam
Tabular Lining Tabelarne brojke
Tabular Oldstyle Tabelarne stare brojke
Titling Alternates Alternative za naslove
Every-line Composer Slagač svih redova
Middle Eastern & South Asian Every-line Composer Slagač svih redova (Bliski istok i Južna Azija)
Standard Every-line Composer Standardni slagač svih redova
First-line Left Indent Lijeva uvlaka prvog reda
Hyphenation… Rastavljanje riječi…
Words Longer Than: Riječi duže od:
@@ -2038,7 +2039,8 @@ digits Malayalam Malajalam
East Asian Composition Settings Postavke istočnoazijske kompozicije
Korean Composition Settings Postavke korejske kompozicije
Select a text object to edit its paragraph attributes. Odaberite tekstualni objekat da uredite njegove atribute pasusa.
Single-line Composer Slagač jednog reda
Middle Eastern & South Asian Single-line Composer Slagač jednog reda (Bliski istok i Južna Azija)
Standard Single-line Composer Standardni slagač jednog reda
Toggle Line Composer Uključi/isključi Line Composer
Space After Paragraph Razmak nakon pasusa
Space Before Paragraph Razmak prije pasusa
@@ -6937,3 +6939,4 @@ shape Open Otvoren
Grommets Ušice
Grommet Inset Udaljenost ušica od ruba
Diameter Prečnik
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer mora biti "singleLine", "everyLine", "standardSingleLine" ili "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -1525,7 +1525,8 @@ antiAlias Sharp Nítid
Every (minutes) Cada (minuts)
Every option is at its default. Totes les opcions són al valor predeterminat.
Every option matches {base}. Totes les opcions coincideixen amb {base}.
Every-line Composer Composició línia per línia
Middle Eastern & South Asian Every-line Composer Composició línia per línia (Orient Pròxim i Àsia Meridional)
Standard Every-line Composer Composició estàndard línia per línia
Exact Exacte
Exact dash lengths Longituds de guió exactes
Example: {name} Exemple: {name}
@@ -4326,7 +4327,8 @@ digits Malayalam Malaiàlam
Single Quotes: Cometes simples:
Single Right Quotation Mark Cometa simple dreta
Single Word Justification: Justificació d’una sola paraula:
Single-line Composer Compositor d’una línia
Middle Eastern & South Asian Single-line Composer Compositor d’una línia (Orient Pròxim i Àsia Meridional)
Standard Single-line Composer Compositor estàndard d’una línia
Sixth Space Espai de sisena part
Size Mida
Size Tile to Art Ajusta la mida del mosaic a l’art
@@ -7476,3 +7478,4 @@ breakText Glyphs Glifs
Grommets Ullets
Grommet Inset Distància dels ullets a la vora
Diameter Diàmetre
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer ha de ser "singleLine", "everyLine", "standardSingleLine" o "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -3
View File
@@ -2029,7 +2029,8 @@ digits Malayalam Malajálamské
Tabular Lining Tabulkové verzálkové
Tabular Oldstyle Tabulkové minuskové
Titling Alternates Titulkové alternativy
Every-line Composer Sazba všech řádků
Middle Eastern & South Asian Every-line Composer Sazba všech řádků (Blízký východ a Jižní Asie)
Standard Every-line Composer Standardní sazba všech řádků
First-line Left Indent Odsazení prvního řádku zleva
Hyphenation… Dělení slov…
Words Longer Than: Slova delší než:
@@ -2069,7 +2070,8 @@ digits Malayalam Malajálamské
East Asian Composition Settings Nastavení východoasijské sazby
Korean Composition Settings Nastavení korejské sazby
Select a text object to edit its paragraph attributes. Vyberte textový objekt, abyste mohli upravit atributy jeho odstavce.
Single-line Composer Sazba jednoho řádku
Middle Eastern & South Asian Single-line Composer Sazba jednoho řádku (Blízký východ a Jižní Asie)
Standard Single-line Composer Standardní sazba jednoho řádku
Toggle Line Composer Přepnout sazbu řádků
Space After Paragraph Mezera za odstavcem
Space Before Paragraph Mezera před odstavcem
@@ -8114,7 +8116,7 @@ breakText Glyphs Glyfy
@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 composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer musí být "singleLine", "everyLine", "standardSingleLine" nebo "standardEveryLine"
@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
Can't render this file because it is too large.
+5 -2
View File
@@ -1837,7 +1837,8 @@ digits Malayalam Malayalam
Tabular Lining Tabulære versalcifre
Tabular Oldstyle Tabulære mediævalcifre
Titling Alternates Titelalternativer
Every-line Composer Hverlinjesætter
Middle Eastern & South Asian Every-line Composer Hverlinjesætter (Mellemøsten og Sydasien)
Standard Every-line Composer Standard-hverlinjesætter
First-line Left Indent Venstre indrykning af første linje
Hyphenation… Orddeling…
Justification… Justering…
@@ -1869,7 +1870,8 @@ digits Malayalam Malayalam
East Asian Composition Settings Indstillinger for østasiatisk komposition
Korean Composition Settings Indstillinger for koreansk komposition
Select a text object to edit its paragraph attributes. Markér et tekstobjekt for at redigere dets afsnitsattributter.
Single-line Composer Enlinjesætter
Middle Eastern & South Asian Single-line Composer Enlinjesætter (Mellemøsten og Sydasien)
Standard Single-line Composer Standard-enlinjesætter
Toggle Line Composer Skift linjesætter
Space After Paragraph Mellemrum efter afsnit
Space Before Paragraph Mellemrum før afsnit
@@ -6899,3 +6901,4 @@ breakText Glyphs Glyffer
Grommets Maljer
Grommet Inset Maljernes afstand fra kanten
Diameter Diameter
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer skal være "singleLine", "everyLine", "standardSingleLine" eller "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -3
View File
@@ -1048,7 +1048,8 @@ font-technology Variable Variabel
Every (minutes) Alle (Minuten)
Every option is at its default. Alle Optionen haben ihren Standardwert.
Every option matches {base}. Alle Optionen entsprechen {base}.
Every-line Composer Alle-Zeilen-Setzer
Middle Eastern & South Asian Every-line Composer Alle-Zeilen-Setzer (Naher Osten und Südasien)
Standard Every-line Composer Standard-Alle-Zeilen-Setzer
Exact dash lengths Exakte Strichlängen
Exceptions (comma separated) Ausnahmen (durch Kommas getrennt)
Exclude Schnittmenge entfernen
@@ -3372,7 +3373,8 @@ digits Malayalam Malayalam
Single Left Quotation Mark Einfaches öffnendes Anführungszeichen
Single Quotes: Einfache Anführungszeichen:
Single Right Quotation Mark Einfaches schließendes Anführungszeichen
Single-line Composer Einzeilen-Setzer
Middle Eastern & South Asian Single-line Composer Einzeilen-Setzer (Naher Osten und Südasien)
Standard Single-line Composer Standard-Einzeilen-Setzer
Toggle Line Composer Zeilensetzer umschalten
Sixth Space Sechstelgeviert-Leerzeichen
Size Größe
@@ -7918,7 +7920,7 @@ breakText Glyphs Glyphen
@msg column: true floats the whole column and takes no onto, above or below column: true macht die ganze Spalte schwebend und nimmt kein onto, above oder below
@msg command must be a shape.* command command muss ein shape.*-Befehl sein
@msg commands[{i}]: missing `command` commands[{i}]: `command` fehlt
@msg composer must be "singleLine" or "everyLine" composer muss „singleLine“ oder „everyLine“ sein
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer muss „singleLine“, „everyLine“, „standardSingleLine“ oder „standardEveryLine“ sein
@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes zusammengesetzte Formen nehmen Pfade, zusammengesetzte Pfade, Gruppen, zusammengesetzte Formen, Text, Angleichungen und Verzerrungshüllen
@msg compound {_1} must contain exactly one open path to join zusammengesetzter Pfad {_1} muss genau einen offenen Pfad zum Zusammenfügen enthalten
@msg connect end must be "start" or "end" connect end muss „start“ oder „end“ sein
Can't render this file because it is too large.
+5 -2
View File
@@ -1013,7 +1013,8 @@ font-technology Variable Μεταβλητές
Every (minutes) Κάθε (λεπτά)
Every option is at its default. Όλες οι επιλογές έχουν τις προεπιλεγμένες τιμές τους.
Every option matches {base}. Όλες οι επιλογές ταιριάζουν με το {base}.
Every-line Composer Σύνθεση όλων των γραμμών
Middle Eastern & South Asian Every-line Composer Σύνθεση όλων των γραμμών (Μέση Ανατολή και Νότια Ασία)
Standard Every-line Composer Τυπική σύνθεση όλων των γραμμών
Exact dash lengths Ακριβή μήκη παυλών
Exceptions (comma separated) Εξαιρέσεις (χωρισμένες με κόμμα)
Exclude Εξαίρεση
@@ -3954,7 +3955,8 @@ digits Malayalam Μαλαγιάλαμ
Single Left Quotation Mark Μονό αριστερό εισαγωγικό
Single Quotes: Μονά εισαγωγικά:
Single Right Quotation Mark Μονό δεξί εισαγωγικό
Single-line Composer Σύνθεση μονής γραμμής
Middle Eastern & South Asian Single-line Composer Σύνθεση μονής γραμμής (Μέση Ανατολή και Νότια Ασία)
Standard Single-line Composer Τυπική σύνθεση μονής γραμμής
Toggle Line Composer Εναλλαγή σύνθεσης γραμμών
Sixth Space Διάστημα ενός έκτου
Size Tile to Art Προσαρμογή μεγέθους πλακιδίου στο σχέδιο
@@ -7448,3 +7450,4 @@ breakText Glyphs Γλύφοι
Grommets Τρουκς
Grommet Inset Απόσταση τρουκς από την άκρη
Diameter Διάμετρος
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" το composer πρέπει να είναι "singleLine", "everyLine", "standardSingleLine" ή "standardEveryLine"
Can't render this file because it is too large.
+5 -2
View File
@@ -1069,7 +1069,8 @@ font-technology Variable Variables
Every (minutes) Cada (minutos)
Every option is at its default. Todas las opciones tienen su valor predeterminado.
Every option matches {base}. Todas las opciones coinciden con {base}.
Every-line Composer Composición de todas las líneas
Middle Eastern & South Asian Every-line Composer Composición de todas las líneas (Oriente Medio y Sur de Asia)
Standard Every-line Composer Composición estándar de todas las líneas
Exact dash lengths Longitudes exactas de guion
Exceptions (comma separated) Excepciones (separadas por comas)
Exclude Excluir
@@ -3403,7 +3404,8 @@ digits Malayalam Malayálam
Single Left Quotation Mark Comilla simple de apertura
Single Quotes: Comillas simples:
Single Right Quotation Mark Comilla simple de cierre
Single-line Composer Composición de una línea
Middle Eastern & South Asian Single-line Composer Composición de una línea (Oriente Medio y Sur de Asia)
Standard Single-line Composer Composición estándar de una línea
Toggle Line Composer Alternar composición de líneas
Sixth Space Sexto de espacio
Size Tamaño
@@ -7439,3 +7441,4 @@ breakText Glyphs Glifos
Grommets Ojales
Grommet Inset Distancia de los ojales al borde
Diameter Diámetro
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer debe ser "singleLine", "everyLine", "standardSingleLine" o "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -1990,7 +1990,8 @@ digits Malayalam Malajalam
Tabular Lining Taulukkonumerot
Tabular Oldstyle Vanhanaikaiset taulukkonumerot
Titling Alternates Otsikkovaihtoehdot
Every-line Composer Kaikkien rivien asettelu
Middle Eastern & South Asian Every-line Composer Kaikkien rivien asettelu (Lähi-itä ja Etelä-Aasia)
Standard Every-line Composer Tavallinen kaikkien rivien asettelu
First-line Left Indent Ensimmäisen rivin vasen sisennys
Hyphenation… Tavutus…
Words Longer Than: Sanat, jotka ovat pidempiä kuin:
@@ -2030,7 +2031,8 @@ digits Malayalam Malajalam
East Asian Composition Settings Itäaasialaisen ladonnan asetukset
Korean Composition Settings Korean ladonnan asetukset
Select a text object to edit its paragraph attributes. Valitse tekstiobjekti, jonka kappalemääritteitä haluat muokata.
Single-line Composer Yhden rivin asettelu
Middle Eastern & South Asian Single-line Composer Yhden rivin asettelu (Lähi-itä ja Etelä-Aasia)
Standard Single-line Composer Tavallinen yhden rivin asettelu
Toggle Line Composer Vaihda rivien asettelu
Space After Paragraph Väli kappaleen jälkeen
Space Before Paragraph Väli ennen kappaletta
@@ -7530,3 +7532,4 @@ breakText Glyphs Merkit
Grommets Purjerenkaat
Grommet Inset Purjerenkaiden etäisyys reunasta
Diameter Halkaisija
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer on oltava "singleLine", "everyLine", "standardSingleLine" tai "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -1064,7 +1064,8 @@ font-technology Variable Variables
Every (minutes) Toutes les (minutes)
Every option is at its default. Toutes les options ont leur valeur par défaut.
Every option matches {base}. Toutes les options correspondent à {base}.
Every-line Composer Compositeur multiligne
Middle Eastern & South Asian Every-line Composer Compositeur multiligne (Moyen-Orient et Asie du Sud)
Standard Every-line Composer Compositeur standard multiligne
Exact dash lengths Longueurs de tirets exactes
Exceptions (comma separated) Exceptions (séparées par des virgules)
Exclude Exclusion
@@ -3395,7 +3396,8 @@ digits Malayalam Malayalam
Single Left Quotation Mark Guillemet simple ouvrant
Single Quotes: Guillemets simples :
Single Right Quotation Mark Guillemet simple fermant
Single-line Composer Compositeur ligne par ligne
Middle Eastern & South Asian Single-line Composer Compositeur ligne par ligne (Moyen-Orient et Asie du Sud)
Standard Single-line Composer Compositeur standard ligne par ligne
Toggle Line Composer Basculer le compositeur de lignes
Sixth Space Espace d’un sixième
Size Taille
@@ -7490,3 +7492,4 @@ breakText Glyphs Glyphes
Grommets Œillets
Grommet Inset Distance des œillets au bord
Diameter Diamètre
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer doit être "singleLine", "everyLine", "standardSingleLine" ou "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -3
View File
@@ -1699,7 +1699,8 @@ antiAlias Sharp शार्प
Every (minutes) हर (मिनट)
Every option is at its default. प्रत्येक ऑप्शन इसके डिफ़ॉल्ट रूप से होता है।
Every option matches {base}. प्रत्येक ऑप्शन {base} से मेल खाता है।
Every-line Composer हर लाइन संगीतकार
Middle Eastern & South Asian Every-line Composer हर लाइन संगीतकार (मध्य पूर्व और दक्षिण एशिया)
Standard Every-line Composer मानक हर लाइन संगीतकार
Exact सटीक
Exact dash lengths सटीक डैश लंबाई
Example: {name} उदाहरण: {name}
@@ -4673,7 +4674,8 @@ antiAlias Sharp शार्प
Single Quotes: एकल उद्धरण:
Single Right Quotation Mark सिंगल राइट कोटेशन मार्क
Single Word Justification: एकल शब्द जस्टिफ़िकेशन:
Single-line Composer एकल लाइन संगीतकार
Middle Eastern & South Asian Single-line Composer एकल लाइन संगीतकार (मध्य पूर्व और दक्षिण एशिया)
Standard Single-line Composer मानक एकल लाइन संगीतकार
Sixth Space छठे हिस्से जितना स्पेस
Size आकार
Size Tile to Art आकार टाइल कला के लिए
@@ -6567,7 +6569,7 @@ antiAlias Sharp शार्प
@msg command `{id}` is not available right now आदेश `{id}` अभी उपलब्ध नहीं है
@msg command must be a shape.* command command कोई shape.* कमांड होना चाहिए
@msg commands[{i}]: missing `command` आदेश [{i}]: लापता `command`
@msg composer must be "singleLine" or "everyLine" composer "singleLine" या "everyLine" होना चाहिए
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer "singleLine", "everyLine", "standardSingleLine" या "standardEveryLine" होना चाहिए
@msg compound {_1} must contain exactly one open path to join जोड़ने के लिए कंपाउंड {_1} में ठीक एक खुला पाथ होना चाहिए
@msg compound paths can only contain paths यौगिक पाथ में केवल पाथ हो सकते हैं
@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes कंपाउंड शेप पाथ, कंपाउंड पाथ, समूह, कंपाउंड शेप, टाइप, ब्लेंड और एन्वेलप लेते हैं
Can't render this file because it is too large.
+5 -2
View File
@@ -1356,7 +1356,8 @@ font-technology Variable Változó
Every (minutes) Gyakoriság (perc)
Every option is at its default. Minden beállítás az alapértéken áll.
Every option matches {base}. Minden beállítás egyezik: {base}.
Every-line Composer Többsoros tördelő
Middle Eastern & South Asian Every-line Composer Többsoros tördelő (Közel-Kelet és Dél-Ázsia)
Standard Every-line Composer Normál többsoros tördelő
Exact Pontos
Exact dash lengths Pontos vonalhosszak
Exceptions (comma separated) Kivételek (vesszővel elválasztva)
@@ -4052,7 +4053,8 @@ mark-style Japanese Japán
Single Left Quotation Mark Bal oldali szimpla idézőjel
Single Quotes: Szimpla idézőjelek:
Single Right Quotation Mark Jobb oldali szimpla idézőjel
Single-line Composer Egysoros tördelő
Middle Eastern & South Asian Single-line Composer Egysoros tördelő (Közel-Kelet és Dél-Ázsia)
Standard Single-line Composer Normál egysoros tördelő
Toggle Line Composer Sortördelő váltása
Sixth Space Hatodkvirt-szóköz
Size Méret
@@ -7479,3 +7481,4 @@ breakText Glyphs Glifák
Grommets Ringlik
Grommet Inset Ringlik távolsága a széltől
Diameter Átmérő
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer értéke "singleLine", "everyLine", "standardSingleLine" vagy "standardEveryLine" lehet
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -1837,7 +1837,8 @@ digits Malayalam Malayalam
Tabular Lining Lining tabular
Tabular Oldstyle Oldstyle tabular
Titling Alternates Alternatif judul
Every-line Composer Komposer tiap baris
Middle Eastern & South Asian Every-line Composer Komposer tiap baris (Timur Tengah dan Asia Selatan)
Standard Every-line Composer Komposer standar tiap baris
First-line Left Indent Indentasi kiri baris pertama
Hyphenation… Pemenggalan kata…
Justification… Justifikasi…
@@ -1869,7 +1870,8 @@ digits Malayalam Malayalam
East Asian Composition Settings Pengaturan komposisi Asia Timur
Korean Composition Settings Pengaturan komposisi Korea
Select a text object to edit its paragraph attributes. Pilih objek teks untuk mengedit atribut paragrafnya.
Single-line Composer Komposer satu baris
Middle Eastern & South Asian Single-line Composer Komposer satu baris (Timur Tengah dan Asia Selatan)
Standard Single-line Composer Komposer standar satu baris
Toggle Line Composer Alihkan komposer baris
Space After Paragraph Spasi setelah paragraf
Space Before Paragraph Spasi sebelum paragraf
@@ -6899,3 +6901,4 @@ breakText Glyphs Glif
Grommets Mata ayam
Grommet Inset Jarak mata ayam dari tepi
Diameter Diameter
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer harus "singleLine", "everyLine", "standardSingleLine", atau "standardEveryLine"
Can't render this file because it contains an unexpected character in line 2432 and column 5.
+5 -3
View File
@@ -1078,7 +1078,8 @@ font-technology Variable Variabili
Every (minutes) Ogni (minuti)
Every option is at its default. Tutte le opzioni hanno il valore predefinito.
Every option matches {base}. Tutte le opzioni corrispondono a {base}.
Every-line Composer Composizione su tutte le righe
Middle Eastern & South Asian Every-line Composer Composizione su tutte le righe (Medio Oriente e Asia meridionale)
Standard Every-line Composer Composizione standard su tutte le righe
Exact dash lengths Lunghezze esatte dei trattini
Exceptions (comma separated) Eccezioni (separate da virgole)
Exclude Escludi
@@ -3448,7 +3449,8 @@ digits Malayalam Malayalam
Single Left Quotation Mark Virgoletta singola di apertura
Single Quotes: Virgolette singole:
Single Right Quotation Mark Virgoletta singola di chiusura
Single-line Composer Composizione su riga singola
Middle Eastern & South Asian Single-line Composer Composizione su riga singola (Medio Oriente e Asia meridionale)
Standard Single-line Composer Composizione standard su riga singola
Toggle Line Composer Alterna composizione delle righe
Sixth Space Spazio di un sesto
Size Dimensione
@@ -7966,7 +7968,7 @@ breakText Glyphs Glifi
@msg column: true floats the whole column and takes no onto, above or below column: true rende mobile l'intera colonna e non accetta onto, above o below
@msg command must be a shape.* command command deve essere un comando shape.*
@msg commands[{i}]: missing `command` commands[{i}]: `command` mancante
@msg composer must be "singleLine" or "everyLine" composer deve essere "singleLine" o "everyLine"
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer deve essere "singleLine", "everyLine", "standardSingleLine" o "standardEveryLine"
@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes le forme composte accettano tracciati, tracciati composti, gruppi, forme composte, testo, fusioni e involucri
@msg compound {_1} must contain exactly one open path to join il composto {_1} deve contenere esattamente un tracciato aperto da unire
@msg connect end must be "start" or "end" end di connect deve essere "start" o "end"
Can't render this file because it is too large.
+5 -2
View File
@@ -1666,7 +1666,8 @@ antiAlias Sharp シャープ
Every (minutes) 間隔 (分)
Every option is at its default. すべてのオプションが初期値です。
Every option matches {base}. すべてのオプションが {base} と同じです。
Every-line Composer すべての行を一括処理
Middle Eastern & South Asian Every-line Composer すべての行を一括処理 (中東・南アジア)
Standard Every-line Composer すべての行を一括処理 (標準)
Exact dash lengths 破線の長さを正確に保つ
Exceptions (comma separated) 例外 (カンマ区切り)
Exclusion 除外
@@ -3256,7 +3257,8 @@ mark-style Japanese 日本式
Simulate Colored Paper 色紙をシミュレート
Simulate Paper 紙色をシミュレート
Single Quotes: 一重引用符:
Single-line Composer 1 行ずつ組む
Middle Eastern & South Asian Single-line Composer 1 行ずつ組む (中東・南アジア)
Standard Single-line Composer 1 行ずつ組む (標準)
Toggle Line Composer 行の組版方式を切り替え
Size Tile to Art タイルをアートワークのサイズに合わせる
Size/Leading サイズ/行送り
@@ -7191,3 +7193,4 @@ breakText Glyphs 字形
Grommets ハトメ
Grommet Inset 端からハトメまでの距離
Diameter 直径
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer は "singleLine"、"everyLine"、"standardSingleLine"、"standardEveryLine" のいずれかにしてください
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -1766,7 +1766,8 @@ digits Malayalam მალაიალამური
Tabular Lining ცხრილური ხაზოვანი
Tabular Oldstyle ცხრილური ძველებური
Titling Alternates სათაურის ალტერნატივები
Every-line Composer აბზაცის მიხედვით აწყობა
Middle Eastern & South Asian Every-line Composer აბზაცის მიხედვით აწყობა (შუა აღმოსავლეთი და სამხრეთ აზია)
Standard Every-line Composer სტანდარტული აბზაცის მიხედვით აწყობა
First-line Left Indent პირველი სტრიქონის მარცხენა შეწევა
Hyphenation… სიტყვების გადატანა…
Justification… სწორება…
@@ -1798,7 +1799,8 @@ digits Malayalam მალაიალამური
East Asian Composition Settings აღმოსავლეთ აზიური აწყობის პარამეტრები
Korean Composition Settings კორეული აწყობის პარამეტრები
Select a text object to edit its paragraph attributes. აბზაცის ატრიბუტების რედაქტირებისთვის მონიშნეთ ტექსტური ობიექტი.
Single-line Composer სტრიქონის მიხედვით აწყობა
Middle Eastern & South Asian Single-line Composer სტრიქონის მიხედვით აწყობა (შუა აღმოსავლეთი და სამხრეთ აზია)
Standard Single-line Composer სტანდარტული სტრიქონის მიხედვით აწყობა
Toggle Line Composer აწყობის რეჟიმის გადართვა
Space After Paragraph ინტერვალი აბზაცის შემდეგ
Space Before Paragraph ინტერვალი აბზაცის წინ
@@ -7609,3 +7611,4 @@ font-script Japanese იაპონური
Grommets ლუვერები
Grommet Inset ლუვერების დაშორება კიდიდან
Diameter დიამეტრი
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer უნდა იყოს "singleLine", "everyLine", "standardSingleLine" ან "standardEveryLine"
Can't render this file because it is too large.
+5 -2
View File
@@ -1656,7 +1656,8 @@ antiAlias Sharp 날카롭게
Every (minutes) 간격 (분)
Every option is at its default. 모든 옵션이 기본값입니다.
Every option matches {base}. 모든 옵션이 {base}와(과) 같습니다.
Every-line Composer 전체 줄 컴포저
Middle Eastern & South Asian Every-line Composer 전체 줄 컴포저 (중동·남아시아)
Standard Every-line Composer 표준 전체 줄 컴포저
Exact dash lengths 정확한 대시 길이
Exceptions (comma separated) 예외 (쉼표로 구분)
Exclusion 제외
@@ -3245,7 +3246,8 @@ mark-style Japanese 일본식
Simulate Colored Paper 색 용지 시뮬레이션
Simulate Paper 용지 시뮬레이션
Single Quotes: 작은따옴표:
Single-line Composer 한 줄 조판
Middle Eastern & South Asian Single-line Composer 한 줄 조판 (중동·남아시아)
Standard Single-line Composer 표준 한 줄 조판
Toggle Line Composer 줄 조판 방식 전환
Size Tile to Art 타일을 아트웍 크기에 맞춤
Size/Leading 크기/행간
@@ -7086,3 +7088,4 @@ breakText Glyphs 글리프
Grommets 아일렛
Grommet Inset 가장자리에서 아일렛까지 거리
Diameter 지름
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer는 "singleLine", "everyLine", "standardSingleLine" 또는 "standardEveryLine"이어야 합니다
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -2
View File
@@ -2354,7 +2354,8 @@ digits Malayalam Malayalam
Tabular Lining Tabulaire lining
Tabular Oldstyle Tabulaire oldstyle
Titling Alternates Titelalternatieven
Every-line Composer Compositie per alinea
Middle Eastern & South Asian Every-line Composer Compositie per alinea (Midden-Oosten en Zuid-Azië)
Standard Every-line Composer Standaardcompositie per alinea
First-line Left Indent Eerste regel links inspringen
Hyphenation… Afbreken…
Justification… Uitvullen…
@@ -2386,7 +2387,8 @@ digits Malayalam Malayalam
East Asian Composition Settings Instellingen voor Oost-Aziatische zetting
Korean Composition Settings Instellingen voor Koreaanse zetting
Select a text object to edit its paragraph attributes. Selecteer een tekstobject om de alineakenmerken ervan te bewerken.
Single-line Composer Compositie per regel
Middle Eastern & South Asian Single-line Composer Compositie per regel (Midden-Oosten en Zuid-Azië)
Standard Single-line Composer Standaardcompositie per regel
Toggle Line Composer Compositiemethode wisselen
Space After Paragraph Ruimte na alinea
Space Before Paragraph Ruimte voor alinea
@@ -7522,3 +7524,4 @@ breakText Glyphs Glyphs
Grommets Zeilringen
Grommet Inset Afstand van zeilringen tot de rand
Diameter Diameter
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer moet "singleLine", "everyLine", "standardSingleLine" of "standardEveryLine" zijn
Can't render this file because it contains an unexpected character in line 2 and column 73.
+5 -3
View File
@@ -1947,7 +1947,8 @@ digits Malayalam Malajalam
Tabular Lining Tabelaryczne nowoczesne
Tabular Oldstyle Tabelaryczne nautyczne
Titling Alternates Alternatywy tytułowe
Every-line Composer Kompozytor wielowierszowy
Middle Eastern & South Asian Every-line Composer Kompozytor wielowierszowy (Bliski Wschód i Azja Południowa)
Standard Every-line Composer Standardowy kompozytor wielowierszowy
First-line Left Indent Wcięcie pierwszego wiersza
Hyphenation… Dzielenie wyrazów…
Words Longer Than: Wyrazy dłuższe niż:
@@ -1987,7 +1988,8 @@ digits Malayalam Malajalam
East Asian Composition Settings Ustawienia składu wschodnioazjatyckiego
Korean Composition Settings Ustawienia składu koreańskiego
Select a text object to edit its paragraph attributes. Zaznacz obiekt tekstowy, aby edytować atrybuty akapitu.
Single-line Composer Kompozytor jednowierszowy
Middle Eastern & South Asian Single-line Composer Kompozytor jednowierszowy (Bliski Wschód i Azja Południowa)
Standard Single-line Composer Standardowy kompozytor jednowierszowy
Toggle Line Composer Przełącz kompozytor wierszy
Space After Paragraph Odstęp po akapicie
Space Before Paragraph Odstęp przed akapitem
@@ -8205,7 +8207,7 @@ breakText Glyphs Glify
@msg column: true floats the whole column and takes no onto, above or below column: true odłącza całą kolumnę i nie przyjmuje onto, above ani below
@msg command must be a shape.* command command musi być poleceniem shape.*
@msg commands[{i}]: missing `command` commands[{i}]: brak `command`
@msg composer must be "singleLine" or "everyLine" composer musi mieć wartość "singleLine" lub "everyLine"
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer musi mieć wartość "singleLine", "everyLine", "standardSingleLine" lub "standardEveryLine"
@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes kształty złożone przyjmują ścieżki, ścieżki złożone, grupy, kształty złożone, tekst, przejścia i koperty
@msg compound {_1} must contain exactly one open path to join obiekt złożony {_1} musi zawierać dokładnie jedną otwartą ścieżkę do połączenia
@msg connect needs a path other than the one extended connect wymaga ścieżki innej niż przedłużana
Can't render this file because it is too large.
+5 -3
View File
@@ -960,7 +960,8 @@ antiAlias Sharp Nítido
Every (minutes) A cada (minutos)
Every option is at its default. Todas as opções estão no padrão.
Every option matches {base}. Todas as opções correspondem a {base}.
Every-line Composer Compositor de Todas as Linhas
Middle Eastern & South Asian Every-line Composer Compositor de Todas as Linhas (Oriente Médio e Sul da Ásia)
Standard Every-line Composer Compositor Padrão de Todas as Linhas
Exact dash lengths Comprimentos de tracejado exatos
Exceptions (comma separated) Exceções (separadas por vírgula)
Exclude Excluir
@@ -2877,7 +2878,8 @@ digits Malayalam Malaiala
Single Left Quotation Mark Aspa Esquerda Única
Single Quotes: Aspas Simples:
Single Right Quotation Mark Aspa Direita Única
Single-line Composer Compositor de Linha Única
Middle Eastern & South Asian Single-line Composer Compositor de Linha Única (Oriente Médio e Sul da Ásia)
Standard Single-line Composer Compositor Padrão de Linha Única
Toggle Line Composer Alternar Compositor de Linhas
Sixth Space Espaço de Sexto
Size Tamanho
@@ -8181,7 +8183,7 @@ swatch Yellow Green Verde-amarelado
@msg column: true floats the whole column and takes no onto, above or below column: true torna flutuante a coluna inteira e não aceita onto, above nem below
@msg command must be a shape.* command command deve ser um comando shape.*
@msg commands[{i}]: missing `command` commands[{i}]: falta `command`
@msg composer must be "singleLine" or "everyLine" composer deve ser "singleLine" ou "everyLine"
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer deve ser "singleLine", "everyLine", "standardSingleLine" ou "standardEveryLine"
@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes formas compostas aceitam caminhos, caminhos compostos, grupos, formas compostas, texto, mesclagens e envelopes
@msg compound {_1} must contain exactly one open path to join o composto {_1} deve conter exatamente um caminho aberto para unir
@msg connect needs a path other than the one extended connect precisa de um caminho diferente do que foi estendido
Can't render this file because it is too large.
+5 -2
View File
@@ -1067,7 +1067,8 @@ font-technology Variable Вариативные
Every (minutes) Каждые (минут)
Every option is at its default. Все параметры имеют значения по умолчанию.
Every option matches {base}. Все параметры совпадают с {base}.
Every-line Composer Компоновщик всех строк
Middle Eastern & South Asian Every-line Composer Компоновщик всех строк (Ближний Восток и Южная Азия)
Standard Every-line Composer Стандартный компоновщик всех строк
Exact dash lengths Точная длина штрихов
Exceptions (comma separated) Исключения (через запятую)
Exclude Исключить
@@ -3435,7 +3436,8 @@ digits Malayalam Малаялам
Single Left Quotation Mark Одинарная открывающая кавычка
Single Quotes: Одинарные кавычки:
Single Right Quotation Mark Одинарная закрывающая кавычка
Single-line Composer Однострочный компоновщик
Middle Eastern & South Asian Single-line Composer Однострочный компоновщик (Ближний Восток и Южная Азия)
Standard Single-line Composer Стандартный однострочный компоновщик
Toggle Line Composer Переключить компоновщик строк
Sixth Space Шестая шпация
Size Размер
@@ -7584,3 +7586,4 @@ shape Open Открытый
Grommets Люверсы
Grommet Inset Отступ люверсов от края
Diameter Диаметр
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer должен быть "singleLine", "everyLine", "standardSingleLine" или "standardEveryLine"
Can't render this file because it is too large.
+5 -3
View File
@@ -1048,7 +1048,8 @@ font-technology Variable Variabla
Every (minutes) Intervall (minuter)
Every option is at its default. Alla alternativ har standardvärden.
Every option matches {base}. Alla alternativ matchar {base}.
Every-line Composer Flerradssättning
Middle Eastern & South Asian Every-line Composer Flerradssättning (Mellanöstern och Sydasien)
Standard Every-line Composer Standard-flerradssättning
Exact dash lengths Exakta strecklängder
Exceptions (comma separated) Undantag (kommaavgränsade)
Exclude Uteslut
@@ -3325,7 +3326,8 @@ digits Malayalam Malayalam
Single Left Quotation Mark Enkelt vänster citattecken
Single Quotes: Enkla citattecken:
Single Right Quotation Mark Enkelt höger citattecken
Single-line Composer Enradssättare
Middle Eastern & South Asian Single-line Composer Enradssättare (Mellanöstern och Sydasien)
Standard Single-line Composer Standard-enradssättare
Toggle Line Composer Växla radsättare
Sixth Space Sjättedelsblanksteg
Size Storlek
@@ -7874,7 +7876,7 @@ digits Hindi Hindi
@msg column: true floats the whole column and takes no onto, above or below column: true gör hela kolumnen flytande och tar inte onto, above eller below
@msg command must be a shape.* command command måste vara ett shape.*-kommando
@msg commands[{i}]: missing `command` commands[{i}]: `command` saknas
@msg composer must be "singleLine" or "everyLine" composer måste vara "singleLine" eller "everyLine"
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer måste vara "singleLine", "everyLine", "standardSingleLine" eller "standardEveryLine"
@msg compound {_1} must contain exactly one open path to join sammansatt {_1} måste innehålla exakt en öppen bana att foga samman
@msg compound shapes take paths, compound paths, groups, compound shapes, type, blends and envelopes sammansatta former tar banor, sammansatta banor, grupper, sammansatta former, text, övergångar och kuvert
@msg connect end must be "start" or "end" connect end måste vara "start" eller "end"
Can't render this file because it is too large.
+5 -2
View File
@@ -1040,7 +1040,8 @@ font-technology Variable Değişken
Every (minutes) Her (dakika)
Every option is at its default. Her seçenek varsayılan değerdedir.
Every option matches {base}. Her seçenek {base} ile eşleşir.
Every-line Composer Her Satır Bestecisi
Middle Eastern & South Asian Every-line Composer Her Satır Bestecisi (Orta Doğu ve Güney Asya)
Standard Every-line Composer Standart Her Satır Bestecisi
Exact dash lengths Tam çizgi uzunlukları
Exceptions (comma separated) İstisnalar (virgülle ayrılmış)
Exclude Hariç tut
@@ -3201,7 +3202,8 @@ digits Malayalam Malayalam
Single Left Quotation Mark Tek Sol Tırnak İşareti
Single Quotes: Tek Alıntılar:
Single Right Quotation Mark Tek Sağ Tırnak İşareti
Single-line Composer Tek Satır Oluşturucu
Middle Eastern & South Asian Single-line Composer Tek Satır Oluşturucu (Orta Doğu ve Güney Asya)
Standard Single-line Composer Standart Tek Satır Oluşturucu
Toggle Line Composer Satır Oluşturucuyu Değiştir
Sixth Space Altıncı Uzay
Size Boyut
@@ -7451,3 +7453,4 @@ breakText Glyphs Glifler
Grommets Kuşgözleri
Grommet Inset Kuşgözlerinin kenara uzaklığı
Diameter Çap
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer "singleLine", "everyLine", "standardSingleLine" veya "standardEveryLine" olmalıdır
Can't render this file because it contains an unexpected character in line 5 and column 25.
+5 -3
View File
@@ -1072,7 +1072,8 @@ font-technology Variable Варіативні
Every (minutes) Кожен (хвилин)
Every option is at its default. Усі параметри мають значення за промовчанням.
Every option matches {base}. Усі параметри збігаються з {base}.
Every-line Composer Компонувальник всіх рядків
Middle Eastern & South Asian Every-line Composer Компонувальник всіх рядків (Близький Схід і Південна Азія)
Standard Every-line Composer Стандартний компонувальник всіх рядків
Exact dash lengths Точна довжина штрихів
Exceptions (comma separated) Винятки (через кому)
Exclude Виключити
@@ -3440,7 +3441,8 @@ digits Malayalam Малаялам
Single Left Quotation Mark Одинарна лапка, що відкриває
Single Quotes: Одинарні лапки:
Single Right Quotation Mark Одинарна лапка, що закриває
Single-line Composer Однорядковий компонувальник
Middle Eastern & South Asian Single-line Composer Однорядковий компонувальник (Близький Схід і Південна Азія)
Standard Single-line Composer Стандартний однорядковий компонувальник
Toggle Line Composer Переключити компонувальник рядків
Sixth Space Шоста шпація
Size Розмір
@@ -7715,7 +7717,7 @@ breakText Glyphs Гліфи
@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 composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer має бути "singleLine", "everyLine", "standardSingleLine" або "standardEveryLine"
@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 потрібен контур, відмінний від того, що продовжується
Can't render this file because it is too large.
+5 -2
View File
@@ -1245,7 +1245,8 @@ font-technology Variable Biến thiên
Every (minutes) Mỗi (phút)
Every option is at its default. Mọi tùy chọn đang ở mặc định.
Every option matches {base}. Mọi tùy chọn khớp với {base}.
Every-line Composer Soạn theo từng dòng
Middle Eastern & South Asian Every-line Composer Soạn theo từng dòng (Trung Đông và Nam Á)
Standard Every-line Composer Soạn theo từng dòng tiêu chuẩn
Exact dash lengths Độ dài nét đứt chính xác
Exceptions (comma separated) Ngoại lệ (phân cách bằng dấu phẩy)
Exclude Loại trừ
@@ -3795,7 +3796,8 @@ mark-style Japanese Kiểu Nhật
Single Left Quotation Mark Dấu nháy đơn mở
Single Quotes: Dấu nháy đơn:
Single Right Quotation Mark Dấu nháy đơn đóng
Single-line Composer Soạn thảo một dòng
Middle Eastern & South Asian Single-line Composer Soạn thảo một dòng (Trung Đông và Nam Á)
Standard Single-line Composer Soạn thảo một dòng tiêu chuẩn
Toggle Line Composer Chuyển đổi cách soạn dòng
Sixth Space Dấu cách 1/6
Size Kích thước
@@ -7106,3 +7108,4 @@ breakText Glyphs Glyph
Grommets Khoen
Grommet Inset Khoảng cách từ mép đến khoen
Diameter Đường kính
@msg composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer phải là "singleLine", "everyLine", "standardSingleLine" hoặc "standardEveryLine"
Can't render this file because it contains an unexpected character in line 204 and column 5.
+5 -3
View File
@@ -1012,7 +1012,8 @@ antiAlias Sharp 锐利
Every (minutes) 每隔 (分钟)
Every option is at its default. 所有选项皆为默认值。
Every option matches {base}. 所有选项皆与{base}相同。
Every-line Composer 逐行排版器
Middle Eastern & South Asian Every-line Composer 逐行排版器(中东和南亚)
Standard Every-line Composer 标准逐行排版器
Exact dash lengths 精确虚线长度
Exceptions (comma separated) 例外词 (逗号分隔)
Exclude 差集
@@ -3264,7 +3265,8 @@ digits Malayalam 马拉雅拉姆数字
Single Left Quotation Mark 左单引号
Single Quotes: 单引号:
Single Right Quotation Mark 右单引号
Single-line Composer 单行排版器
Middle Eastern & South Asian Single-line Composer 单行排版器(中东和南亚)
Standard Single-line Composer 标准单行排版器
Toggle Line Composer 切换行排版器
Sixth Space 六分之一空格
Size 大小
@@ -8191,7 +8193,7 @@ breakText Glyphs 字形
@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 composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer 必须是 "singleLine"、"everyLine"、"standardSingleLine" 或 "standardEveryLine"
@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 需要一条不同于被延伸路径的路径
Can't render this file because it is too large.
+5 -3
View File
@@ -1042,7 +1042,8 @@ font-technology Variable 可變
Every (minutes) 每隔 (分鐘)
Every option is at its default. 所有選項皆為預設值。
Every option matches {base}. 所有選項皆與{base}相同。
Every-line Composer 逐行排版程式
Middle Eastern & South Asian Every-line Composer 逐行排版程式(中東與南亞)
Standard Every-line Composer 標準逐行排版程式
Exact dash lengths 精確虛線長度
Exceptions (comma separated) 例外 (以逗號分隔)
Exclude 差集
@@ -4517,7 +4518,8 @@ digits Malayalam 馬來亞拉姆數字
Single Left Quotation Mark 左單引號
Single Quotes: 單引號:
Single Right Quotation Mark 右單引號
Single-line Composer 單行排版程式
Middle Eastern & South Asian Single-line Composer 單行排版程式(中東與南亞)
Standard Single-line Composer 標準單行排版程式
Toggle Line Composer 切換行排版程式
Sixth Space 六分之一空格
Size 大小
@@ -7999,7 +8001,7 @@ breakText Glyphs 字符
@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 composer must be "singleLine", "everyLine", "standardSingleLine" or "standardEveryLine" composer 必須是 "singleLine"、"everyLine"、"standardSingleLine" 或 "standardEveryLine"
@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 需要延伸路徑以外的另一條路徑
Can't render this file because it is too large.
+1 -1
View File
@@ -393,7 +393,7 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
"type.lineComposer",
"Toggle Line Composer",
"Cmd+Alt+Shift+C",
"{} the selected type's paragraphs (or those the Type tool's selection touches) use the Single-line Composer when they all use the Every-line Composer, else the Every-line Composer (text.setFormat {composer}) → \"singleLine\" | \"everyLine\"",
"{} the selected type's paragraphs (or those the Type tool's selection touches) use the Single-line Composer when they all use the Every-line Composer, else the Every-line Composer, each keeping its shaping: Middle Eastern & South Asian or Standard (text.setFormat {composer}) → \"singleLine\" | \"everyLine\" | \"standardSingleLine\" | \"standardEveryLine\"",
),
(
"type.hyphenate",
+22 -7
View File
@@ -54,15 +54,27 @@ pub(crate) fn align(app: &mut VectorcraftApp, justify: &str) -> Result<Value, St
}
/// `type.lineComposer` (Cmd+Alt+Shift+C): the Single-line Composer for the paragraphs the panel
/// acts on when they all use the Every-line Composer, else the Every-line Composer. Returns the
/// composer set.
/// acts on when they all use the Every-line Composer, else the Every-line Composer; each keeps its
/// shaping (a Standard composer toggles to the other Standard one). Returns the composer set.
pub(crate) fn toggle_composer(app: &mut VectorcraftApp) -> Result<Value, String> {
text_style(app).ok_or("select some type first")?;
let id = if shared_composer(app) == Some(Composer::EveryLine) { "singleLine" } else { "everyLine" };
let shared = shared_composer(app);
let to_single = shared.is_some_and(|c| !c.is_single_line());
let id = composer_id(shared.unwrap_or_default().with_breaking(to_single));
format(app, json!({ "composer": id }));
Ok(json!(id))
}
/// The `text.setFormat` value of `composer`.
fn composer_id(composer: Composer) -> &'static str {
match composer {
Composer::SingleLine => "singleLine",
Composer::EveryLine => "everyLine",
Composer::StandardSingleLine => "standardSingleLine",
Composer::StandardEveryLine => "standardEveryLine",
}
}
/// `type.hyphenate` (Cmd+Alt+Shift+H): what the Hyphenate checkbox does, on the paragraphs the
/// panel acts on. Returns whether they now hyphenate.
pub(crate) fn toggle_hyphenate(app: &mut VectorcraftApp) -> Result<Value, String> {
@@ -876,11 +888,14 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
}
ui.separator();
let composer = shared_composer(app);
for (c, label, id) in
[(Composer::SingleLine, tl!("Single-line Composer"), "singleLine"), (Composer::EveryLine, tl!("Every-line Composer"), "everyLine")]
{
for (c, label) in [
(Composer::SingleLine, tl!("Middle Eastern & South Asian Single-line Composer")),
(Composer::EveryLine, tl!("Middle Eastern & South Asian Every-line Composer")),
(Composer::StandardSingleLine, tl!("Standard Single-line Composer")),
(Composer::StandardEveryLine, tl!("Standard Every-line Composer")),
] {
if menu_item(ui, label, has, composer == Some(c)) {
format(app, json!({ "composer": id }));
format(app, json!({ "composer": composer_id(c) }));
}
}
ui.separator();
@@ -82,6 +82,69 @@ fn paragraph_mixed_composer_checks_neither_menu_item() {
assert_eq!(shared_composer(&app), Some(Composer::EveryLine));
}
/// Cmd+Alt+Shift+C switches between Single-line and Every-line and keeps what each paragraph's
/// composer does with complex scripts: a Standard composer toggles to the other Standard one.
#[test]
fn toggling_the_line_composer_keeps_the_shaping() {
let (mut app, id) = editing_text("A\nB\n");
for (from, first, second) in [
("standardEveryLine", "standardSingleLine", "standardEveryLine"),
("everyLine", "singleLine", "everyLine"),
("standardSingleLine", "standardEveryLine", "standardSingleLine"),
] {
app.run("text.setFormat", json!({"id": id, "composer": from})).unwrap();
app.session.set_tool_option("selectAll", &json!(true));
assert_eq!(toggle_composer(&mut app).unwrap(), json!(first), "{from}");
assert_eq!(toggle_composer(&mut app).unwrap(), json!(second), "{from} again");
}
// Paragraphs that differ take Every-line, as before the Standard composers existed.
app.run("text.setFormat", json!({"id": id, "composer": "standardSingleLine"})).unwrap();
app.run("text.setFormat", json!({"id": id, "start": 2, "end": 3, "composer": "singleLine"})).unwrap();
app.session.set_tool_option("selectAll", &json!(true));
assert_eq!(toggle_composer(&mut app).unwrap(), json!("everyLine"));
}
/// The Paragraph panel menu lists the four composers, and ticks the one every selected paragraph has.
#[test]
fn the_paragraph_menu_sets_each_of_the_four_composers() {
let (mut app, id) = editing_text("A\nB\n");
app.session.set_tool_option("selectAll", &json!(true));
let ctx = egui::Context::default();
let items = |app: &mut VectorcraftApp| {
let mut seen = vec![];
let mut out = ctx.run_ui(egui::RawInput::default(), |ui| menu(app, ui));
out.textures_delta.clear();
for shape in out.shapes {
collect_texts(&shape.shape, &mut seen);
}
seen
};
fn collect_texts(shape: &egui::Shape, out: &mut Vec<String>) {
match shape {
egui::Shape::Vec(v) => v.iter().for_each(|s| collect_texts(s, out)),
egui::Shape::Text(t) => out.push(t.galley.text().to_string()),
_ => {}
}
}
let texts = items(&mut app);
for label in [
"Middle Eastern & South Asian Single-line Composer",
"Middle Eastern & South Asian Every-line Composer",
"Standard Single-line Composer",
"Standard Every-line Composer",
] {
assert!(texts.iter().any(|t| t == label), "{label} in {texts:?}");
}
for (value, want) in [
("standardEveryLine", Composer::StandardEveryLine),
("singleLine", Composer::SingleLine),
("standardSingleLine", Composer::StandardSingleLine),
] {
app.run("text.setFormat", json!({"id": id, "composer": value})).unwrap();
assert_eq!(shared_composer(&app), Some(want), "{value}");
}
}
#[test]
fn paragraph_mixed_hyphenate_checks_off() {
let (mut app, id) = editing_text("A\nB\n");
+15 -7
View File
@@ -1,6 +1,6 @@
# VectorCraft MCP server
> **Last updated:** 2026-11-13 · **Change:** Snap to Point with Smart Guides off draws no Smart Guides labels or lines, #7250; no response-shape change. Previously: Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter (#7097); existing response shapes retained.
> **Last updated:** 2026-11-14 · **Change:** `text.setFormat {composer}` and paragraph styles also take `standardSingleLine` and `standardEveryLine` (#4935); existing values and responses unchanged. Previously: Snap to Point with Smart Guides off draws no Smart Guides labels or lines, #7250; no response-shape change. Previously: Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter (#7097); existing response shapes retained.
`vectorcraft-cli mcp` runs a [Model Context Protocol](https://modelcontextprotocol.io) server on stdio
(newline-delimited JSON-RPC 2.0; see [Protocol](#protocol) for version negotiation). Agents use it to
@@ -9553,7 +9553,7 @@ The `paraStyleOptions` dialog exposes `name`, `section` (`general`, `basic`, `ta
100000 pt); it is disabled at 256 stops or when a stop is already at that position. Delete Tab removes the selected
stop, and Clear All Tabs leaves the style with no stops, which it then sets. OK sorts the stops by
position; of two stops at one position it keeps the one edited last.
- Composition: `composer` (`singleLine` or `everyLine`) and the `roman_hanging` checkbox.
- Composition: `composer` (`singleLine`, `everyLine`, `standardSingleLine` or `standardEveryLine`) and the `roman_hanging` checkbox.
- Hyphenation: the `hyphenate` checkbox, `words_longer_than`, `after_first`, `before_last`, `hyphen_limit`,
`hyphenation_zone` and the `hyphenate_capitalized` checkbox. The options are inactive while Hyphenation is off, and
Hyphenation Zone is inactive with the Every-line Composer.
@@ -10478,9 +10478,16 @@ of the group in the Layers panel (`layer.move`).
## Paragraph composer
`text.setFormat {ids?, composer: "singleLine"|"everyLine"}` sets how a text object's lines are broken (the Paragraph
panel menu's Single-line and Every-line Composer; stored in the paragraph attributes as `para.composer`, saved only
when it is Single-line). Every-line, the default, picks the breaks of the whole paragraph together in area type:
`text.setFormat {ids?, composer: "singleLine"|"everyLine"|"standardSingleLine"|"standardEveryLine"}` sets how a text
object's lines are broken and whether complex scripts are shaped (the Paragraph panel menu's four composers: Middle
Eastern & South Asian Single-line and Every-line, and Standard Single-line and Every-line; stored in the paragraph
attributes as `para.composer`, saved only when it is not Every-line, which is the default and what all type used before the
Standard composers existed). `singleLine` and `everyLine` shape Indic, Arabic and Hebrew type with the font's layout
tables, as all type is set; `standardSingleLine` and `standardEveryLine` break lines the same way but set such type
glyph by glyph as the font maps its characters (no conjuncts, reordering, mark placement or joining forms), for legacy
fonts that keep a script on Latin character codes. Latin and other scripts keep their kerning and ligatures under every
composer. An older VectorCraft cannot open a file that uses a Standard composer. `.ai`, EPS and PDF files carry no composer.
Every-line, the default, picks the breaks of the whole paragraph together in area type:
justified text gets even word spacing, ragged text (left, centre or right aligned) an even rag, so it may move a word
that fits to the next line to avoid a lone short word on the last line or a full line next to a short one.
Single-line fills each line as far as it goes. Point type and type on a path have no line width, so both composers
@@ -10492,8 +10499,9 @@ narrower, or beside a wrap object, gets the room there. Such a paragraph falls b
no room for all of it, or when the search for its breaks passes VectorCraft's own limits (1,000,000 lines tried and
2,000,000 baseline steps for one paragraph, 2,000,000 lines and 4,000,000 steps for all the paragraphs of a frame).
The UI command `type.lineComposer` (Cmd+Alt+Shift+C, in remote mode `press_key {key: "C", mods: {cmd: true, alt: true,
shift: true}}` or `invoke_menu`) sets `singleLine` when every paragraph of the selected type (or every paragraph the
Type tool's selection touches) uses Every-line, else `everyLine`, and returns the composer it set.
shift: true}}` or `invoke_menu`) sets the Single-line form when every paragraph of the selected type (or every paragraph the
Type tool's selection touches) uses an Every-line one, else the Every-line form, keeping each paragraph's shaping (`singleLine`
or `everyLine`; a Standard composer toggles between `standardSingleLine` and `standardEveryLine`), and returns the composer it set.
```json
{"name":"run_command","arguments":{"command":"text.setFormat","params":{"ids":[7],"composer":"singleLine"}}}
File diff suppressed because one or more lines are too long
+5 -3
View File
@@ -1,6 +1,6 @@
# Type parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-11 · **Change:** minor (kerning at the Type tool's caret at the start of a line sets the space before the character after it, #5111; previously minor: type's strokes in an envelope paint along its bent glyph outlines at their own weight, Distort Appearance on or off, as users' `.ai` files draw them, #6644; previously minor: a centred or right-aligned line of tracked type is aligned without the tracking after its last character, as the page of users' `.ai` files aligns it, #6610; previously minor: tracking and manual kerning in horizontally scaled type are thousandths of the em as the Horizontal Scale draws it, as the page of users' `.ai` files spaces such type; previously minor: Edit › Edit Custom Dictionary…: its dialog adds, deletes and changes the custom dictionary's words, #4936; previously minor: Direct Selection shows and drags the direction handles of type on a path's path, #3565; 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: Auto Spell Check: `edit.autoSpellCheck` underlines the unknown words, #4936; previously minor: PDF marked-text export (#6309): compatible glyphs stay on one layout line with per-glyph offsets; scores and estimates unchanged; paint-only Arabic harakat keep joining with GDEF-mark ownership and Insert Kashidas base-letter paint; scores and estimates unchanged; custom dictionary and Ignore All: `text.spelling.addWord`, `removeWord`, `changeWord`, `dictionary` and `ignoreAll`, #4936; previously minor: spell check engine: `text.spelling.check` and `text.spelling.suggest` on craft-proof, #4936; previously minor: right-aligned area type sets the text after a line's last tab against the right edge; a soft return in justified type no longer keeps its line from being justified; 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) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-14 · **Change:** minor (Paragraph composers (#4935): the Paragraph panel menu and paragraph styles offer four composers, the Middle Eastern & South Asian Single-line and Every-line (how all type is set, and the default) and a Standard Single-line and Every-line that set Indic, Arabic and Hebrew type glyph by glyph as the font maps it, for legacy fonts that keep a script on Latin character codes; `.ai` and EPS files do not carry the choice; scores and estimates unchanged; previously minor: kerning at the Type tool's caret at the start of a line sets the space before the character after it, #5111; previously minor: type's strokes in an envelope paint along its bent glyph outlines at their own weight, Distort Appearance on or off, as users' `.ai` files draw them, #6644; previously minor: a centred or right-aligned line of tracked type is aligned without the tracking after its last character, as the page of users' `.ai` files aligns it, #6610; previously minor: tracking and manual kerning in horizontally scaled type are thousandths of the em as the Horizontal Scale draws it, as the page of users' `.ai` files spaces such type; previously minor: Edit › Edit Custom Dictionary…: its dialog adds, deletes and changes the custom dictionary's words, #4936; previously minor: Direct Selection shows and drags the direction handles of type on a path's path, #3565; 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: Auto Spell Check: `edit.autoSpellCheck` underlines the unknown words, #4936; previously minor: PDF marked-text export (#6309): compatible glyphs stay on one layout line with per-glyph offsets; scores and estimates unchanged; paint-only Arabic harakat keep joining with GDEF-mark ownership and Insert Kashidas base-letter paint; scores and estimates unchanged; custom dictionary and Ignore All: `text.spelling.addWord`, `removeWord`, `changeWord`, `dictionary` and `ignoreAll`, #4936; previously minor: spell check engine: `text.spelling.check` and `text.spelling.suggest` on craft-proof, #4936; previously minor: right-aligned area type sets the text after a line's last tab against the right edge; a soft return in justified type no longer keeps its line from being justified; 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) · **Target:** Adobe Illustrator 2026 (30.x)
Glyphs review (#6084): a positional variant no supported feature draws is accepted as a glyph choice. Entire Font respects the selection's variable axes and font version; the default cell can reset an unlisted choice without GSUB alternates. Contextual choices use the supplying face, including fallback. Feature-only boundaries preserve ligature clusters and Arabic mark attachment. Encoded characters insert unchanged except Arabic presentation forms with a joining base letter; normalization reports success only after insertion succeeds. Latest follow-up regressions await runtime verification. Scores and estimates unchanged.
@@ -20,6 +20,7 @@ against Illustrator's public documentation; **estimated** unless noted.
| Feature | Status | Notes |
|---|---|---|
| 2026-11-14 | minor | Paragraph composers (#4935): `text.setFormat {composer}` and paragraph styles take `singleLine` and `everyLine` (the Middle Eastern & South Asian composers, what all type used and the default) and `standardSingleLine` and `standardEveryLine`, which break lines the same way and set a complex script (Indic, Arabic, Hebrew) glyph by glyph as the font maps its characters, with no conjuncts, reordering, marks placed or joining forms. The choice is per paragraph, saved in the native file only when it is not Every-line, and not written to `.ai`, EPS or PDF files, whose composer setting this app has no recorded format for. Scores and estimates unchanged. Tests `tests::composers`. |
| Mouse wheel over the closed font-family field | done | #5253: Character, Properties and Control step selected text through the family list using saved font filters (excluding search text), one undo step per notch; the style is matched and the list stops at either end. Escape and leaving the field keep the change. The field takes the wheel only when the pointer was moved onto it after the field last moved or was covered by a window or overlay, and the wheel stream began there; a stream that began elsewhere stays there until 0.5 s pass with no wheel input. Order, bounds, Undo grouping, this rule and its 0.5 s are VectorCraft's choices; scores unchanged. |
| Soft return (forced line break, Shift+Enter) | done | Shift+Enter inserts a soft return (U+2028), breaking the line without starting a new paragraph; paragraph spacing (space before/after) and first-line indents apply only at paragraph ends; continuation lines in lists do not repeat the marker; in justified text a line a soft return ends is justified as a wrapped line is, only the paragraph's last line keeping its alignment, as Illustrator's own layout in a user's `.ai` sets it (evidence: `tests::typo::soft_return_in_justified_text_spreads_like_a_wrapped_line`; first done the other way in #2754) |
| Native font-family labels | partial | With Show Font Names in English off, localized legacy names are used when typographic names contain no native label (#2208); loaded-font and catalog-only regressions. Choosing among multiple native languages is unchanged. |
@@ -40,7 +41,7 @@ against Illustrator's public documentation; **estimated** unless noted.
| Variable fonts | done | named instances as styles; Character panel › Variable Font sets each axis (`fontAxes`); the font menu's Font Technology › Variable lists only variable font families, with the script, kind and ★ filters ([Find, apply, and adjust variable fonts](https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/find-apply-and-adjust-variable-fonts.html)); a family with a variable file beside static ones counts as variable. Evidence: `font_menu::tests::the_variable_filter_lists_only_variable_families`, `tests_axes::a_family_with_variation_axes_is_variable`, `tests_sysfonts::a_family_with_a_variable_file_beside_static_ones_is_variable` |
| Fallback glyphs keep the text's weight and slant | done | #2491: a character from a fallback face is set in that family's face nearest the run's weight and slant; Bold Italic of a missing family is drawn Bold (Source Sans 3 has no Bold Italic) rather than Italic; a letter and its combining marks (a grapheme cluster) are drawn in one face, the first that has all of them, so marks the text's font lacks attach to their letter instead of drawing as missing glyphs (#4491). Vietnamese letters with two marks (Ể, Ứ, Ự) sit on their letter whether typed precomposed, decomposed or as a vowel plus a tone mark, built from GPOS mark-to-mark in fonts without the precomposed letters. Evidence: `tests::vietnamese` |
| Colour fonts (bitmap, COLR, OpenType SVG) | partial | bitmap glyphs (`sbix`, `CBDT`) done: the largest strike's PNG, transformed with the type, fill and stroke ignored; PDF Type 3 glyphs or images, SVG images with outlined text (live text leaves emoji to the viewer, their fonts not embedded), EPS and legacy `.ai` images, Create Outlines images; not `sbix` duplicate, flipped, JPEG or TIFF glyphs, or `CBDT` BGRA or mask data, or ruby; in envelopes they warp as images do, and a Warp effect moves them without bending them. COLR (v0 and v1) done: a glyph's layers as vector art (solid colours, linear and radial gradients, clip glyphs and boxes, blend modes, transforms, palette 0, the foreground colour from the run's fill, variable fonts at the face's instance), transformed with the type; drawn on the canvas, written as paths in SVG, EPS, legacy `.ai` and PDF with outlined text, as text in PDF (Type 3 glyphs), and Create Outlines makes groups of editable paths. Paints documents have no form for draw the glyph as an image (256 px per em): sweep gradients, Porter-Duff compositing, radial gradients from a circle that isn't the centre, repeating or reflecting gradients. Not ruby. COLR and SVG glyphs also go with type that geometry effects reshape (on the canvas and in exports), into Expand Appearance and EMF/WMF export, as their art, and bitmap glyphs as images. OpenType SVG done: a glyph's SVG document (its element `glyph<gid>`) is read by the SVG importer into vector art in font units, `currentColor` in the run's fill (and the legacy `context-fill` and `context-stroke` in its fill and stroke), a `viewBox` mapped onto the em square, and then drawn, exported and outlined as COLR glyphs are; in PDF real text such glyphs are text that draws nothing, with their art drawn where they sit. Images in glyph documents are in the art, holding their pixels until a document takes them in; text, scripts and embedded content are left out, as the table rules them out. Not CPAL palette variables. Evidence: `tests_svg_glyphs`, `svg/tests/it/svg_glyphs.rs`, `tests_colourfonts::svg_glyph_images_draw_and_outline`, `tests_colourfonts::create_outlines_turns_svg_glyphs_into_groups`, `tests_colourfonts::pdf_real_text_draws_svg_glyphs_as_art_and_keeps_their_characters`, `tests_colourfonts::expand_appearance_keeps_the_colour_glyphs_of_type_with_effects`, `render::tests_colrglyphs::colour_glyphs_go_with_type_that_a_geometry_effect_reshapes`, `tests_bitmaps`, `tests_colr`, `render::tests_bitmapglyphs`, `render::tests_colrglyphs`, `pdf::tests::colour_bitmap_glyphs_export_as_images`, `pdf::tests::colr_glyphs_export_as_vector_art`, `svg/tests/it/colour_glyphs.rs`, `eps` `colour_bitmap_glyphs_*` and `colr_glyphs_*`, `tests_pathops::create_outlines_turns_bitmap_glyphs_into_images`, `tests_pathops::create_outlines_turns_colr_glyphs_into_layer_groups` |
| Every-line and Single-line composers | done | tuned by eye, never compared side by side |
| Every-line and Single-line composers | done | tuned by eye, never compared side by side; each in a Middle Eastern & South Asian and a Standard form (#4935), see below |
| Optical Margin Alignment | done | Type › Optical Margin Alignment, `type.opticalMarginAlignment`: per type object, with one setting for all the frames of a thread, in point and area type of left-to-right paragraphs, and at the brackets of type on a path whose first paragraph runs left to right; right-to-left paragraphs of point and area type, and type on a path whose first paragraph runs right to left, do not hang |
| System Layout | done | Character panel menu › System Layout, `type.systemLayout`: the whole document, off by default and for documents from before it, saved only when on. On, every text object advances by whole points (at least one when a character takes space). New point, area and path type, threaded frames, placed text, graph and dimension labels and pasted plain text inherit it. Evidence: `tests::system_layout_rounds_positive_advances_to_whole_points`, `typecmd::area_tests::system_layout_sets_the_document_and_every_text_object`, `panels::character::tests::system_layout_menu_item_toggles_the_document` |
| Fractional Widths | done | Character panel menu › Fractional Widths, `type.fractionalWidths`: per type object, and every frame of its threads. On by default and for documents from before it; saved only when off. Off, each character that takes space advances by a whole number of points, at least one, so small type does not run together. Evidence: `tests::fractional_widths_off_rounds_positive_advances_to_whole_points`, `typecmd::area_tests::fractional_widths_is_set_per_object_and_saved_only_when_off`, `panels::character::tests::fractional_widths_menu_item_toggles_the_type_object` |
@@ -61,7 +62,8 @@ against Illustrator's public documentation; **estimated** unless noted.
| Middle Eastern: bidirectional layout, Paragraph Direction | done | PDF export keeps harakat and zero-advance Noto Arabic dot glyphs in one compatible batch per layout line, with per-glyph vertical offsets (#6309). `crates/pdf/src/tests/realtext.rs` (`mark_text_*`) checks decoded cluster mappings, mixed Arabic/Latin/digits, contour placement against outline export, vertical columns, differing path rotations and PDF/X-1a/3/4. Editable-text import still needs ActualText support (#6165); separately styled or differently rotated clusters and external viewer search/copy remain outside this export-only evidence. |
| Middle Eastern and Indic: digit types (Character panel menu › Digits: Default, Arabic, Hindi, Farsi; Devanagari, Bengali, Gurmukhi, Gujarati, Odia, Tamil, Telugu, Kannada, Malayalam) | done | `text.setFormat` / `text.setRangeStyle {digits}` (`"devanagari"`, `"bengali"`, `"gurmukhi"`, `"gujarati"`, `"odia"`, `"tamil"`, `"telugu"`, `"kannada"`, `"malayalam"` added, #4942); the text keeps the typed digits, the glyphs and SVG export follow the style; carried by character styles. Not yet: `.ai` export of the setting; Indic digits typed as such stay as typed under another system. Evidence: `text::tests::indic_digits_map_to_their_scripts_block`, `tests::bidi::indic_digits_draw_the_scripts_own_digits`, `typecmd::area_tests::indic_digits_round_trip_through_the_commands_and_the_file` |
| Middle Eastern: Kashidas | done | Paragraph Insert Kashidas sets the length for justified Arabic area type; Character-menu Kashidas allows or excludes selected characters, on by default. A kashida is inserted only between two allowed joined characters. The character switch is retained in character styles and the native file; the length is retained in paragraph styles and the native file. Paint-only harakat (coloured or hidden marks) stay in one shaping cluster so letters keep joining; when the character-level pass matches, a glyph may take a later in-cluster character's run only if GDEF names it a mark (class 3) and that character is a harakat—otherwise the cluster start (a mark may miss its colour; a base never takes a mark's). Inserted tatweels take the base letter's paint—not a trailing mark's. Fonts without GDEF and some AAT/`morx` ligatures (e.g. Geeza Pro Allah) can leave a mark painted as its letter. No Character-panel harakat colour command yet. Evidence: `tests::harakat`. [Public help](https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/justify-text-using-kashida-and-hyphenation.html). |
| Middle Eastern: Middle Eastern composers, split caret | missing | Character Direction is done; editable bidirectional SVG text remains incomplete. |
| Middle Eastern & South Asian composers and Standard composers (Paragraph panel menu, paragraph styles, `text.setFormat {composer}`) | done / partial | #4935: per paragraph, four choices. Middle Eastern & South Asian Single-line and Every-line are how all type was already set (complex-script shaping on) and stay the default, so existing documents do not change. Standard Single-line and Every-line break lines the same way and set Indic, Arabic and Hebrew type glyph by glyph as the font maps its characters (no conjuncts, reordering, mark placement or joining), for legacy fonts that keep a script on Latin character codes; Latin and other scripts keep their kerning and ligatures. The native file and paragraph styles keep the choice (`standardSingleLine` / `standardEveryLine`; an older VectorCraft cannot read a file that uses them). `.ai`, EPS and PDF import and export carry no composer: this app has no recorded format for it, so a Standard paragraph opened from or saved to those files comes back Middle Eastern & South Asian. Evidence: `tests::composers`, `tests::panelcmds::text_set_format_takes_the_four_composers`, `native_v3::all_four_composers_round_trip` |
| Middle Eastern: split caret | missing | Character Direction is done; editable bidirectional SVG text remains incomplete. |
| CJK: input methods (marked text, candidate window) | done | |
| CJK: kinsoku (Hard, Soft, None), the predefined mojikumi sets (None, YakumonoHankaku, GyomatsuYakumonoHankaku, GyomatsuYakumonoZenkaku, YakumonoZenkaku, with VectorCraft's own spacing for each) and Line-end Punctuation Half Width, tate-chu-yoko (auto) | done / partial | custom kinsoku sets, custom mojikumi sets and the Mojikumi Settings dialog missing |
| CJK: Kinsoku Shori Type (Push In First, Push Out First, Push Out Only) | done | Paragraph panel menu › Kinsoku Shori Type (`text.setFormat {kinsokuType}`), with the East Asian options ([Formatting Asian characters](https://helpx.adobe.com/illustrator/using/formatting-asian-characters.html)); Push Out Only is the default, and a push-in closes the line's gaps next to CJK characters by at most a tenth of an em each (VectorCraft's own limit). Evidence: `layout::wrapping_tests::kinsoku_shori_type_pushes_a_closing_bracket_in_or_out`, `tests::vertical::kinsoku_shori_type_pushes_a_closing_bracket_in_or_out`, `typecmd::area_tests::kinsoku_shori_type_is_set_per_paragraph_and_saved_only_when_not_push_out_only` |