mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 21:44:57 +00:00
Merge pull request #7564 from dotCooCoo/fix/svg-direction-any-case
SVG import: direction keywords match in any letter case
This commit is contained in:
@@ -965,6 +965,12 @@ impl Ctx {
|
||||
"normal".into()
|
||||
}
|
||||
|
||||
/// Whether the computed `direction` of element `n` is `rtl`, in any letter case (CSS keywords
|
||||
/// are ASCII case-insensitive, https://www.w3.org/TR/css-values-3/#keywords).
|
||||
fn is_rtl(&self, n: XNode) -> bool {
|
||||
self.prop(n, "direction").is_some_and(|d| d.trim().eq_ignore_ascii_case("rtl"))
|
||||
}
|
||||
|
||||
/// The Character Direction of the characters of element `n` inside a `<text>`, and what it
|
||||
/// leaves out (SVG 1.1 §10.7.4,
|
||||
/// https://www.w3.org/TR/SVG11/text.html#RelationshipWithBi-directionality, and CSS Writing
|
||||
@@ -987,7 +993,7 @@ impl Ctx {
|
||||
let inherited = parent.as_ref().and_then(|p| p.style.char_direction);
|
||||
let mut notes = parent.map_or_else(Vec::new, |p| p.bidi_notes.clone());
|
||||
let rtl = |rtl: bool| Some(if rtl { ParaDirection::RightToLeft } else { ParaDirection::LeftToRight });
|
||||
let own = || rtl(self.prop(n, "direction").is_some_and(|d| d.trim() == "rtl"));
|
||||
let own = || rtl(self.is_rtl(n));
|
||||
let (dir, note) = match bidi.as_str() {
|
||||
"embed" => (own(), None),
|
||||
"bidi-override" => (own(), Some(BIDI_OVERRIDE)),
|
||||
@@ -1376,7 +1382,7 @@ impl Ctx {
|
||||
// With `unicode-bidi: plaintext`, the text runs in the direction of its first strong
|
||||
// character, and each paragraph in that of its own ([`pin_first_strong`]).
|
||||
let plaintext = self.unicode_bidi(t) == "plaintext";
|
||||
let rtl = if plaintext { self.first_strong_rtl(t) == Some(true) } else { self.prop(t, "direction").is_some_and(|d| d.trim() == "rtl") };
|
||||
let rtl = if plaintext { self.first_strong_rtl(t) == Some(true) } else { self.is_rtl(t) };
|
||||
let pin = |obj: &mut TextObject| {
|
||||
pin_direction(obj, rtl);
|
||||
if plaintext {
|
||||
@@ -1403,7 +1409,7 @@ impl Ctx {
|
||||
let chunk: String = cs.chars[i..end].iter().map(|c| c.0).collect();
|
||||
text_first_strong_rtl(&chunk) == Some(true)
|
||||
};
|
||||
let rtl = if plaintext { chunk_rtl() } else { self.prop(el, "direction").is_some_and(|d| d.trim() == "rtl") };
|
||||
let rtl = if plaintext { chunk_rtl() } else { self.is_rtl(el) };
|
||||
if !vertical && rtl { 1.0 - a } else { a }
|
||||
};
|
||||
let anchor = anchor_of(0);
|
||||
|
||||
@@ -469,6 +469,9 @@ fn rtl_point_text_start_and_end_use_directional_edges() {
|
||||
(r#"<text x="200" y="60" direction="rtl" font-size="20"><tspan direction="ltr">Wave</tspan></text>"#, 0.0),
|
||||
(r#"<text x="200" y="60" text-anchor="start" font-size="20">Wave</text>"#, 0.0),
|
||||
(r#"<text x="200" y="60" direction="ltr" text-anchor="end" font-size="20">Wave</text>"#, 1.0),
|
||||
// CSS keywords are case-insensitive.
|
||||
(r#"<text x="200" y="60" direction="RTL" font-size="20">Wave</text>"#, 1.0),
|
||||
(r#"<text x="200" y="60" style="direction: Rtl" text-anchor="end" font-size="20">Wave</text>"#, 0.0),
|
||||
// With `unicode-bidi: plaintext`, the direction of the chunk's first strong character.
|
||||
(r#"<text x="200" y="60" unicode-bidi="plaintext" font-size="20">אבג</text>"#, 1.0),
|
||||
(r#"<text x="200" y="60" unicode-bidi="plaintext" text-anchor="end" font-size="20">12 אב</text>"#, 0.0),
|
||||
@@ -572,6 +575,8 @@ fn a_tspan_bidi_embedding_becomes_its_character_direction() {
|
||||
("ltr", "rtl", "normal", None, false),
|
||||
("rtl", "ltr", "normal", None, false),
|
||||
("ltr", "rtl", "EMBED", Some(Rtl), false),
|
||||
("ltr", "RTL", "embed", Some(Rtl), false),
|
||||
("RTL", "ltr", "embed", Some(Ltr), false),
|
||||
("ltr", "rtl", "sideways", None, false),
|
||||
] {
|
||||
let (t, w) = read(&format!(
|
||||
@@ -581,7 +586,7 @@ fn a_tspan_bidi_embedding_becomes_its_character_direction() {
|
||||
assert_eq!(t.plain_text(), "ab 1 2 cd", "{case}: the characters stay in logical order");
|
||||
assert_eq!(char_direction_of(&t, "1 2"), want, "{case}: {:?}", t.runs);
|
||||
assert_eq!(char_direction_of(&t, "ab"), None, "{case}");
|
||||
assert_eq!(t.para_at(0).direction == Some(Rtl), outer == "rtl", "{case}: the paragraph keeps the text's direction");
|
||||
assert_eq!(t.para_at(0).direction == Some(Rtl), outer.eq_ignore_ascii_case("rtl"), "{case}: the paragraph keeps the text's direction");
|
||||
assert_eq!(w.iter().any(|w| w.contains("bidi-override") && w.contains("not supported")), warns, "{case}: {w:?}");
|
||||
if !warns {
|
||||
assert!(w.is_empty(), "{case}: {w:?}");
|
||||
|
||||
Reference in New Issue
Block a user