From 230b201d54994abd5b35b928a30f99ec653c7fc0 Mon Sep 17 00:00:00 2001 From: yorubad-dev Date: Wed, 15 Jan 2025 05:16:18 +0100 Subject: [PATCH 1/5] handle whitespacing collapse *handle collapse newline, space and tab *check bidi properties for whitespace implementation *complete test check for true and false template Part-of: --- rsvg/src/text.rs | 2 +- rsvg/src/text2.rs | 52 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/rsvg/src/text.rs b/rsvg/src/text.rs index ecf524347..b40d56bea 100644 --- a/rsvg/src/text.rs +++ b/rsvg/src/text.rs @@ -1152,7 +1152,7 @@ impl From for pango::Gravity { /// Constants with Unicode's directional formatting characters /// /// -mod directional_formatting_characters { +pub mod directional_formatting_characters { /// Left-to-Right Embedding /// /// Treat the following text as embedded left-to-right. diff --git a/rsvg/src/text2.rs b/rsvg/src/text2.rs index 1e1b9fe72..cac7ced7b 100644 --- a/rsvg/src/text2.rs +++ b/rsvg/src/text2.rs @@ -4,6 +4,7 @@ use rctree::NodeEdge; use crate::element::{Element, ElementData, ElementTrait}; use crate::node::{Node, NodeData}; +use crate::properties::WhiteSpace; use crate::text::BidiControl; #[allow(dead_code)] @@ -22,9 +23,7 @@ struct Character { // y: f64, // angle: Angle, // hidden: bool, - addressable: bool, - // middle: bool, // anchored_chunk: bool, } @@ -36,11 +35,48 @@ struct Character { // A xx B xx C "xx" are bidi control characters // addressable: ttfffttffft -fn collapse_white_space(input: &str, white_space: WhiteSpace) -> Vec:: { - // HOMEWORK - unimplemented!() +// HOMEWORK +#[allow(unused)] +fn collapse_white_space(input: &str, white_space: WhiteSpace) -> Vec { + match white_space { + WhiteSpace::Normal => collapse_white_space_normal(input), + _ => unimplemented!(), + } } +fn is_bidi_control(ch: char) -> bool { + use crate::text::directional_formatting_characters::*; + ch == LRE || ch == RLE || ch == LRO || ch == RLO || ch == PDF +} + +fn collapse_white_space_normal(input: &str) -> Vec { + let mut result: Vec = Vec::new(); + let mut prev_was_space: bool = false; + // let mut character = Character::default(); + + for ch in input.chars() { + if is_bidi_control(ch) { + result.push(Character { addressable: false }); + continue; + } + + let is_space = ch == ' ' || ch == '\t' || ch == '\n'; + + if is_space { + if prev_was_space { + result.push(Character { addressable: false }); + } else { + result.push(Character { addressable: true }); + prev_was_space = true; + } + } else { + result.push(Character { addressable: true }); + prev_was_space = false; + } + } + + result +} fn get_bidi_control(element: &Element) -> BidiControl { // Extract bidi control logic to separate function to avoid duplication @@ -184,8 +220,13 @@ mod tests { // Takes a string made of 't' and 'f' characters, and compares it // to the `addressable` field of the Characters slice. fn check_true_false_template(template: &str, characters: &[Character]) { + assert_eq!(characters.len(), template.len()); + // HOMEWORK // it's a loop with assert_eq!(characters[i].addressable, ...); + for (i, ch) in template.chars().enumerate() { + assert_eq!(characters[i].addressable, ch == 't'); + } } #[rustfmt::skip] @@ -211,5 +252,4 @@ mod tests { let expected = "ttffttfft"; check_true_false_template(expected, &result); } - } -- GitLab From 31cf2c96b27b7fe4bbe791cc6bf8e757aefe00f4 Mon Sep 17 00:00:00 2001 From: yorubad-dev Date: Wed, 15 Jan 2025 05:50:02 +0100 Subject: [PATCH 2/5] refactor collapse_white_space_normal to simplify it and allow code reusability Part-of: --- rsvg/src/text2.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/rsvg/src/text2.rs b/rsvg/src/text2.rs index cac7ced7b..305dbccc5 100644 --- a/rsvg/src/text2.rs +++ b/rsvg/src/text2.rs @@ -14,6 +14,7 @@ pub struct Text2; impl ElementTrait for Text2 {} #[derive(Default)] +#[allow(dead_code)] struct Character { // https://www.w3.org/TR/SVG2/text.html#TextLayoutAlgorithm // Section "11.5.1 Setup" @@ -46,13 +47,17 @@ fn collapse_white_space(input: &str, white_space: WhiteSpace) -> Vec fn is_bidi_control(ch: char) -> bool { use crate::text::directional_formatting_characters::*; - ch == LRE || ch == RLE || ch == LRO || ch == RLO || ch == PDF + matches!(ch, LRE | RLE | LRO | RLO | PDF) +} + +// move to inline constant if conditions needs to change +fn is_space(ch: char) -> bool { + matches!(ch, ' ' | '\t' | '\n') } fn collapse_white_space_normal(input: &str) -> Vec { - let mut result: Vec = Vec::new(); + let mut result: Vec = Vec::with_capacity(input.len()); let mut prev_was_space: bool = false; - // let mut character = Character::default(); for ch in input.chars() { if is_bidi_control(ch) { @@ -60,9 +65,7 @@ fn collapse_white_space_normal(input: &str) -> Vec { continue; } - let is_space = ch == ' ' || ch == '\t' || ch == '\n'; - - if is_space { + if is_space(ch) { if prev_was_space { result.push(Character { addressable: false }); } else { -- GitLab From 1b2b6fe399a9f7c8f33426382631c496597b5ce4 Mon Sep 17 00:00:00 2001 From: yorubad-dev Date: Thu, 16 Jan 2025 22:23:42 +0100 Subject: [PATCH 3/5] add character field to addressable and more bidi-control properties to check with Part-of: --- rsvg/src/text2.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/rsvg/src/text2.rs b/rsvg/src/text2.rs index 305dbccc5..9f0643024 100644 --- a/rsvg/src/text2.rs +++ b/rsvg/src/text2.rs @@ -25,6 +25,7 @@ struct Character { // angle: Angle, // hidden: bool, addressable: bool, + character: char, // middle: bool, // anchored_chunk: bool, } @@ -47,7 +48,7 @@ fn collapse_white_space(input: &str, white_space: WhiteSpace) -> Vec fn is_bidi_control(ch: char) -> bool { use crate::text::directional_formatting_characters::*; - matches!(ch, LRE | RLE | LRO | RLO | PDF) + matches!(ch, LRE | RLE | LRO | RLO | PDF | LRI | FSI | PDI) } // move to inline constant if conditions needs to change @@ -61,19 +62,32 @@ fn collapse_white_space_normal(input: &str) -> Vec { for ch in input.chars() { if is_bidi_control(ch) { - result.push(Character { addressable: false }); + result.push(Character { + addressable: false, + character: ch, + }); continue; } if is_space(ch) { if prev_was_space { - result.push(Character { addressable: false }); + result.push(Character { + addressable: false, + character: ch, + }); } else { - result.push(Character { addressable: true }); + result.push(Character { + addressable: true, + character: ch, + }); prev_was_space = true; } } else { - result.push(Character { addressable: true }); + result.push(Character { + addressable: true, + character: ch, + }); + prev_was_space = false; } } -- GitLab From 44146176e9306e3ee6e0ec950528c563a766af4e Mon Sep 17 00:00:00 2001 From: yorubad-dev Date: Thu, 16 Jan 2025 22:27:16 +0100 Subject: [PATCH 4/5] add missing bidi control property "RLI" Part-of: --- rsvg/src/text2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsvg/src/text2.rs b/rsvg/src/text2.rs index 9f0643024..1f1bbe3bd 100644 --- a/rsvg/src/text2.rs +++ b/rsvg/src/text2.rs @@ -48,7 +48,7 @@ fn collapse_white_space(input: &str, white_space: WhiteSpace) -> Vec fn is_bidi_control(ch: char) -> bool { use crate::text::directional_formatting_characters::*; - matches!(ch, LRE | RLE | LRO | RLO | PDF | LRI | FSI | PDI) + matches!(ch, LRE | RLE | LRO | RLO | PDF | LRI | RLI| FSI | PDI) } // move to inline constant if conditions needs to change -- GitLab From 7ea6d8851df34fcde0bae531a1318665002a839a Mon Sep 17 00:00:00 2001 From: yorubad-dev Date: Thu, 16 Jan 2025 22:35:49 +0100 Subject: [PATCH 5/5] fix ci fmt fail Part-of: --- rsvg/src/text2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsvg/src/text2.rs b/rsvg/src/text2.rs index 1f1bbe3bd..f1986e19a 100644 --- a/rsvg/src/text2.rs +++ b/rsvg/src/text2.rs @@ -48,7 +48,7 @@ fn collapse_white_space(input: &str, white_space: WhiteSpace) -> Vec fn is_bidi_control(ch: char) -> bool { use crate::text::directional_formatting_characters::*; - matches!(ch, LRE | RLE | LRO | RLO | PDF | LRI | RLI| FSI | PDI) + matches!(ch, LRE | RLE | LRO | RLO | PDF | LRI | RLI | FSI | PDI) } // move to inline constant if conditions needs to change -- GitLab