Place: Word's low, medium and high kashida justification sets Insert Kashidas

A Word paragraph justified with w:jc lowKashida, mediumKashida or
highKashida placed as plain justified type, and its kashida length was
dropped. ECMA-376 Part 1, 17.18.44 (ST_Jc) gives these values a
slightly longer, a medium and the widest kashida length.

Such a paragraph now places justified with Insert Kashidas set to
Short, Medium or Long. A paragraph justified with both, and every other
alignment, still places with Insert Kashidas set to None. VectorCraft
writes no Word or RTF files, so this change does not affect export.

Docs: docs/mcp.md, docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-10-21 23:32:26 +07:00
committed by bflatastic
parent 3884cf9704
commit 7d58ce4f9d
4 changed files with 60 additions and 7 deletions
+14 -6
View File
@@ -19,7 +19,9 @@
//! the color.
//! - Paragraph formatting: alignment (`w:jc`), start and end indents (`w:start` or `w:left`,
//! `w:end` or `w:right`: the right and left indents of a right-to-left paragraph), first-line and
//! hanging indents, space before and after, and direction (`w:bidi`).
//! hanging indents, space before and after, and direction (`w:bidi`). A paragraph justified with
//! a low, medium or high kashida length (`lowKashida`, `mediumKashida`, `highKashida`) is
//! justified with Short, Medium or Long kashidas; `both` is justified without kashidas.
//! - Styles (§17.7.2): the document defaults, then the paragraph style (else the default paragraph
//! style) and the styles it is based on, then the run's character style (else the default
//! character style) and the styles it is based on, then direct formatting. Bold, italic, caps,
@@ -37,6 +39,7 @@
use std::collections::HashMap;
use roxmltree::Node;
use vectorcraft_doc::text::Kashida;
use vectorcraft_doc::{CharPosition, CharStyle, Justify, ParaDirection, ParaStyle, ScriptMetrics, TextRun};
use super::text::{self, Story};
@@ -361,8 +364,9 @@ enum Align {
Left,
Center,
Right,
/// Justified, the last line at the start (the right of a right-to-left paragraph).
Both,
/// Justified, the last line at the start (the right of a right-to-left paragraph), with the
/// kashida length of `lowKashida`, `mediumKashida` and `highKashida` (§17.18.44).
Both(Kashida),
/// Justified, the last line too.
Distribute,
Start,
@@ -860,8 +864,8 @@ impl Reader {
Align::Left => Justify::Left,
Align::Center => Justify::Center,
Align::Right => Justify::Right,
Align::Both if rtl => Justify::JustifyRight,
Align::Both => Justify::JustifyLeft,
Align::Both(_) if rtl => Justify::JustifyRight,
Align::Both(_) => Justify::JustifyLeft,
Align::Distribute => Justify::JustifyAll,
Align::Start => Justify::Auto,
Align::End if rtl => Justify::Left,
@@ -873,6 +877,7 @@ impl Reader {
space_before: points(p.before),
space_after: points(p.after),
direction: p.rtl.map(|rtl| if rtl { ParaDirection::RightToLeft } else { ParaDirection::LeftToRight }),
kashida: if let Align::Both(k) = p.align { k } else { Kashida::None },
..ParaStyle::default()
}
})
@@ -898,7 +903,10 @@ fn para_props(ppr: Node) -> ParaProps {
Some("left") => Some(Align::Left),
Some("center") => Some(Align::Center),
Some("right") => Some(Align::Right),
Some("both" | "lowKashida" | "mediumKashida" | "highKashida") => Some(Align::Both),
Some("both") => Some(Align::Both(Kashida::None)),
Some("lowKashida") => Some(Align::Both(Kashida::Short)),
Some("mediumKashida") => Some(Align::Both(Kashida::Medium)),
Some("highKashida") => Some(Align::Both(Kashida::Long)),
Some("distribute" | "thaiDistribute") => Some(Align::Distribute),
Some("start") => Some(Align::Start),
Some("end") => Some(Align::End),