Fix #4940: text is shaped in its language

Characters get a language (CharStyle::language, a BCP 47 tag of one of
Document Setup's languages; none for the default, English: USA, saved
only when set). The shaper sets it on the HarfRust buffer, so fonts use
their language forms (OpenType locl): Turkish keeps fi apart and the dot
on its i. Runs in different languages are shaped apart. New type takes
the document's language.
This commit is contained in:
bflatastic
2026-11-01 01:39:11 +07:00
parent 14c4616202
commit a85487ad39
8 changed files with 120 additions and 28 deletions
+4 -1
View File
@@ -811,7 +811,8 @@ pub(crate) fn new_area_fit(s: &Session, p: &Value, c: &str) -> Result<vectorcraf
/// The character style new type gets: `size`, `font`, `style` and `color` from `p` (an RGB
/// `color` in a CMYK document as [`super::paint::new_color`] stores it), else the defaults,
/// filled with the current fill unless that is None or white (black then).
/// filled with the current fill unless that is None or white (black then), in the document's
/// language.
pub(crate) fn new_type_style(s: &Session, p: &Value) -> CharStyle {
let mut style = CharStyle::default();
if let Some(sz) = p.get("size").and_then(Value::as_f64) {
@@ -831,5 +832,7 @@ pub(crate) fn new_type_style(s: &Session, p: &Value) -> CharStyle {
None if !s.paint.fill.is_none() && s.paint.fill != vectorcraft_color::Paint::solid(vectorcraft_color::Color::WHITE) => s.paint.fill.clone(),
None => vectorcraft_color::Paint::solid(vectorcraft_color::Color::BLACK),
};
// In the document's language (Document Setup), none for the default.
style.language = s.doc().ok().and_then(|d| vectorcraft_doc::setup::char_language(&d.doc.setup.language).ok().flatten()).map(str::to_string);
style
}
+2 -2
View File
@@ -127,8 +127,8 @@ fn apply(s: &mut DocSetup, units: &mut vectorcraft_doc::Unit, k: &str, v: &Value
"discardWhiteOverprint" => s.discard_white_overprint = flag(k, v)?,
"language" => {
let l = v.as_str().unwrap_or("");
let (name, quotes) = LANGUAGES.iter().find(|(n, _)| n.eq_ignore_ascii_case(l)).ok_or_else(|| {
bad(C, format!("unknown language `{l}` (one of {})", LANGUAGES.iter().map(|(n, _)| *n).collect::<Vec<_>>().join(", ")))
let (name, _, quotes) = LANGUAGES.iter().find(|(n, _, _)| n.eq_ignore_ascii_case(l)).ok_or_else(|| {
bad(C, format!("unknown language `{l}` (one of {})", LANGUAGES.iter().map(|(n, _, _)| *n).collect::<Vec<_>>().join(", ")))
})?;
s.language = name.to_string();
s.quotes = *quotes;