Merge pull request #4845 from Taha-Mahmoodi/feat/units-east-asian-type

Units: Preferences › East Asian Type reads, with Q and Ha units (#394)
This commit is contained in:
BFlat
2026-11-02 14:56:57 +07:00
committed by GitHub
37 changed files with 335 additions and 37 deletions
+77
View File
@@ -145,9 +145,86 @@ fn mixed_mul_div() {
assert_eq!(Unit::Points.parse("10*2/5 px"), Some(Unit::Pixels.to_pt(4.0)));
}
/// Q and Ha are a quarter of a millimetre each, written back and read in any field, with or
/// without their suffix.
#[test]
fn q_and_ha_are_a_quarter_millimetre() {
for u in [Unit::Q, Unit::Ha] {
assert!((u.points() - Unit::Millimeters.points() / 4.0).abs() < 1e-12, "{u:?}");
assert!((u.to_pt(4.0) - Unit::Millimeters.to_pt(1.0)).abs() < 1e-12, "{u:?}");
let tol = 0.0005 * u.points() + 1e-9;
for pt in [0.0, 1.0, 12.5, 72.0, 100.0, 595.28, 1234.5678, -36.0] {
let shown = u.format(pt);
let back = u.parse(&shown).unwrap_or_else(|| panic!("{u:?} can't read back `{shown}`"));
assert!((back - pt).abs() <= tol, "{u:?}: {pt} → `{shown}` → {back}");
let bare = u.parse(&u.number(pt)).unwrap();
assert!((bare - pt).abs() <= tol, "{u:?}: bare `{}` → {bare}", u.number(pt));
let pts = Unit::Points.parse(&shown).unwrap();
assert!((pts - pt).abs() <= tol, "{u:?}: `{shown}` in a points field → {pts}");
}
}
assert_eq!(Unit::Q.format(72.0 / 25.4), "4 Q");
assert_eq!(Unit::Ha.format(Unit::Millimeters.to_pt(2.5)), "10 H");
// 13 Q is 3.25 mm, however it is typed.
let want = Unit::Millimeters.to_pt(3.25);
for typed in ["13q", "13 Q", "13Q+0", "26/2 q"] {
let got = Unit::Points.parse(typed).unwrap_or_else(|| panic!("`{typed}` reads as nothing"));
assert!((got - want).abs() < 1e-9, "`{typed}` → {got}");
}
assert!((Unit::Q.parse("13").unwrap() - want).abs() < 1e-9, "a bare number is in the field's unit");
assert!((Unit::Millimeters.parse("13 h").unwrap() - want).abs() < 1e-9, "a typed unit wins over the field's");
for typed in ["13h", "13 H", "13Ha", "13 ha"] {
assert!((Unit::Points.parse(typed).unwrap() - want).abs() < 1e-9, "`{typed}`");
}
// Mixed with other units.
assert!((Unit::Points.parse("4q+1mm").unwrap() - Unit::Millimeters.to_pt(2.0)).abs() < 1e-9);
}
/// Only Preferences › Units › East Asian Type offers Q and Ha: the list every other place shares
/// leaves them out, and `named` answers for it alone.
#[test]
fn only_the_east_asian_type_list_names_q_and_ha() {
assert_eq!(Unit::EAST_ASIAN[..10], Unit::ALL);
assert_eq!(Unit::EAST_ASIAN[10..], [Unit::Q, Unit::Ha]);
for u in Unit::EAST_ASIAN {
assert_eq!(Unit::named_east_asian(u.label()), Some(u));
assert_eq!(Unit::named_east_asian(u.key()), Some(u));
assert_eq!(Unit::named_east_asian(&u.label().to_uppercase()), Some(u));
assert_eq!(Unit::named_east_asian(u.suffix()), if u == Unit::FeetInches { Some(Unit::Feet) } else { Some(u) });
}
for name in ["q", "Q", "ha", "Ha", "H", "h"] {
assert_eq!(Unit::named(name), None, "`{name}`");
}
assert_eq!(Unit::named_east_asian("Q"), Some(Unit::Q));
assert_eq!(Unit::named_east_asian("h"), Some(Unit::Ha));
assert_eq!(Unit::named_east_asian("Ha"), Some(Unit::Ha));
assert_eq!(Unit::named_east_asian("furlongs"), None);
}
#[test]
fn readout_has_no_negative_zero() {
assert_eq!(Unit::Points.readout(-0.001), "0.00 pt");
assert_eq!(Unit::Points.readout(-0.0), "0.00 pt");
assert_eq!(Unit::Points.readout(-12.5), "-12.50 pt");
}
/// Q and Ha take the suffixes `q` and `h` (`ha` too) without taking anyone else's: every unit's
/// own suffix still reads as that unit in a points field, a Q or Ha value is never read as
/// another unit, and `h`, `ha` and `q` mean nothing to a unit that is not offered Q and Ha when
/// they are typed as words that are not suffixes (`1hr`, `1hq`, `1qt`).
#[test]
fn q_and_ha_suffixes_do_not_take_other_units_suffixes() {
for u in Unit::EAST_ASIAN {
if matches!(u, Unit::FeetInches) {
continue;
}
let typed = format!("3{}", u.suffix());
let got = Unit::Points.parse(&typed).unwrap_or_else(|| panic!("`{typed}` reads as nothing"));
assert!((got - u.to_pt(3.0)).abs() < 1e-9, "`{typed}` is 3 {u:?}: {got}");
}
for typed in ["1hr", "1hq", "1qt", "1qq", "1hh", "1hm", "1hectare"] {
assert_eq!(Unit::Points.parse(typed), None, "`{typed}`");
}
// A suffix after math covers the whole expression, as for the other units.
assert!((Unit::Points.parse("26/2 q").unwrap() - Unit::Q.to_pt(13.0)).abs() < 1e-9);
}
+51 -10
View File
@@ -14,6 +14,11 @@ pub enum Unit {
Meters,
Yards,
Feet,
/// Q (級), a quarter of a millimetre: the Japanese typesetting unit of type size.
Q,
/// Ha (歯), also a quarter of a millimetre: the Japanese unit of spacing, leading and
/// positions.
Ha,
}
impl Unit {
@@ -29,6 +34,23 @@ impl Unit {
Unit::Yards,
Unit::Feet,
];
/// The units Preferences › Units › East Asian Type offers: all of [`Unit::ALL`], then Q and
/// Ha. Only that preference lists Q and Ha; rulers, documents and the other Units
/// preferences stay on [`Unit::ALL`].
pub const EAST_ASIAN: [Unit; 12] = [
Unit::Points,
Unit::Picas,
Unit::Inches,
Unit::Millimeters,
Unit::Centimeters,
Unit::Pixels,
Unit::FeetInches,
Unit::Meters,
Unit::Yards,
Unit::Feet,
Unit::Q,
Unit::Ha,
];
/// Points per unit.
pub fn points(self) -> f64 {
match self {
@@ -37,6 +59,8 @@ impl Unit {
Unit::Inches => 72.0,
Unit::Millimeters => 72.0 / 25.4,
Unit::Centimeters => 72.0 / 2.54,
// 0.25 mm each.
Unit::Q | Unit::Ha => 72.0 / 101.6,
Unit::Meters => 72.0 / 0.0254,
Unit::Yards => 72.0 * 36.0,
Unit::Feet | Unit::FeetInches => 72.0 * 12.0,
@@ -53,9 +77,11 @@ impl Unit {
Unit::FeetInches | Unit::Feet => "ft",
Unit::Meters => "m",
Unit::Yards => "yd",
Unit::Q => "Q",
Unit::Ha => "H",
}
}
pub fn label(self) -> &'static str {
pub const fn label(self) -> &'static str {
match self {
Unit::Points => "Points",
Unit::Picas => "Picas",
@@ -66,6 +92,8 @@ impl Unit {
Unit::FeetInches => "Feet & Inches",
Unit::Meters => "Meters",
Unit::Yards => "Yards",
Unit::Q => "Q",
Unit::Ha => "Ha",
Unit::Feet => "Feet",
}
}
@@ -115,12 +143,13 @@ impl Unit {
pub fn number(self, pt: f64) -> String {
// Three decimals for the small units (`595.276 pt`), four for the large ones (`8.2677 in`,
// `35.2778 mm`, the `0.0078 in` stroke preset); trailing zeros are trimmed (`1 pt` is `1`).
let decimals = if matches!(self, Unit::Points | Unit::Pixels | Unit::Picas) { 3 } else { 4 };
let decimals = if matches!(self, Unit::Points | Unit::Pixels | Unit::Picas | Unit::Q | Unit::Ha) { 3 } else { 4 };
let s = format!("{:.*}", decimals, self.from_pt(pt));
let s = s.trim_end_matches('0').trim_end_matches('.');
if s == "-0" { "0".into() } else { s.into() }
}
/// Parse `12`, `12pt`, `1in`, `3 mm`, `2p6` (picas+points), simple `+ - * /` arithmetic.
/// Parse `12`, `12pt`, `1in`, `3 mm`, `2p6` (picas+points), `6q` (Q) and `6h` (Ha), simple
/// `+ - * /` arithmetic.
///
/// A unit after a `*` or `/` operand measures the whole expression (`1080/2 px` is 540 px), so
/// math typed before a field's unit suffix works. After `*` or `/`, a percentage scales the term
@@ -132,7 +161,7 @@ impl Unit {
}
/// The value naming this unit in the Units preferences (`points`, `millimeters`,
/// `feetInches`).
pub fn key(self) -> &'static str {
pub const fn key(self) -> &'static str {
match self {
Unit::Points => "points",
Unit::Picas => "picas",
@@ -144,19 +173,29 @@ impl Unit {
Unit::Meters => "meters",
Unit::Yards => "yards",
Unit::Feet => "feet",
Unit::Q => "q",
Unit::Ha => "ha",
}
}
/// The unit `name` names: its label, suffix or [`Unit::key`] in any case, ignoring spaces and
/// punctuation (`Millimeters`, `mm`, `Feet & Inches`, `feetInches`).
/// The unit of [`Unit::ALL`] that `name` names: its label, suffix or [`Unit::key`] in any
/// case, ignoring spaces and punctuation (`Millimeters`, `mm`, `Feet & Inches`, `feetInches`).
/// Q and Ha are named by [`Unit::named_east_asian`] only.
pub fn named(name: &str) -> Option<Unit> {
Self::named_in(&Unit::ALL, name)
}
/// [`Unit::named`] among the units of Preferences › Units › East Asian Type
/// ([`Unit::EAST_ASIAN`]): also `Q` and `Ha` (`q`, `H`).
pub fn named_east_asian(name: &str) -> Option<Unit> {
Self::named_in(&Unit::EAST_ASIAN, name)
}
fn named_in(units: &[Unit], name: &str) -> Option<Unit> {
let letters = |s: &'static str| s.chars().filter(char::is_ascii_alphanumeric).map(|c| c.to_ascii_lowercase());
let given = || name.chars().filter(char::is_ascii_alphanumeric).map(|c| c.to_ascii_lowercase());
// Feet and Feet & Inches share the suffix `ft`: it names the plain unit, so Feet & Inches
// is left to its label and key.
Unit::ALL
.into_iter()
.find(|u| letters(u.label()).eq(given()))
.or_else(|| Unit::ALL.into_iter().filter(|u| *u != Unit::FeetInches).find(|u| u.suffix().chars().eq(given())))
units.iter().copied().find(|u| letters(u.label()).eq(given())).or_else(|| {
units.iter().copied().filter(|u| *u != Unit::FeetInches).find(|u| u.suffix().chars().map(|c| c.to_ascii_lowercase()).eq(given()))
})
}
/// A point value as the canvas measurement labels show it: two decimals and the suffix
/// (`12.50 mm`).
@@ -254,6 +293,8 @@ fn number_unit(s: &str) -> Option<(f64, Option<Unit>)> {
"ft" | "'" => Some(Unit::Feet),
"yd" => Some(Unit::Yards),
"p" | "pc" => Some(Unit::Picas),
"q" | "Q" => Some(Unit::Q),
"h" | "H" | "ha" | "Ha" => Some(Unit::Ha),
_ => return None,
};
Some((v, unit))
+11 -1
View File
@@ -81,6 +81,16 @@ pub const UNITS: &[(&str, &str)] = &[
("yards", "Yards"),
("feet", "Feet"),
];
/// What Units › East Asian Type offers, as (`Unit::key`, `Unit::label`): [`Unit::EAST_ASIAN`].
pub const EAST_ASIAN_UNITS: &[(&str, &str)] = &{
let mut out = [("", ""); Unit::EAST_ASIAN.len()];
let mut i = 0;
while i < out.len() {
out[i] = (Unit::EAST_ASIAN[i].key(), Unit::EAST_ASIAN[i].label());
i += 1;
}
out
};
const LINE_STYLE: &[(&str, &str)] = &[("lines", "Lines"), ("dots", "Dots")];
/// Performance › Graphics Processor (`gpuPreference`), read by the desktop app at startup. The
/// values are WebGPU's power preferences plus `automatic`; 0.5.0's default, `powerSaving`, reads as
@@ -201,7 +211,7 @@ pub const PREF_SPECS: &[PrefSpec] = &[
p!("unitsGeneral", "Units", "", "General", choice(UNITS)),
p!("unitsStroke", "Units", "", "Stroke", choice(UNITS)),
p!("unitsType", "Units", "", "Type", choice(UNITS)),
p!("unitsAsianType", "Units", "", "East Asian Type", choice(UNITS)),
p!("unitsAsianType", "Units", "", "East Asian Type", choice(EAST_ASIAN_UNITS)),
p!("numbersWithoutUnitsArePoints", "Units", "", "Numbers Without Units Are Points", bool),
p!("identifyObjectsBy", "Units", "", "Identify Objects By", choice(&[("objectName", "Object Name"), ("xmlId", "XML ID")])),
// Guides & Grid
+55 -1
View File
@@ -6,7 +6,7 @@ use serde_json::json;
use vectorcraft_doc::Unit;
use vectorcraft_tools::{Mods, Overlay, PointerEvent, PointerKind};
use crate::cmd::prefscmds::{PREF_SPECS, PrefKind, UNITS};
use crate::cmd::prefscmds::{EAST_ASIAN_UNITS, PREF_SPECS, PrefKind, UNITS};
use crate::units::Measure;
use crate::*;
@@ -132,3 +132,57 @@ fn distance_params_take_a_unit() {
let st = t.first_style();
assert_eq!((st.size, st.leading, st.tracking), (36.0, Some(72.0), 20.0));
}
#[test]
fn east_asian_type_unit_is_a_preference_that_offers_q_and_ha() {
let want: Vec<(&str, &str)> = Unit::EAST_ASIAN.iter().map(|u| (u.key(), u.label())).collect();
assert_eq!(EAST_ASIAN_UNITS, want.as_slice());
let mut s = session();
assert_eq!(s.east_asian_type_unit(), Unit::Points, "points until chosen");
for u in Unit::EAST_ASIAN {
s.execute("prefs.set", &json!({"key": "unitsAsianType", "value": u.key()})).unwrap();
assert_eq!(s.east_asian_type_unit(), u);
assert_eq!(s.unit(Measure::AsianType), u);
assert_eq!(s.type_unit(), Unit::Points, "Type is its own preference");
}
// By label, in any case.
s.execute("prefs.set", &json!({"key": "unitsAsianType", "value": "ha"})).unwrap();
assert_eq!(s.prefs.units_asian_type, "ha");
s.execute("prefs.set", &json!({"key": "unitsAsianType", "value": "Q"})).unwrap();
assert_eq!(s.prefs.units_asian_type, "q");
// No other Units preference offers them.
for key in ["unitsGeneral", "unitsStroke", "unitsType"] {
for v in ["q", "Q", "ha", "Ha"] {
assert!(s.execute("prefs.set", &json!({"key": key, "value": v})).is_err(), "{key} = {v}");
}
}
assert_eq!((Measure::AsianType.name(), Measure::AsianType.pref_key()), ("asianType", "unitsAsianType"));
let list = s.execute("prefs.list", &json!({})).unwrap();
let row = list.as_array().unwrap().iter().find(|r| r["key"] == "unitsAsianType").unwrap().clone();
assert_eq!(row["options"].as_array().unwrap().iter().rev().take(2).collect::<Vec<_>>(), [&json!("ha"), &json!("q")]);
}
#[test]
fn east_asian_type_unit_leaves_the_document_in_points() {
let mut s = session();
let id = s.execute("text.create", &json!({"x": 10, "y": 10, "text": "日本語"})).unwrap()["id"].clone();
s.execute("select.set", &json!({ "ids": [id] })).unwrap();
s.execute("text.setStyle", &json!({"size": 12, "leading": 15})).unwrap();
let before = s.doc().unwrap().doc.clone();
s.execute("prefs.set", &json!({"key": "unitsAsianType", "value": "q"})).unwrap();
let after = &s.doc().unwrap().doc;
assert_eq!(units(&s), Unit::Points);
assert_eq!(after.units, before.units);
let size = |d: &vectorcraft_doc::Document| match &d.node(NodeId(id.as_u64().unwrap())).unwrap().kind {
NodeKind::Text(t) => (t.first_style().size, t.first_style().leading),
_ => panic!("not text"),
};
assert_eq!(size(after), size(&before));
assert_eq!(size(after), (12.0, Some(15.0)));
// Typed in Q or Ha, the value is stored in points.
s.execute("text.setStyle", &json!({"size": "17 Q", "leading": "20 H"})).unwrap();
let (sz, lead) = size(&s.doc().unwrap().doc);
assert!((sz - Unit::Q.to_pt(17.0)).abs() < 1e-9, "{sz}");
assert!((lead.unwrap() - Unit::Ha.to_pt(20.0)).abs() < 1e-9, "{lead:?}");
assert!((sz - 17.0 * 72.0 / 101.6).abs() < 1e-9);
}
+13 -3
View File
@@ -3,9 +3,10 @@
//! General (rulers, positions, sizes, dialog distances, canvas readouts) is the active document's
//! units, so they travel with the file: Document Setup (`document.setUnits`) changes them, and
//! Preferences ▸ Units ▸ General changes them too and is also the units new documents start in (and
//! the unit shown while no document is open). Stroke (weights, dashes) and Type (sizes, leading,
//! baseline shift) are application preferences. Typed values with a unit ("5 mm", "12 pt") work in
//! any unit.
//! the unit shown while no document is open). Stroke (weights, dashes), Type (sizes, leading,
//! baseline shift) and East Asian Type (the only
//! preference that offers Q and Ha, and no field reads it yet) are application preferences. Typed values with a unit
//! ("5 mm", "12 pt", "13 Q") work in any unit.
use vectorcraft_doc::Unit;
@@ -17,6 +18,7 @@ pub enum Measure {
General,
Stroke,
Type,
AsianType,
}
impl Measure {
@@ -26,6 +28,7 @@ impl Measure {
Measure::General => "general",
Measure::Stroke => "stroke",
Measure::Type => "type",
Measure::AsianType => "asianType",
}
}
@@ -35,6 +38,7 @@ impl Measure {
Measure::General => "unitsGeneral",
Measure::Stroke => "unitsStroke",
Measure::Type => "unitsType",
Measure::AsianType => "unitsAsianType",
}
}
}
@@ -51,6 +55,7 @@ impl Session {
Measure::General => self.active().map_or_else(|| self.default_units(), |d| d.doc.units),
Measure::Stroke => pref_unit(&self.prefs.units_stroke),
Measure::Type => pref_unit(&self.prefs.units_type),
Measure::AsianType => Unit::named_east_asian(&self.prefs.units_asian_type).unwrap_or_default(),
}
}
@@ -64,6 +69,11 @@ impl Session {
self.unit(Measure::Type)
}
/// Units ▸ East Asian Type: no field shows in it yet.
pub fn east_asian_type_unit(&self) -> Unit {
self.unit(Measure::AsianType)
}
/// Preferences ▸ Units ▸ General: the units new documents start in.
pub fn default_units(&self) -> Unit {
pref_unit(&self.prefs.units_general)
+3
View File
@@ -6091,6 +6091,9 @@ breakText Glyphs Глифи
Small to Large От малко към голямо
Large to Small От голямо към малко
Distribute Evenly Равномерно разпределение
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Създаване на легенда на образците
Create Swatch Legend… Създаване на легенда на образците…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6122,6 +6122,9 @@ shape Open Otvoren
Small to Large Od manjeg prema većem
Large to Small Od većeg prema manjem
Distribute Evenly Rasporedi ravnomjerno
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Kreiraj legendu uzoraka boja
Create Swatch Legend… Kreiraj legendu uzoraka boja…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6216,6 +6216,9 @@ breakText Glyphs Glifs
Small to Large De petit a gran
Large to Small De gran a petit
Distribute Evenly Distribueix uniformement
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Crea una llegenda de mostres
Create Swatch Legend… Crea una llegenda de mostres…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6228,6 +6228,9 @@ breakText Glyphs Glyfy
Small to Large Od nejmenšího po největší
Large to Small Od největšího po nejmenší
Distribute Evenly Rozmístit rovnoměrně
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Vytvořit legendu vzorníku
Create Swatch Legend… Vytvořit legendu vzorníku…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6106,6 +6106,9 @@ breakText Glyphs Glyffer
Small to Large Fra lille til stor
Large to Small Fra stor til lille
Distribute Evenly Fordel jævnt
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Opret farveprøveforklaring
Create Swatch Legend… Opret farveprøveforklaring…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -5814,6 +5814,9 @@ breakText Glyphs Glyphen
Small to Large Von klein nach groß
Large to Small Von groß nach klein
Distribute Evenly Gleichmäßig verteilen
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Farbfeldlegende erstellen
Create Swatch Legend… Farbfeldlegende erstellen…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6180,6 +6180,9 @@ breakText Glyphs Γλύφοι
Small to Large Από μικρό σε μεγάλο
Large to Small Από μεγάλο σε μικρό
Distribute Evenly Ομοιόμορφη κατανομή
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Δημιουργία υπομνήματος δειγμάτων χρωμάτων
Create Swatch Legend… Δημιουργία υπομνήματος δειγμάτων χρωμάτων…
HEX HEX
Can't render this file because it contains an unexpected character in line 163 and column 5.
+3
View File
@@ -6170,6 +6170,9 @@ breakText Glyphs Glifos
Small to Large De menor a mayor
Large to Small De mayor a menor
Distribute Evenly Distribuir uniformemente
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Crear leyenda de muestras
Create Swatch Legend… Crear leyenda de muestras…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6258,6 +6258,9 @@ breakText Glyphs Merkit
Small to Large Pienestä suureen
Large to Small Suuresta pieneen
Distribute Evenly Jaa tasaisesti
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Luo värimallien selite
Create Swatch Legend… Luo värimallien selite…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6223,6 +6223,9 @@ breakText Glyphs Glyphes
Small to Large Du plus petit au plus grand
Large to Small Du plus grand au plus petit
Distribute Evenly Répartir uniformément
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Créer une légende des nuances
Create Swatch Legend… Créer une légende des nuances…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6212,6 +6212,9 @@ breakText Glyphs Glifák
Small to Large Kicsitől a nagyig
Large to Small Nagytól a kicsiig
Distribute Evenly Egyenletes elosztás
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Színmintajelmagyarázat létrehozása
Create Swatch Legend… Színmintajelmagyarázat létrehozása…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6106,6 +6106,9 @@ breakText Glyphs Glif
Small to Large Kecil ke besar
Large to Small Besar ke kecil
Distribute Evenly Distribusikan merata
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Buat Legenda Swatch
Create Swatch Legend… Buat Legenda Swatch…
HEX HEX
Can't render this file because it contains an unexpected character in line 2206 and column 5.
+3
View File
@@ -5848,6 +5848,9 @@ breakText Glyphs Glifi
Small to Large Dal più piccolo al più grande
Large to Small Dal più grande al più piccolo
Distribute Evenly Distribuisci uniformemente
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Crea legenda campioni
Create Swatch Legend… Crea legenda campioni…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -5913,6 +5913,9 @@ breakText Glyphs 字形
Small to Large 小さい順
Large to Small 大きい順
Distribute Evenly 均等に分布
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend スウォッチの凡例を作成
Create Swatch Legend… スウォッチの凡例を作成…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6216,6 +6216,9 @@ breakText Glyphs გლიფები
Small to Large პატარიდან დიდისკენ
Large to Small დიდიდან პატარისკენ
Distribute Evenly თანაბრად განაწილება
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend ფერის ნიმუშების ლეგენდის შექმნა
Create Swatch Legend… ფერის ნიმუშების ლეგენდის შექმნა…
HEX HEX
Can't render this file because it is too large.
+3
View File
@@ -5809,6 +5809,9 @@ breakText Glyphs 글리프
Small to Large 작은 것부터
Large to Small 큰 것부터
Distribute Evenly 균등 분포
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend 견본 범례 만들기
Create Swatch Legend… 견본 범례 만들기…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6150,6 +6150,9 @@ breakText Glyphs Glyphs
Small to Large Van klein naar groot
Large to Small Van groot naar klein
Distribute Evenly Gelijkmatig verdelen
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Stalenlegenda maken
Create Swatch Legend… Stalenlegenda maken…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6083,6 +6083,9 @@ breakText Glyphs Glify
Small to Large Od najmniejszego do największego
Large to Small Od największego do najmniejszego
Distribute Evenly Rozmieść równomiernie
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Utwórz legendę próbek
Create Swatch Legend… Utwórz legendę próbek…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6301,6 +6301,9 @@ swatch Yellow Green Verde-amarelado
Small to Large Do menor para o maior
Large to Small Do maior para o menor
Distribute Evenly Distribuir uniformemente
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Criar Legenda de Amostras
Create Swatch Legend… Criar Legenda de Amostras…
HEX HEX
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -6205,6 +6205,9 @@ breakText Glyphs Глифы
Small to Large От меньшего к большему
Large to Small От большего к меньшему
Distribute Evenly Распределить равномерно
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Создать легенду образцов
Create Swatch Legend… Создать легенду образцов…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -6280,6 +6280,9 @@ breakText Glyphs Glyfer
Small to Large Från liten till stor
Large to Small Från stor till liten
Distribute Evenly Fördela jämnt
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Skapa färgrutelegend
Create Swatch Legend… Skapa färgrutelegend…
HEX HEX
Can't render this file because it contains an unexpected character in line 5 and column 25.
+3
View File
@@ -6185,6 +6185,9 @@ breakText Glyphs Glifler
Small to Large Küçükten Büyüğe
Large to Small Büyükten Küçüğe
Distribute Evenly Eşit Dağıt
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Renk Örneği Açıklaması Oluştur
Create Swatch Legend… Renk Örneği Açıklaması Oluştur…
HEX HEX
Can't render this file because it contains an unexpected character in line 5 and column 25.
+3
View File
@@ -5828,6 +5828,9 @@ breakText Glyphs Гліфи
Small to Large Від меншого до більшого
Large to Small Від більшого до меншого
Distribute Evenly Розподілити рівномірно
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Створити легенду зразків
Create Swatch Legend… Створити легенду зразків…
HEX HEX
Can't render this file because it contains an unexpected character in line 177 and column 5.
+3
View File
@@ -5829,6 +5829,9 @@ breakText Glyphs Glyph
Small to Large Từ nhỏ đến lớn
Large to Small Từ lớn đến nhỏ
Distribute Evenly Phân bố đều
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend Tạo chú giải mẫu màu
Create Swatch Legend… Tạo chú giải mẫu màu…
HEX HEX
Can't render this file because it contains an unexpected character in line 199 and column 5.
+3
View File
@@ -6069,6 +6069,9 @@ breakText Glyphs 字形
Small to Large 从小到大
Large to Small 从大到小
Distribute Evenly 均匀分布
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend 创建色板图例
Create Swatch Legend… 创建色板图例…
HEX HEX
Can't render this file because it contains an unexpected character in line 2 and column 73.
+3
View File
@@ -5866,6 +5866,9 @@ breakText Glyphs 字符
Small to Large 從小到大
Large to Small 從大到小
Distribute Evenly 均勻分佈
# Preferences > Units > East Asian Type: Q and Ha, the Japanese typesetting units (a quarter of a millimetre each), named the same in every language.
Q Q
Ha Ha
Create Swatch Legend 建立色票圖例
Create Swatch Legend… 建立色票圖例…
HEX HEX
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1 -1
View File
@@ -23,7 +23,7 @@ pub fn weight_presets(unit: Unit) -> [f64; 22] {
Unit::Inches => IN_PRESETS,
Unit::Pixels => PX_PRESETS,
Unit::Picas => return PC_PRESETS,
Unit::Points | Unit::FeetInches | Unit::Feet | Unit::Meters | Unit::Yards => return PT_PRESETS,
Unit::Points | Unit::FeetInches | Unit::Feet | Unit::Meters | Unit::Yards | Unit::Q | Unit::Ha => return PT_PRESETS,
};
native.map(|v| unit.to_pt(v))
}
+25 -10
View File
@@ -1,6 +1,6 @@
# Gaps
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-01 · **Change:** minor (G5: dynamic symbols, #4938; estimate 15–26 → 14–24 h) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (G5: dynamic symbols, #4938; estimate 15–26 → 14–24 h) · **Target:** Adobe Illustrator 2026 (30.x; G12: Units › East Asian Type acts, with Q and Ha units; estimate unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
## Feature submission evidence
@@ -402,18 +402,32 @@ from G14 and the budget run of G15: **~170–270 h** one agent, ~50–80 h wall
- **Done (2026-10-21, #394):** General › Constrain Angle turns the arrow keys' axes (guides stay on the page's), holds Shift drags of the Selection, Direct Selection, Free Transform, Slice Selection, Reshape and Measure tools and the Pen's handles to the turned axes, and new rectangles, rounded rectangles, ellipses, grids, point and area type, Shift-drawn polygons and stars and the shape size dialogs are drawn along it with their bounding box turned; 0° and whole turns are exactly as before, quarter turns exact (<https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rotate-objects-by-specific-angles.html>). Arcs, spirals, flares and the Pen's new paths are not turned yet. Estimate unchanged. **2026-10-24:** General › Corner Radius is the Rounded Rectangle tool's radius: the tool takes the preference when chosen and when it changes while the tool is active (or lent a selection tool for a drag), and the radius ↑/↓ set while drawing one, or a Tool Options value, becomes the preference, clamped to its 0–1296 pt range (<https://helpx.adobe.com/illustrator/using/drawing-simple-lines-shapes.html>). Estimate unchanged.
- **Done (2026-10-17):** Background Export shows its progress in a dialog with Cancel and Continue in Background (#2564), on the shared cancel token (#2546); a cancelled export writes no file. Save As, Export for Screens and Export Selection don't show it yet. Estimate unchanged.
- **Done:** quick Image Trace presets trace at once and leave the panel as it was; the Image Trace button (Control bar, Properties) opens the controls with Threshold and Advanced (Paths, Corners, Noise), as the public documentation describes (<https://helpx.adobe.com/illustrator/using/image-trace-results-optimization.html>). Other context-specific Properties gaps remain.
- **Audited (2026-10-30, #394):** every Preferences dialog option but the five below is read by shipped code, by
its field or its key; Highlight Alternate Glyphs (the canvas's render options), Real-time Drawing and Editing
- **Done (2026-10-31, #394):** Units › East Asian Type is read, and Q and Ha are units. 1 Q and 1 Ha are each a
quarter of a millimetre (0.709 pt), the Japanese typesetting units: the [Illustrator Scripting Guide's
Measurement Units table](https://ai-scripting.docsforadobe.dev/scripting/measurementUnits/) gives 0.709 pt per Q
(its "0.23 millimeter" is a slip: 0.709 pt is 0.25 mm, [the metric quart](https://en.wikipedia.org/wiki/Metric_typographic_units)),
[InDesign's unit notation table](https://helpx.adobe.com/in/indesign/desktop/layout-and-grid-tools/rulers-and-measure-tools/change-ruler-measurement-units.html)
lists `q` and `h` as the Q and Ha suffixes a field takes, and Ha is the same length as Q, used for spacing
instead of type size ([Toshi Omagari on Q and Ha](https://tosche.net/jp/blog/font-size-in-the-metric-system)). The
public pages do not say which fields follow East Asian Type, so no field uses it yet (that waits for a source). It offers Points,
Picas, Inches, Millimeters, Centimeters, Pixels, Feet & Inches, Meters, Yards, Feet, Q and Ha (`unitsAsianType`,
Points by default); only
it lists Q and Ha, not the rulers, Document Setup or
the other Units preferences. The model stays in points; any length field reads `13q` or `13h` (`Ha`, `H`) with or
without a space. Not done: no field shows in it (it waits for a source). Tests `east_asian_*` and `q_and_ha_*` in
`crates/doc` and `crates/engine`. Estimate unchanged.
- **Audited (2026-10-30, #394):** every Preferences dialog option but the four below is read by shipped code,
by its field or its key; Highlight Alternate Glyphs (the canvas's render options), Real-time Drawing and Editing
(tool previews wait for the commit), Show Tool Tips, Anti-aliased Artwork, Use Precise Cursors and Devices ›
Enable Touch Workspace and Touch Gestures included.
- **Missing:** 5 Preferences options stored but not acted on (#394), each waiting on a subsystem of its own:
- **Missing:** 4 Preferences options stored but not acted on (#394), each waiting on a subsystem of its own:
User Interface › Open Documents As Tabs (off would open documents in floating windows; one window per
document is G7), Units › East Asian Type (nothing is measured in it yet, and the Q and Ha units aren't in the
unit lists), Hyphenation › Default Language (hyphenation is English-only, with no per-language dictionaries),
Plug-ins & Scratch Disks › Primary and Secondary (documents are kept in memory; nothing pages to disk), and
Clipboard Handling › Legacy vector clipboard with its Preserve Paths / Preserve Appearance and Overprints choice
(Illustrator's own clipboard flavour, which has no public specification). Also Properties panel per
context, context menus beyond the canvas, Layers panel row menus and Collect for Export, SVG Interactivity.
document is G7), Hyphenation › Default Language (hyphenation is English-only, with no per-language
dictionaries), Plug-ins & Scratch Disks › Primary and Secondary (documents are kept in memory; nothing pages to
disk), and Clipboard Handling › Legacy vector clipboard with its Preserve Paths / Preserve Appearance and
Overprints choice (Illustrator's own clipboard flavour, which has no public specification). Also Properties
panel per context, context menus beyond the canvas, Layers panel row menus and Collect for Export, SVG
Interactivity.
- **Impact:** settings that silently do nothing erode trust.
- **Estimate:** 13–20 h.
@@ -689,6 +703,7 @@ trap, and the defaults (0.25 pt, 100%, 40%) are VectorCraft's own, the pages giv
| Date | Change | Summary |
|---|---|---|
| 2026-10-31 | minor | G12: Units › East Asian Type acts (#394): Q and Ha (a quarter of a millimetre each) are units that preference offers; 4 Preferences options remain stored but not acted on. Estimate unchanged. |
| 2026-11-01 | minor | G5: dynamic symbols (#4938): Symbol Options › Symbol Type, per-instance fill, stroke, opacity and blend for objects of a dynamic symbol's art that stay linked (redefining keeps them, Break Link bakes them, Reset and Static drop them; `symbol.instance.setAppearance`, `symbol.instance.reset`; `crates/engine/src/tests/dynamic_symbols.rs`); on-canvas Direct Selection of the parts and `.ai` round trip remain. Estimate 15–26 → 14–24 h. |
| 2026-11-01 | minor | G13: Artboard background colors in output (#4937): raster exports (a transparent background too), PDF, SVG and EPS pages, `.ai` files' PDF pages, Export for Screens and print (and its preview) draw each artboard's color behind its art, inside the artboard and in the color's own model; Export for Screens has Include Artboard Fill beside Include Bleed (on by default, remembered; `includeArtboardFill`, also on `document.export` and `file.print`); editing data keeps the color as the artboard's, and Export for Screens' document rows keep it too; estimate unchanged. |
| 2026-11-01 | minor | G5: Select › Start Global Edit on a group takes the groups like it (the same objects at the same places, moved or scaled; Appearance, Size and the artboard options apply) and gives an edit made to an object inside one to the object at its place in each of the others, in proportion, as one undo step (#4939); rotated copies and Shift-click exclusion remain. Estimate unchanged. |
+8 -3
View File
@@ -3540,11 +3540,16 @@ Commands take and return lengths in points (the distances of `object.path.offset
string takes the same arithmetic as the desktop app's fields, where `%` is a share of the value before it:
`"200mm*50%"` is 100 mm and `"50pt+25%"` is 62.5 pt. The units
only change what the UI shows and how it reads typed numbers. Preferences ▸ Units has
three: General (rulers, positions and sizes, the Info panel, dialog distances, canvas measurement labels), Stroke
(weights, dashes) and Type (font size, leading, baseline shift). General is the active document's units
four: General (rulers, positions and sizes, the Info panel, dialog distances, canvas measurement labels), Stroke
(weights, dashes), Type (font size, leading, baseline shift) and East Asian Type (no field uses it yet). General is the active document's units
(`document.inspect` → `units`): `document.setUnits {units}` (Document Setup) sets it for that document, and
`prefs.set {key: "unitsGeneral", value}` sets it for the active document too (one undo step) and is the units
`file.new` starts in when it gets no `units`. Stroke and Type are the preferences `unitsStroke` and `unitsType`.
`file.new` starts in when it gets no `units`. Stroke, Type and East Asian Type are the preferences `unitsStroke`,
`unitsType` and `unitsAsianType`. Only `unitsAsianType` also takes `q` (Q, `Q`) and `ha` (Ha, `Ha`), each a quarter of
a millimetre (0.709 pt); the other preferences, `document.setUnits` and the rulers do not list them, and it is Points
by default. A length typed with a unit
reads `13q` or `13h` (also `13 Q`, `13Ha`) in any field or string param (`text.setStyle {size: "13 Q"}`): the value
is stored in points.
`document.switchUnits` (Cmd/Ctrl+Alt+Shift+U) sets the active document's units to the next unit in the order a
right-click on a ruler lists them (Points, Picas, Inches, Millimeters, Centimeters, Pixels, Feet & Inches, Meters,
Yards, Feet, then Points again), in one undo step, and replies `{units}`.
File diff suppressed because one or more lines are too long
+4 -1
View File
@@ -1,6 +1,6 @@
# Type parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-01 · **Change:** minor (Glyphs panel: the character selected with the Type tool is highlighted and scrolled into view, #4908; previously minor: Serbian in Cyrillic and Latin and Croatian among the languages, with their quote marks; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (Glyphs panel: the character selected with the Type tool is highlighted and scrolled into view, #4908; previously minor: Serbian in Cyrillic and Latin and Croatian among the languages, with their quote marks; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units (#394); scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
Type is Illustrator's largest single area by use (weight 13 of 105 across "Type core" and "Type advanced" in
[target-app-parity.md](target-app-parity.md)). This checklist lists the features one by one. Status is from the
@@ -58,6 +58,8 @@ against Illustrator's public documentation; **estimated** unless noted.
| CJK: input methods (marked text, candidate window) | done | |
| CJK: kinsoku (Hard, Soft, None), Line-end Punctuation Half Width, tate-chu-yoko (auto) | done / partial | custom kinsoku sets, the Mojikumi Settings dialog and the other mojikumi sets missing |
| CJK: Proportional Metrics (`palt` in horizontal type, `vpal` in vertical type) | done | #966 |
| CJK: manual tate-chu-yoko | done | Character panel menu › Tate-chu-yoko (`text.setFormat` / `text.setRangeStyle {tateChuYoko}`), with Show East Asian Options: marked characters stand side by side across one em of a vertical column, squeezed to the em when wider; two or three half-width digits still do so without the mark; horizontal type keeps the mark and does not move them. Up/Down and Left/Right settings remain. Evidence: `tests_vertical::manual_tate_chu_yoko_sets_marked_characters_across_one_em`, `typecmd::tate_chu_yoko_is_a_character_attribute_saved_only_when_on` |
| CJK: East Asian Type units (Q, Ha) | done | Preferences › Units › East Asian Type (`unitsAsianType`, Points by default) offers every unit and Q and Ha, a quarter of a millimetre each ([Scripting Guide](https://ai-scripting.docsforadobe.dev/scripting/measurementUnits/): 0.709 pt per Q; [InDesign's unit notation](https://helpx.adobe.com/in/indesign/desktop/layout-and-grid-tools/rulers-and-measure-tools/change-ruler-measurement-units.html): `q`, `h`). The public pages do not say which fields follow it, so no field uses it yet and that waits for a source. Evidence: `q_and_ha_are_a_quarter_millimetre`, `east_asian_type_unit_*` |
| CJK: manual tate-chu-yoko | done | Character panel menu › Tate-chu-yoko (`text.setFormat` / `text.setRangeStyle {tateChuYoko}`), with Show East Asian Options: marked characters stand side by side across one em of a vertical column, squeezed to the em when wider; two or three half-width digits still do so without the mark; horizontal type keeps the mark and does not move them. Tate-chu-yoko Settings… (`ui.tateChuYokoSettings`, `{tcyUpDown, tcyLeftRight}` in points) moves a marked block up or down and right or left as one piece. Evidence: `tests_vertical::manual_tate_chu_yoko_sets_marked_characters_across_one_em`, `tests_vertical::tate_chu_yoko_settings_move_a_marked_block_up_down_left_and_right`, `typecmd::tate_chu_yoko_is_a_character_attribute_saved_only_when_on`, `typecmd::tate_chu_yoko_settings_are_character_attributes_saved_only_when_set`, `dialogs::tate_chu_yoko::tests` |
| CJK: Standard Vertical Roman Alignment | done | Character panel menu › Standard Vertical Roman Alignment (`text.setFormat` / `text.setRangeStyle {standardVerticalRoman}`), with Show East Asian Options, off by default: in vertical type the marked half-width characters (Latin letters, digits and other characters that would lie on their side) stand upright one below the other, each in its upright cell; spaces keep their width and tate-chu-yoko blocks stay across the column; horizontal type keeps the mark and does not change. Character Style Options has its own checkbox for it. Evidence: `tests_vertical::standard_vertical_roman_alignment_stands_half_width_characters_upright`, `typecmd::standard_vertical_roman_is_a_character_attribute_saved_only_when_on` |
| CJK: ruby, manual tate-chu-yoko | partial | ruby (ふりがな) for live text (`type.ruby`): a reading over a byte range, above (right of the column in vertical type) or below, start/centre/end alignment, size, overhang or squeeze; saved natively, laid out with its line growing, drawn on the canvas, in SVG and PDF (as outlines where ruby is present), in EPS, EMF/WMF and legacy `.ai` (legacy `.ai` writes type with ruby as outlines), and kept by Create Outlines, Expand Appearance and flattening, each glyph where the layout puts it (`typecmd::ruby_tests::create_outlines_keeps_the_ruby_where_it_is_laid_out`); manual tate-chu-yoko missing | #633 |
@@ -73,6 +75,7 @@ Character Styles menu New/Redefine and footer New capture the first selected cha
| Date | Change | Summary |
|---|---|---|
| 2026-10-31 | minor | Units › East Asian Type acts (#394): Q and Ha (a quarter of a millimetre each) are units that preference offers; scores unchanged |
| 2026-11-01 | minor | Glyphs panel (#4908): the character selected with the Type tool (a range's first, else the one before the caret) is highlighted in the grid and scrolled into view when the selection moves to another character; Show › Alternates for Current Selection not yet; scores unchanged |
| 2026-11-01 | minor | Serbian: Cyrillic (`sr-Cyrl`), Serbian: Latin (`sr-Latn`) and Croatian (`hr`) in the language list, with their quote marks (Serbian „…” and ’…’ per the Pravopis srpskoga jezika, Matica srpska 2010, ISBN 978-86-7946-079-0, т. 168, and [CLDR `sr`](https://github.com/unicode-org/cldr/blob/main/common/main/sr.xml); Croatian „…“ and ‚…‘ per [CLDR `hr`](https://github.com/unicode-org/cldr/blob/main/common/main/hr.xml)); Serbian text gets the fonts' Serbian forms (italic б, г, д, п, т); scores unchanged |
| 2026-11-01 | minor | Area Type Options › Text Flow (#4978): By Rows / By Columns radio buttons and `text.areaOptions {flow}`; area type with several rows and columns fills them across each row first or down each column first (the default, so existing documents are unchanged; saved only when by rows); scores unchanged |
+4 -2
View File
@@ -1,6 +1,6 @@
# UI and interaction parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-01 · **Change:** minor (Color Effects add-on: Find Nearest Swatch, #4923) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (Color Effects add-on: Find Nearest Swatch, #4923) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x)
## Feature submission evidence
@@ -200,6 +200,7 @@ tools, never checked side by side) isn't captured row by row.
| Arithmetic in fields (`+ - * /`, and `%` of the value before it: `3cm*50%`, `50pt+25%`) and unit suffixes (`3 mm`, `1in`, `2p6`) | done | `Unit::parse`; mixed units in one expression not verified |
| Numeric fields: focus click selects the whole value; dragging selects from the pressed character | partial | #1326; select-all waits for click release; px/pt/plain/optional fields, both directions and replacement text tested; native API input, 17 px partial replacement, Undo/Redo, saved-file round trip and screenshots verified; Tab, double-click, arrows and wheel preserved; short movements still classified as clicks can select all and remain open |
| Units: pt, pc, in, mm, cm, px, ft-in, m, yd, ft; General/Stroke/Type units | done | units preference reverting to points on SVG output reported (#864) |
| Units › East Asian Type (Q and Ha) | done | #394: `unitsAsianType` offers every unit and Q and Ha, a quarter of a millimetre each ([Scripting Guide's Measurement Units](https://ai-scripting.docsforadobe.dev/scripting/measurementUnits/): 0.709 pt per Q; [InDesign's unit notation](https://helpx.adobe.com/in/indesign/desktop/layout-and-grid-tools/rulers-and-measure-tools/change-ruler-measurement-units.html): `q`, `h`); only it lists Q and Ha. The public pages do not say which fields use it, so no field uses it yet and that waits for a source. Tests `q_and_ha_are_a_quarter_millimetre`, `east_asian_type_unit_*` |
| Field precision: 3 decimals for steps; values kept as f64 | done | |
| Scrubby labels (beyond Illustrator) | done | #400 |
| 3D Lighting Color picker, preview, reset dot and Reset all | initial | One to ten opaque RGB lights for Revolve, Extrude & Bevel, Inflate and Rotate; select, add or delete a light and edit its settings or gizmo; Standard, Diffuse, Top Left and Right select original rigs, with Custom for manual changes; Cancel restores all lights |
@@ -333,7 +334,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
| Swatch, graphic style and symbol library panels: each library opens in a panel of its own, several at once, that floats, groups, docks and closes like any panel; opening an open library brings its panel forward; Previous / Next Library change the library in place; the panel menu's Persistent reopens the panel at startup with its view and find field (a library loaded from a file is read again; when its file is missing the panel reopens showing the file's path with Locate Library…, and the status bar names the file) | done | #2603; panel ids `library:<kind>:<id>`, `ui.libraryPanel {panel, library?, view?, showFind?, persistent?}`, `ui.libraryPanel.locate {panel, path?}`; the library panels have no sort option, as before |
| DXF export/import preserves intended curve closure | done | #1299; R13–2018 closed SPLINE bit set/read; an open curve ending at its start stays open; knots and control points unchanged; native CIRCLE/ARC export and CNC preset remain pending |
| macOS save sheet: choose the format from a menu | done | #866; the save panel is VectorCraft's own `NSSavePanel` with its Format menu set before the sheet opens (`apps/vectorcraft/src/mac_save_format.rs`); #1855 had withdrawn the menu that was added after the sheet began, which made Save As, Save a Copy and the first Save show no sheet |
| Preferences: every option acts | partial | 5 stored but unused (#394, audited 2026-10-30): Open Documents As Tabs, Units › East Asian Type, Hyphenation › Default Language, Scratch Disks, Legacy vector clipboard; the rest act. General › Corner Radius drives the Rounded Rectangle tool and follows its ↑/↓ (2026-10-24) |
| Preferences: every option acts | partial | 4 stored but unused (#394, audited 2026-10-30): Open Documents As Tabs, Hyphenation › Default Language, Scratch Disks, Legacy vector clipboard; the rest act (Units › East Asian Type since 2026-10-31). General › Corner Radius drives the Rounded Rectangle tool and follows its ↑/↓ (2026-10-24) |
| Preferences › General › Constrain Angle | done | arrow keys and Shift drags along the turned axes; the Rectangle, Rounded Rectangle, Ellipse and grid tools, point and area type and the shape size dialogs draw along them with the bounding box turned; Shift-drawn polygons and stars keep the turned base orientation; the Line Segment tool's Shift steps count from it (#394, <https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rotate-objects-by-specific-angles.html>); arcs, spirals, flares and Pen paths are not turned |
| Tabs panel: a stop drags from where the press landed, a stop just added included | done | #1458 |
| Outline view keeps template layers in Preview, dimmed | done | #1486; a picture placed to be traced stays visible under the outlines |
@@ -399,6 +400,7 @@ separate. Scores and hours unchanged. [Behavior and command details](development
| Date | Change | Summary |
|---|---|---|
| 2026-10-31 | minor | Units › East Asian Type acts (#394): Q and Ha (a quarter of a millimetre each) are units that preference offers; 4 Preferences options remain stored but unused; scores and estimates unchanged |
| 2026-11-01 | minor | Color Effects add-on (a VectorCraft addition): Find Nearest Swatch (#4923); scores and estimates unchanged |
| 2026-11-01 | minor | Artboards panel: a row dragged above or below another reorders the artboards (#4687); scores and estimates unchanged |
| 2026-11-01 | minor | Object › Plug-ins › Color Effects › Create Swatch Legend…: a dialog that draws labelled chips of the colour swatches (all, or the ones selected in the Swatches panel) as one group (#4919); scores and estimates unchanged |