mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 09:59:47 -06:00
Units: Preferences › East Asian Type reads, with Q and Ha units (#394)
Squashed from #4845 onto main.
This commit is contained in:
committed by
bflatastic
parent
15a5e64134
commit
1b5d11ef4b
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user