[librsvg: 5/15] layout::TextSpan - compute the span's bbox and store it here, not in the drawing code




commit eb93155bc4778d19e930b1e8a969fa22ae1a3af5
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Oct 18 12:02:29 2021 -0500

    layout::TextSpan - compute the span's bbox and store it here, not in the drawing code
    
    Unfortunately this requires asking the draw_ctx for its current
    transform.  We'll refactor this later.
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/613>

 src/drawing_ctx.rs | 59 +++++-------------------------------------------------
 src/layout.rs      |  2 ++
 src/text.rs        | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 54 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 9ddd1508..72708a79 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -333,7 +333,9 @@ impl DrawingCtx {
         self.measuring
     }
 
-    fn get_transform(&self) -> Transform {
+    // FIXME: this is public just so that text.rs can access it.  Maybe the draw_fn passed to 
with_discrete_layer should
+    // obtain the current transform as an argument?
+    pub fn get_transform(&self) -> Transform {
         Transform::from(self.cr.matrix())
     }
 
@@ -1362,12 +1364,11 @@ impl DrawingCtx {
 
         let paint_order = values.paint_order();
 
-        let bbox = compute_text_box(&span.layout, span.x, span.y, transform, span.gravity);
-        if bbox.is_none() {
+        if span.bbox.is_none() {
             return Ok(self.empty_bbox());
         }
 
-        let mut bbox = bbox.unwrap();
+        let mut bbox = span.bbox.unwrap();
 
         with_saved_cr(&self.cr.clone(), || {
             self.cr
@@ -1914,51 +1915,6 @@ fn compute_stroke_and_fill_box(
     Ok(bbox)
 }
 
-fn compute_text_box(
-    layout: &pango::Layout,
-    x: f64,
-    y: f64,
-    transform: Transform,
-    gravity: pango::Gravity,
-) -> Option<BoundingBox> {
-    #![allow(clippy::many_single_char_names)]
-
-    let (ink, _) = layout.extents();
-    if ink.width == 0 || ink.height == 0 {
-        return None;
-    }
-
-    let ink_x = f64::from(ink.x);
-    let ink_y = f64::from(ink.y);
-    let ink_width = f64::from(ink.width);
-    let ink_height = f64::from(ink.height);
-    let pango_scale = f64::from(pango::SCALE);
-
-    let (x, y, w, h) = if gravity_is_vertical(gravity) {
-        (
-            x + (ink_x - ink_height) / pango_scale,
-            y + ink_y / pango_scale,
-            ink_height / pango_scale,
-            ink_width / pango_scale,
-        )
-    } else {
-        (
-            x + ink_x / pango_scale,
-            y + ink_y / pango_scale,
-            ink_width / pango_scale,
-            ink_height / pango_scale,
-        )
-    };
-
-    let r = Rect::new(x, y, x + w, y + h);
-    let bbox = BoundingBox::new()
-        .with_transform(transform)
-        .with_rect(r)
-        .with_ink_rect(r);
-
-    Some(bbox)
-}
-
 fn setup_cr_for_stroke(cr: &cairo::Context, stroke: &Stroke) {
     cr.set_line_width(stroke.width);
     cr.set_miter_limit(stroke.miter_limit.0);
@@ -1974,11 +1930,6 @@ fn setup_cr_for_stroke(cr: &cairo::Context, stroke: &Stroke) {
     }
 }
 
-// FIXME: should the pango crate provide this like PANGO_GRAVITY_IS_VERTICAL() ?
-fn gravity_is_vertical(gravity: pango::Gravity) -> bool {
-    matches!(gravity, pango::Gravity::East | pango::Gravity::West)
-}
-
 /// escape quotes and backslashes with backslash
 fn escape_link_target(value: &str) -> Cow<'_, str> {
     static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"['\\]").unwrap());
diff --git a/src/layout.rs b/src/layout.rs
index c0dff1fb..085cf584 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -5,6 +5,7 @@
 use std::rc::Rc;
 
 use crate::aspect_ratio::AspectRatio;
+use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
 use crate::dasharray::Dasharray;
 use crate::document::AcquiredNodes;
@@ -97,6 +98,7 @@ pub struct Image {
 pub struct TextSpan {
     pub layout: pango::Layout,
     pub gravity: pango::Gravity,
+    pub bbox: Option<BoundingBox>,
     pub is_visible: bool,
     pub x: f64,
     pub y: f64,
diff --git a/src/text.rs b/src/text.rs
index 103dcd4b..285b59b0 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -17,7 +17,9 @@ use crate::properties::{
     ComputedValues, Direction, FontStretch, FontStyle, FontVariant, FontWeight, TextAnchor,
     UnicodeBidi, WritingMode, XmlLang, XmlSpace,
 };
+use crate::rect::Rect;
 use crate::space::{xml_space_normalize, NormalizeDefault, XmlSpaceNormalize};
+use crate::transform::Transform;
 use crate::xml::Attributes;
 
 /// An absolutely-positioned array of `Span`s
@@ -275,6 +277,56 @@ impl MeasuredSpan {
     }
 }
 
+// FIXME: should the pango crate provide this like PANGO_GRAVITY_IS_VERTICAL() ?
+fn gravity_is_vertical(gravity: pango::Gravity) -> bool {
+    matches!(gravity, pango::Gravity::East | pango::Gravity::West)
+}
+
+fn compute_text_box(
+    layout: &pango::Layout,
+    x: f64,
+    y: f64,
+    transform: Transform,
+    gravity: pango::Gravity,
+) -> Option<BoundingBox> {
+    #![allow(clippy::many_single_char_names)]
+
+    let (ink, _) = layout.extents();
+    if ink.width == 0 || ink.height == 0 {
+        return None;
+    }
+
+    let ink_x = f64::from(ink.x);
+    let ink_y = f64::from(ink.y);
+    let ink_width = f64::from(ink.width);
+    let ink_height = f64::from(ink.height);
+    let pango_scale = f64::from(pango::SCALE);
+
+    let (x, y, w, h) = if gravity_is_vertical(gravity) {
+        (
+            x + (ink_x - ink_height) / pango_scale,
+            y + ink_y / pango_scale,
+            ink_height / pango_scale,
+            ink_width / pango_scale,
+        )
+    } else {
+        (
+            x + ink_x / pango_scale,
+            y + ink_y / pango_scale,
+            ink_width / pango_scale,
+            ink_height / pango_scale,
+        )
+    };
+
+    let r = Rect::new(x, y, x + w, y + h);
+    let bbox = BoundingBox::new()
+        .with_transform(transform)
+        .with_rect(r)
+        .with_ink_rect(r);
+
+    Some(bbox)
+}
+
 impl PositionedSpan {
     fn draw(
         &self,
@@ -311,9 +363,12 @@ impl PositionedSpan {
 
         let gravity = layout.context().unwrap().gravity();
 
+        let bbox = compute_text_box(&layout, x, y, draw_ctx.get_transform(), gravity);
+
         let span = layout::TextSpan {
             layout,
             gravity,
+            bbox,
             is_visible,
             x,
             y,


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