diff --git a/crates/doc/src/text.rs b/crates/doc/src/text.rs index d2abfed9..24d7e088 100644 --- a/crates/doc/src/text.rs +++ b/crates/doc/src/text.rs @@ -253,10 +253,17 @@ pub struct TextStyle { pub style_id: Option, } +/// The font new text starts in. A build can name another (`FIGCRAFT_DEFAULT_FONT="Noto Sans Thai"`, +/// for a distribution whose users mostly write a script Inter lacks); empty means Inter. +pub const DEFAULT_FONT: &str = match option_env!("FIGCRAFT_DEFAULT_FONT") { + Some(family) if !family.is_empty() => family, + _ => "Inter", +}; + impl Default for TextStyle { fn default() -> Self { Self { - font_family: "Inter".into(), + font_family: DEFAULT_FONT.into(), font_style: "Regular".into(), font_size: 12.0, line_height: LineHeight::Auto, @@ -790,6 +797,18 @@ mod case_tests { assert!(!valid_feature_tag("lig") && !valid_feature_tag("ligatures") && !valid_feature_tag("li\u{e9}")); } + #[test] + fn new_text_starts_in_the_builds_default_font() { + // Inter, unless the build names another with `FIGCRAFT_DEFAULT_FONT` (empty means Inter). + let named = option_env!("FIGCRAFT_DEFAULT_FONT").filter(|f| !f.is_empty()); + assert_eq!(DEFAULT_FONT, named.unwrap_or("Inter")); + let st = TextStyle::default(); + assert_eq!(st.font_family, DEFAULT_FONT); + // The family is always written, so a saved file keeps it in a build with another default. + let saved = serde_json::to_value(&st).unwrap(); + assert_eq!(saved["font_family"], DEFAULT_FONT); + } + #[test] fn variations_are_backward_compatible_and_imply_weight() { // Files written before variable fonts load with no custom axes, and stay byte-identical. diff --git a/crates/engine/src/text_behaviour_tests.rs b/crates/engine/src/text_behaviour_tests.rs index f15817e8..92a43306 100644 --- a/crates/engine/src/text_behaviour_tests.rs +++ b/crates/engine/src/text_behaviour_tests.rs @@ -288,3 +288,25 @@ fn a_drag_with_the_text_tool_makes_a_fixed_size_box() { let (b3, _) = text_tool((100.0, 100.0), (180.0, 101.0), "A"); assert_eq!((b3.width(), b3.height()), (80.0, line.height())); } + +#[test] +fn new_text_starts_in_the_builds_default_font() { + // `text.create` without a fontFamily and a click with the Text tool both start in + // `figcraft_doc::DEFAULT_FONT` (Inter, unless the build names another with + // `FIGCRAFT_DEFAULT_FONT`), and the family is written with the text. + use crate::tools::{PointerEvent, PointerKind, ToolId}; + let mut s = Session::new(); + let made = text(&mut s, "Text", json!({})); + s.set_tool(ToolId::Text); + s.pointer(&PointerEvent::at(PointerKind::Down, 300.0, 300.0, 1.0)).unwrap(); + s.pointer(&PointerEvent::at(PointerKind::Up, 300.0, 300.0, 1.0)).unwrap(); + crate::textedit::insert(&mut s, "Tool").unwrap(); + let typed = s.ds().unwrap().text_edit.as_ref().unwrap().id; + assert_ne!(made, typed); + let doc = s.doc().unwrap(); + for t in [made, typed] { + let td = doc.node(t).unwrap().kind.text().unwrap(); + assert_eq!(td.style.font_family, figcraft_doc::DEFAULT_FONT); + assert_eq!(serde_json::to_value(td).unwrap()["style"]["font_family"], figcraft_doc::DEFAULT_FONT); + } +} diff --git a/docs/releasing.md b/docs/releasing.md index 3dbc0fbf..8ad7e614 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -68,6 +68,22 @@ FIGCRAFT_DEFAULT_SERVER=wss://design.example.org/ cargo build --release -p figcr The release workflow leaves it unset. The public server's terms are in [`online-sharing-terms.md`](online-sharing-terms.md). +## The default font + +New text starts in Inter (`figcraft_doc::DEFAULT_FONT`). A distribution whose users mostly write a +script Inter lacks (Thai, say) can name another family with `FIGCRAFT_DEFAULT_FONT` when building; +unset or empty means Inter. Pick a family the build embeds from craft-fonts (the web build has no +other fonts) or one its users have installed: + +```sh +FIGCRAFT_DEFAULT_FONT="Noto Sans Thai" cargo build --release -p figcraft +``` + +Files record each text's family, so the variable only changes what new text starts in: a file +saved by one build keeps its fonts in a build with another default. Like any other family, it +renders only where it is available (embedded or installed); elsewhere the text falls back to the +faces that are. The release workflow leaves it unset. + ## What gets built | Platform | Artifacts | Built on |