mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 21:27:00 -06:00
Character Alignment: on a character range too, with the East Asian options (review of #389)
text.setRangeStyle takes charAlign, so the panel menu works on the characters selected with the Type tool (it routes there while text is edited, and charAlign alone was answered with "nothing to change"). One char_align_param parses it for both commands. The menu shows with Preferences › Type › Show East Asian Options, like Mojikumi Set and Top-to-Top Leading. Rows in the Simplified Chinese, Spanish and Brazilian Portuguese catalogs; the Japanese Em Box Center names the em box. ROADMAP: the gating, the range command, and ICF top/bottom still missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
178ca03eba
commit
18cbe007b8
+2
-2
@@ -129,7 +129,7 @@ grade by behaviour against `plan/illustrator/`, not by whether a menu item exist
|
||||
- Pathfinder (10 exact curve booleans), Offset, Outline Stroke, Simplify, Clean Up, Split Into Grid, Divide Objects Below. Object › Path › Remove Anchor Points (`path.removeAnchors`) removes the direct-selected anchors without opening their paths (the Delete key still deletes them with their segments): the neighbours keep their handle directions and their facing handles are refitted so one cubic follows the two old segments, and straight sides stay straight. The Delete Anchor Point tool uses the same refit. The Control bar, the contextual task bar, the Properties quick actions and the canvas context menu offer it when anchors are selected.
|
||||
- Live effects with previewing dialogs: Distort & Transform, Path, Convert to Shape, 15 Warp styles, Round Corners, Scribble, Effect → Pathfinder (all 10 operations, live on groups; several loose objects are grouped first, in one undo step), Color Adjustments (Brightness/Contrast, Curves, Levels, Hue/Saturation, Shift to Color, Temperature/Tint, on vectors, live type and embedded images), and raster drop shadow, glows and feather. SVG and PDF export keep live effects (geometry baked; SVG raster effects as filters).
|
||||
- **Type:** Text Wrap, Type on a Path effects (Rainbow/Skew/3D Ribbon/Stair Step/Gravity), Character and Paragraph Styles (override-preserving redefine), Area Type Options (rows/columns/inset/first baseline), threaded text across any closed shapes, Fit Headline. Area type resizes like Illustrator's type areas: a bounding-box handle drag (Selection tool) or Area Type Options Width/Height size the frame and the text reflows at its size (threads too); Direct Selection drags a frame corner or edge (`text.reshapeArea`). Point type still scales. Variable fonts list every named instance as a style of their family (Figtree Light to Black and their italics, Bahnschrift, Segoe UI Variable), and the instance chosen is shaped, drawn, outlined and measured at its axis settings; PDF and SVG embed it as that instance. Variation axis sliders are not done. Hebrew and Arabic are laid out right to left with the Unicode bidirectional algorithm (embedded Latin and numbers keep their direction, lines put in visual order after wrapping) in point, area and path type, with caret, selection and arrow keys in visual order; each paragraph's direction comes from its first strong character unless Paragraph Direction sets it (Paragraph panel with Show Indic Options, `text.setFormat {direction}`), and new type aligns to the start of its direction. SVG export outlines right-to-left text.
|
||||
- **Interface languages, vertical type:** VectorCraft ▸ Language (or Preferences ▸ User Interface) picks Automatic (the system locale) or a registered language, persisted as `interfaceLanguage`. Translations come from per-language catalogs (`i18n/*.tsv`): Traditional and Simplified Chinese, Japanese and Spanish (neutral international Spanish, for every `es-*` locale) cover the whole interface, Czech and Brazilian Portuguese every menu label, Brazilian Portuguese the shell's `tl!` literals too (tested); untranslated text stays English. Japanese and Chinese glyphs come from the craft-fonts build input (release builds) or the installed fonts, Czech and Spanish ones from the bundled UI fonts. The Basic toolbar's Type button holds Vertical Type in its flyout. Vertical Type, Vertical Area Type and Vertical Type on a Path create vertical text (columns right to left, upright CJK glyphs and marks with `vert` alternates, Latin and longer numbers on their side, two- and three-digit numbers set as tate-chu-yoko in one em of the column (kept whole when justified), upright glyphs centred on the column (tracked or justified too), point type's anchor on the first column's centre line); kinsoku (the strict set) applies to horizontal and vertical Japanese, and justified Japanese lines spread their room between characters (not inside Latin words); Paragraph panel › Mojikumi Set (shown with Preferences › Type › Show East Asian Options, `text.setFormat {mojikumi}`): None or Line-end Punctuation Half Width (new type's default, as in Illustrator; older documents and imported text keep None) shares one half-em space between consecutive punctuation, sets a closing mark ending a line half width, and puts a quarter em between Japanese and Latin letters or digits; Paragraph panel menu › Top-to-Top / Bottom-to-Bottom Leading measures leading from em box top to top (area type's first line touches the frame) or from baseline to baseline; Character panel menu › Character Alignment lines characters smaller than the largest on their line up on the Roman baseline or the em box top/right, centre or bottom/left; Type ▸ Type Orientation switches existing text; caret, selection, hit testing and arrow keys follow the writing direction. Vertical text exports to PDF as real text and to SVG as outlines.
|
||||
- **Interface languages, vertical type:** VectorCraft ▸ Language (or Preferences ▸ User Interface) picks Automatic (the system locale) or a registered language, persisted as `interfaceLanguage`. Translations come from per-language catalogs (`i18n/*.tsv`): Traditional and Simplified Chinese, Japanese and Spanish (neutral international Spanish, for every `es-*` locale) cover the whole interface, Czech and Brazilian Portuguese every menu label, Brazilian Portuguese the shell's `tl!` literals too (tested); untranslated text stays English. Japanese and Chinese glyphs come from the craft-fonts build input (release builds) or the installed fonts, Czech and Spanish ones from the bundled UI fonts. The Basic toolbar's Type button holds Vertical Type in its flyout. Vertical Type, Vertical Area Type and Vertical Type on a Path create vertical text (columns right to left, upright CJK glyphs and marks with `vert` alternates, Latin and longer numbers on their side, two- and three-digit numbers set as tate-chu-yoko in one em of the column (kept whole when justified), upright glyphs centred on the column (tracked or justified too), point type's anchor on the first column's centre line); kinsoku (the strict set) applies to horizontal and vertical Japanese, and justified Japanese lines spread their room between characters (not inside Latin words); Paragraph panel › Mojikumi Set (shown with Preferences › Type › Show East Asian Options, `text.setFormat {mojikumi}`): None or Line-end Punctuation Half Width (new type's default, as in Illustrator; older documents and imported text keep None) shares one half-em space between consecutive punctuation, sets a closing mark ending a line half width, and puts a quarter em between Japanese and Latin letters or digits; Paragraph panel menu › Top-to-Top / Bottom-to-Bottom Leading measures leading from em box top to top (area type's first line touches the frame) or from baseline to baseline; Character panel menu › Character Alignment (with the East Asian options; `text.setFormat` or `text.setRangeStyle {charAlign}`) lines characters smaller than the largest on their line up on the Roman baseline or the em box top/right, centre or bottom/left (ICF top and bottom not yet); Type ▸ Type Orientation switches existing text; caret, selection, hit testing and arrow keys follow the writing direction. Vertical text exports to PDF as real text and to SVG as outlines.
|
||||
- **Transparency:** opacity masks (clip/invert/disable/link), exported as SVG `<mask>` and PDF soft masks.
|
||||
- **Advanced art:** live Blends (steps/distance/smooth colour, editable spine, anchor-targeted Blend tool, faithful interpolation, knockout), Envelope Distort (warp/mesh/top object, Reset, full Envelope Options, mesh handles, Edit Contents; type, images, symbols, gradients, patterns and appearance distorted everywhere), Liquify tools with options and pen pressure, Puppet Warp with rotating pins, Perspective Grid with presets, movable planes and projected type (choosing a perspective tool shows the grid; Hide Grid hides it with the tool still chosen), Gradient Mesh, Shape Builder (stroke-only open paths and lines cut the regions they cross and enclose regions of their own; Alt deletes their pieces; filled open paths count as closed), Live Paint (every path an edge, open lines included), Image Trace (12 presets), pattern swatches with pattern editing mode, live Repeat (radial/grid/mirror).
|
||||
- **Paint and appearance (M3):**
|
||||
@@ -200,7 +200,7 @@ about 1–1.5 agent-hours each, so the other rows (estimated on the older scale)
|
||||
| Raster effects (Effect Gallery, Document Raster Effects Settings) | 4 | 20% | ~55 Photoshop-style filters (Artistic, Brush Strokes, Distort, Pixelate, Sketch, Stylize, Texture, Video) and the Effect Gallery; Document Raster Effects Settings and raster effects in PDF are done | 28–42 |
|
||||
| 3D and Materials | 4 | 0% | Extrude & Bevel, Revolve, Inflate, Rotate, lighting, materials (software renderer) | 50–80 |
|
||||
| Type core | 9 | 79% | Middle Eastern features beyond bidi layout and Paragraph Direction (Character Direction, digit types, kashidas, the Middle Eastern composers, editable bidirectional SVG text, a split caret where directions meet); composer/hyphenation options, Optical Margin Alignment, hidden characters, Transform Again after a type-area resize (it scales the type), partial selection of type-area anchors by marquee | 15–20 |
|
||||
| Type advanced | 4 | 50% | CJK composition for vertical type (ruby, mojikumi beyond Line-end Punctuation Half Width — hanging punctuation, line-start brackets, kinsoku sets and the Mojikumi Settings dialog —, proportional vertical metrics, manual tate-chu-yoko), variable font axis sliders (named instances are styles), tab leaders, spell check (open dictionary), Touch Type, Retype; vertical point/area/path type and Type Orientation have initial support | 20–28 |
|
||||
| Type advanced | 4 | 50% | CJK composition for vertical type (ruby, mojikumi beyond Line-end Punctuation Half Width — hanging punctuation, line-start brackets, kinsoku sets and the Mojikumi Settings dialog —, proportional vertical metrics, manual tate-chu-yoko, Character Alignment on the ICF top and bottom), variable font axis sliders (named instances are styles), tab leaders, spell check (open dictionary), Touch Type, Retype; vertical point/area/path type and Type Orientation have initial support | 20–28 |
|
||||
| Symbols, blends, envelopes, Repeat, perspective | 5 | 88% | symbol libraries (original), dynamic symbols, envelope Anti-Alias/Preserve Shape output and warp point editing, brush interpolation in blends (M8 fidelity pass done) | 5–8 |
|
||||
| Image Trace, graphs, image tools | 3 | 70% | graph Design/Column/Marker, Create Object Mosaic, Crop Image polish (Vector Halftone is done) | 6–10 |
|
||||
| Layers, artboards, document setup | 5 | 82% | Layers panel: a confirmation before deleting layers that hold art, Collect for Export, row context menus, the Layer Options dialog for several rows with mixed values, Paste Remembers Layers for sublayers, drag-scrolling a long panel while dragging rows; artboard presets/rearrange polish (Document Setup, New Document and the rest of the Layers panel are done) | 4–7 |
|
||||
|
||||
@@ -120,16 +120,7 @@ fn set_format(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
return Err(bad(C, "nothing to change"));
|
||||
}
|
||||
let (position, small_caps) = super::docsetup::script_params(p, &s.doc()?.doc.setup, C)?;
|
||||
let char_align = match p.get("charAlign") {
|
||||
None => None,
|
||||
Some(v) => Some(match v.as_str() {
|
||||
Some("romanBaseline") => vectorcraft_doc::CharAlign::RomanBaseline,
|
||||
Some("emBoxTop") => vectorcraft_doc::CharAlign::EmBoxTop,
|
||||
Some("emBoxCenter") => vectorcraft_doc::CharAlign::EmBoxCenter,
|
||||
Some("emBoxBottom") => vectorcraft_doc::CharAlign::EmBoxBottom,
|
||||
_ => return Err(bad(C, "`charAlign` must be \"romanBaseline\", \"emBoxTop\", \"emBoxCenter\" or \"emBoxBottom\"")),
|
||||
}),
|
||||
};
|
||||
let char_align = super::textedit::char_align_param(p, C)?;
|
||||
let mojikumi = match p.get("mojikumi") {
|
||||
None => None,
|
||||
Some(v) => Some(match v.as_str() {
|
||||
|
||||
@@ -27,7 +27,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Character",
|
||||
[],
|
||||
None,
|
||||
"{id, start?: byte, end?: byte (default: all text), font?, style?, size?: pt, leading?: pt|\"auto\", tracking?, kerning?: 1/1000 em|\"auto\", baselineShift?: pt, hScale?: %, vScale?: %, rotation?: deg, fill?: colour|\"none\", stroke?: colour|\"none\", strokeWidth?: pt, strokeOptions?: {weight?, cap?, join?, miterLimit?, dash?, dashOffset?, alignDashes?} (as stroke.set: the character stroke), underline?, strikethrough?, allCaps?: bool, smallCaps?: bool, position?: \"normal\"|\"superscript\"|\"subscript\" (sizes from Document Setup), features?: [\"dlig\", \"-liga\", …]} style a character range (runs are split at the range ends) → {id, runs}",
|
||||
"{id, start?: byte, end?: byte (default: all text), font?, style?, size?: pt, leading?: pt|\"auto\", tracking?, kerning?: 1/1000 em|\"auto\", baselineShift?: pt, hScale?: %, vScale?: %, rotation?: deg, fill?: colour|\"none\", stroke?: colour|\"none\", strokeWidth?: pt, strokeOptions?: {weight?, cap?, join?, miterLimit?, dash?, dashOffset?, alignDashes?} (as stroke.set: the character stroke), underline?, strikethrough?, allCaps?: bool, smallCaps?: bool, position?: \"normal\"|\"superscript\"|\"subscript\" (sizes from Document Setup), features?: [\"dlig\", \"-liga\", …], charAlign?: \"romanBaseline\"|\"emBoxTop\"|\"emBoxCenter\"|\"emBoxBottom\"} style a character range (runs are split at the range ends) → {id, runs}",
|
||||
has_doc,
|
||||
set_range_style
|
||||
),
|
||||
@@ -151,6 +151,7 @@ pub(crate) struct CharChange {
|
||||
features: Option<Vec<String>>,
|
||||
position: Option<vectorcraft_doc::CharPosition>,
|
||||
small_caps: Option<Option<f64>>,
|
||||
char_align: Option<vectorcraft_doc::CharAlign>,
|
||||
}
|
||||
|
||||
/// `features: ["dlig", "-liga", …]` → the canonical tag list (differences from the defaults).
|
||||
@@ -163,6 +164,19 @@ pub(crate) fn features_param(p: &Value, cmd: &str) -> Result<Option<Vec<String>>
|
||||
Ok(Some(vectorcraft_text::OtFeatures::default().with_tags(tags).to_tags()))
|
||||
}
|
||||
|
||||
/// `charAlign: "romanBaseline"|"emBoxTop"|"emBoxCenter"|"emBoxBottom"` (Character Alignment).
|
||||
pub(crate) fn char_align_param(p: &Value, cmd: &str) -> Result<Option<vectorcraft_doc::CharAlign>> {
|
||||
use vectorcraft_doc::CharAlign;
|
||||
let Some(v) = p.get("charAlign").filter(|v| !v.is_null()) else { return Ok(None) };
|
||||
Ok(Some(match v.as_str() {
|
||||
Some("romanBaseline") => CharAlign::RomanBaseline,
|
||||
Some("emBoxTop") => CharAlign::EmBoxTop,
|
||||
Some("emBoxCenter") => CharAlign::EmBoxCenter,
|
||||
Some("emBoxBottom") => CharAlign::EmBoxBottom,
|
||||
_ => return Err(bad(cmd, "`charAlign` must be \"romanBaseline\", \"emBoxTop\", \"emBoxCenter\" or \"emBoxBottom\"")),
|
||||
}))
|
||||
}
|
||||
|
||||
fn paint_param(p: &Value, k: &str, cmd: &str) -> Result<Option<Paint>> {
|
||||
match p.get(k) {
|
||||
None | Some(Value::Null) => Ok(None),
|
||||
@@ -213,6 +227,7 @@ impl CharChange {
|
||||
features: features_param(p, cmd)?,
|
||||
position,
|
||||
small_caps,
|
||||
char_align: char_align_param(p, cmd)?,
|
||||
};
|
||||
if c.size.is_some_and(|v| v <= 0.0) {
|
||||
return Err(bad(cmd, "size must be positive"));
|
||||
@@ -240,6 +255,7 @@ impl CharChange {
|
||||
&& self.features.is_none()
|
||||
&& self.position.is_none()
|
||||
&& self.small_caps.is_none()
|
||||
&& self.char_align.is_none()
|
||||
}
|
||||
|
||||
pub(crate) fn apply(&self, st: &mut CharStyle) {
|
||||
@@ -310,6 +326,9 @@ impl CharChange {
|
||||
if let Some(v) = self.small_caps {
|
||||
st.small_caps = v;
|
||||
}
|
||||
if let Some(v) = self.char_align {
|
||||
st.char_align = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -452,6 +452,11 @@ mod area_tests {
|
||||
assert_eq!(serde_json::to_value(&runs(&s)[0].style).unwrap()["charAlign"], "emBoxCenter");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(runs(&s)[0].style.char_align, CharAlign::RomanBaseline);
|
||||
// Characters selected with the Type tool: only the range takes it (雅 is 3 bytes).
|
||||
assert!(s.execute("text.setRangeStyle", &json!({"id": id, "start": 3, "end": 6, "charAlign": "top"})).is_err());
|
||||
s.execute("text.setRangeStyle", &json!({"id": id, "start": 3, "end": 6, "charAlign": "emBoxTop"})).unwrap();
|
||||
let aligns: Vec<_> = runs(&s).iter().map(|r| (r.text.clone(), r.style.char_align)).collect();
|
||||
assert_eq!(aligns, [("雅".to_string(), CharAlign::RomanBaseline), ("楽".to_string(), CharAlign::EmBoxTop)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -299,6 +299,7 @@
|
||||
Changing these settings changes how raster effects look when exported, flattened or expanded. Cambiar estos ajustes modifica el aspecto de los efectos ráster al exportar, acoplar o expandir.
|
||||
Channel Canal
|
||||
Character Carácter
|
||||
Character Alignment Alineación de caracteres
|
||||
Character / Paragraph Carácter / Párrafo
|
||||
Character Rotation Rotación de caracteres
|
||||
Character Set: Juego de caracteres:
|
||||
@@ -752,6 +753,9 @@
|
||||
Ellipse Tool Herramienta Elipse
|
||||
Ellipse… Elipse…
|
||||
Ellipsis Puntos suspensivos
|
||||
Em Box Bottom/Left Abajo/izquierda del cuadro eme
|
||||
Em Box Center Centro del cuadro eme
|
||||
Em Box Top/Right Arriba/derecha del cuadro eme
|
||||
Em Dash Raya
|
||||
Em Space Espacio eme
|
||||
Embed Incrustar
|
||||
@@ -2081,6 +2085,7 @@
|
||||
Right-to-Left Paragraph Direction Dirección de párrafo de derecha a izquierda
|
||||
Right: Derecha:
|
||||
Rise… Ascenso…
|
||||
Roman Baseline Línea de base latina
|
||||
Roman Hanging Punctuation Puntuación colgante romana
|
||||
Rotate Rotar
|
||||
Rotate 90° CW Rotar 90° en sentido horario
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -15,7 +15,7 @@
|
||||
Character Alignment 文字揃え
|
||||
Decorative 装飾
|
||||
Em Box Bottom/Left 仮想ボディの下 / 左
|
||||
Em Box Center 中央
|
||||
Em Box Center 仮想ボディの中央
|
||||
Em Box Top/Right 仮想ボディの上 / 右
|
||||
Favorites お気に入り
|
||||
Japanese 日本語
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -336,6 +336,7 @@
|
||||
Changing these settings changes how raster effects look when exported, flattened or expanded. Alterar estas configurações muda a aparência dos efeitos de raster ao exportar, achatar ou expandir.
|
||||
Channel Canal
|
||||
Character Caractere
|
||||
Character Alignment Alinhamento de Caracteres
|
||||
Character / Paragraph Caractere / Parágrafo
|
||||
Character Rotation Rotação de Caractere
|
||||
Character Set: Conjunto de Caracteres:
|
||||
@@ -721,6 +722,9 @@
|
||||
Ellipse Tool Ferramenta Elipse
|
||||
Ellipse… Elipse…
|
||||
Ellipsis Reticências
|
||||
Em Box Bottom/Left Base/Esquerda da Caixa Eme
|
||||
Em Box Center Centro da Caixa Eme
|
||||
Em Box Top/Right Topo/Direita da Caixa Eme
|
||||
Em Dash Travessão
|
||||
Em Space Espaço Em
|
||||
Embed Incorporar
|
||||
@@ -1873,6 +1877,7 @@
|
||||
Right Plane Plano Direito
|
||||
Right: Direita:
|
||||
Rise… Rise…
|
||||
Roman Baseline Linha de Base Romana
|
||||
Roman Hanging Punctuation Pontuação Pendurada Romana
|
||||
Rotate Girar
|
||||
Rotate Tool Ferramenta Girar
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -302,6 +302,7 @@
|
||||
Changing these settings changes how raster effects look when exported, flattened or expanded. 更改这些设置会改变栅格效果在导出、拼合或扩展时的外观。
|
||||
Channel 色版
|
||||
Character 字符
|
||||
Character Alignment 字符对齐
|
||||
Character / Paragraph 字符/段落
|
||||
Character Rotation 字符旋转
|
||||
Character Set: 字符集:
|
||||
@@ -747,6 +748,9 @@
|
||||
Ellipse Tool 椭圆工具
|
||||
Ellipse… 椭圆形…
|
||||
Ellipsis 删节号
|
||||
Em Box Bottom/Left 全角字框下 / 左
|
||||
Em Box Center 全角字框居中
|
||||
Em Box Top/Right 全角字框上 / 右
|
||||
Em Dash 长破折号
|
||||
Em Space 全角空格
|
||||
Embed 嵌入
|
||||
@@ -2053,6 +2057,7 @@
|
||||
Right-Justified Tab 右对齐制表位
|
||||
Right: 右:
|
||||
Rise… 上升…
|
||||
Roman Baseline 罗马基线
|
||||
Roman Hanging Punctuation 西文悬挂标点
|
||||
Rotate 旋转
|
||||
Rotate 90° CW 顺时针旋转 90°
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -395,24 +395,28 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
menu_item(ui, tl!(l), false, false);
|
||||
}
|
||||
ui.separator();
|
||||
// Character Alignment: where characters smaller than the largest on their line line up.
|
||||
let align = s.as_ref().map(|s| s.char_align);
|
||||
ui.add_enabled_ui(has, |ui| {
|
||||
ui.menu_button(tl!("Character Alignment"), |ui| {
|
||||
use vectorcraft_doc::CharAlign;
|
||||
for (label, a, key) in [
|
||||
(tl!("Roman Baseline"), CharAlign::RomanBaseline, "romanBaseline"),
|
||||
(tl!("Em Box Top/Right"), CharAlign::EmBoxTop, "emBoxTop"),
|
||||
(tl!("Em Box Center"), CharAlign::EmBoxCenter, "emBoxCenter"),
|
||||
(tl!("Em Box Bottom/Left"), CharAlign::EmBoxBottom, "emBoxBottom"),
|
||||
] {
|
||||
if menu_item(ui, label, true, align == Some(a)) {
|
||||
format(app, json!({"charAlign": key}));
|
||||
// Character Alignment: where characters smaller than the largest on their line line up, with
|
||||
// the East Asian options.
|
||||
if app.session.prefs.show_east_asian_options {
|
||||
let align = s.as_ref().map(|s| s.char_align);
|
||||
ui.add_enabled_ui(has, |ui| {
|
||||
// Indented like the items beside it (their check column).
|
||||
ui.menu_button(format!(" {}", tl!("Character Alignment")), |ui| {
|
||||
use vectorcraft_doc::CharAlign;
|
||||
for (label, a, key) in [
|
||||
(tl!("Roman Baseline"), CharAlign::RomanBaseline, "romanBaseline"),
|
||||
(tl!("Em Box Top/Right"), CharAlign::EmBoxTop, "emBoxTop"),
|
||||
(tl!("Em Box Center"), CharAlign::EmBoxCenter, "emBoxCenter"),
|
||||
(tl!("Em Box Bottom/Left"), CharAlign::EmBoxBottom, "emBoxBottom"),
|
||||
] {
|
||||
if menu_item(ui, label, true, align == Some(a)) {
|
||||
format(app, json!({"charAlign": key}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
ui.separator();
|
||||
ui.separator();
|
||||
}
|
||||
for l in ["Standard Vertical Roman Alignment", "Tate-chu-yoko", "Fractional Widths", "System Layout", "No Break"] {
|
||||
menu_item(ui, tl!(l), false, l == "Fractional Widths");
|
||||
}
|
||||
@@ -432,3 +436,23 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use vectorcraft_engine::Session;
|
||||
|
||||
/// Character Alignment is in the panel menu with the East Asian options only (as Mojikumi Set
|
||||
/// and Top-to-Top Leading are in the Paragraph panel).
|
||||
#[test]
|
||||
fn character_alignment_shows_with_the_east_asian_options() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 300, "height": 200})).unwrap();
|
||||
let id = app.session.execute("text.create", &json!({"x": 20, "y": 50, "text": "雅楽"})).unwrap()["id"].clone();
|
||||
app.session.execute("select.set", &json!({"ids": [id]})).unwrap();
|
||||
let shown = |app: &mut VectorcraftApp| crate::tests_labels::painted_text(app, menu).contains("Character Alignment");
|
||||
assert!(!shown(&mut app));
|
||||
app.session.prefs.show_east_asian_options = true;
|
||||
assert!(shown(&mut app));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user