[librsvg: 12/37] text.rs: Start logic to turn a NodeText and its children to Chunks



commit e97cbefd025a8b0e0a1955f2d78fc54c089eb1fe
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Oct 30 18:16:30 2018 -0600

    text.rs: Start logic to turn a NodeText and its children to Chunks

 rsvg_internals/src/text.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 95 insertions(+), 2 deletions(-)
---
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index c5a45640..74a8228f 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -38,11 +38,21 @@ use state::{
 ///
 /// [text chunk]: https://www.w3.org/TR/SVG11/text.html#TextLayoutIntroduction
 struct Chunk {
-    x: Option<f64>,
-    y: Option<f64>,
+    x: Option<Length>,
+    y: Option<Length>,
     spans: Vec<Span>,
 }
 
+impl Chunk {
+    fn new(x: Option<Length>, y: Option<Length>) -> Chunk {
+        Chunk {
+            x,
+            y,
+            spans: Vec::new(),
+        }
+    }
+}
+
 struct Span {
     values: ComputedValues,
     text: String,
@@ -138,6 +148,52 @@ impl PositionedSpan {
     }
 }
 
+/// Walks the children of a `<text>`, `<tspan>`, or `<tref>` element
+/// and appends chunks/spans from them into the specified `chunks`
+/// array.
+///
+/// `x` and `y` are the absolute position for the first chunk.  If the
+/// first child is a `<tspan>` with a specified absolute position, it
+/// will be used instead of the given arguments.
+fn children_to_chunks(
+    chunks: &mut Vec<Chunk>,
+    node: &RsvgNode,
+    cascaded: &CascadedValues<'_>,
+    x: Option<Length>,
+    y: Option<Length>,
+) {
+    let values = cascaded.get();
+
+    for child in node.children() {
+        match child.get_type() {
+            NodeType::Chars => node.with_impl(|chars: &NodeChars| {
+                let span = chars.make_span(&child, &values);
+
+                let num_chunks = chunks.len();
+                if num_chunks > 0 {
+                    chunks[num_chunks - 1].spans.push(span);
+                } else {
+                    let mut chunk = Chunk::new(x, y);
+                    chunk.spans.push(span);
+                    chunks.push(chunk);
+                }
+            }),
+
+            NodeType::TSpan => node.with_impl(|tspan: &NodeTSpan| {
+                let cascaded = CascadedValues::new(cascaded, &child);
+                tspan.to_chunks(&child, &cascaded, chunks, x, y);
+            }),
+
+            NodeType::TRef => node.with_impl(|tref: &NodeTRef| {
+                let cascaded = CascadedValues::new(cascaded, &child);
+                tref.to_chunks(&child, &cascaded, chunks, x, y);
+            }),
+
+            _ => (),
+        }
+    }
+}
+
 /// In SVG text elements, we use `NodeChars` to store character data.  For example,
 /// an element like `<text>Foo Bar</text>` will be a `NodeText` with a single child,
 /// and the child will be a `NodeChars` with "Foo Bar" for its contents.
@@ -257,6 +313,16 @@ impl NodeText {
             dy: Cell::new(Length::default()),
         }
     }
+
+    fn make_chunks(&self, node: &RsvgNode, cascaded: &CascadedValues<'_>) -> Vec<Chunk> {
+        let mut chunks = Vec::new();
+
+        let x = self.x.get();
+        let y = self.y.get();
+
+        children_to_chunks(&mut chunks, node, cascaded, Some(x), Some(y));
+        chunks
+    }
 }
 
 impl NodeTrait for NodeText {
@@ -332,6 +398,19 @@ impl NodeTRef {
         }
     }
 
+    fn to_chunks(
+        &self,
+        _node: &RsvgNode,
+        _cascaded: &CascadedValues<'_>,
+        _chunks: &mut Vec<Chunk>,
+        _x: Option<Length>,
+        _y: Option<Length>,
+    ) {
+        // let x = self.x.get().or(x);
+        // let y = self.y.get().or(y);
+        // unimplemented!();
+    }
+
     fn measure(
         &self,
         node: &RsvgNode,
@@ -423,6 +502,20 @@ impl NodeTSpan {
         }
     }
 
+    fn to_chunks(
+        &self,
+        node: &RsvgNode,
+        cascaded: &CascadedValues<'_>,
+        chunks: &mut Vec<Chunk>,
+        x: Option<Length>,
+        y: Option<Length>,
+    ) {
+        let x = self.x.get().or(x);
+        let y = self.y.get().or(y);
+
+        children_to_chunks(chunks, node, cascaded, x, y);
+    }
+
     fn measure(
         &self,
         node: &RsvgNode,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]