[librsvg] rsvg_text_create_layout(): This is now implemented in Rust. Yay!



commit 8f1a6bc2c6a1133a2c8bf925854bfb494d70a1ef
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Dec 15 11:48:04 2017 -0600

    rsvg_text_create_layout(): This is now implemented in Rust.  Yay!

 rsvg-text.c      |  81 ++-----------------------------------------
 rust/src/lib.rs  |   5 +++
 rust/src/text.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+), 79 deletions(-)
---
diff --git a/rsvg-text.c b/rsvg-text.c
index ff72a53..1107864 100644
--- a/rsvg-text.c
+++ b/rsvg-text.c
@@ -549,85 +549,8 @@ rsvg_new_tref (const char *element_name, RsvgNode *parent)
                                 rsvg_node_tref_free);
 }
 
-static PangoLayout *
-rsvg_text_create_layout (RsvgDrawingCtx *ctx, const char *text)
-{
-    RsvgState *state;
-    PangoContext *context;
-    PangoFontDescription *font_desc;
-    PangoLayout *layout;
-    PangoAttrList *attr_list;
-    double dpi_y;
-    const char *lang;
-    UnicodeBidi unicode_bidi;
-    RsvgLength letter_spacing;
-    const TextDecoration *font_decor;
-
-    g_assert (text != NULL);
-
-    state = rsvg_current_state (ctx);
-
-    context = rsvg_drawing_ctx_get_pango_context (ctx);
-
-    lang = rsvg_state_get_language (state);
-    if (lang)
-        pango_context_set_language (context, pango_language_from_string (lang));
-
-    unicode_bidi = rsvg_state_get_unicode_bidi (state);
-    if (unicode_bidi == UNICODE_BIDI_OVERRIDE || unicode_bidi == UNICODE_BIDI_EMBED)
-        pango_context_set_base_dir (context,
-                                    rsvg_state_get_text_dir (state));
-
-    if (PANGO_GRAVITY_IS_VERTICAL (rsvg_state_get_text_gravity (state)))
-        pango_context_set_base_gravity (context, rsvg_state_get_text_gravity (state));
-
-    font_desc = pango_font_description_copy (pango_context_get_font_description (context));
-
-    if (rsvg_state_get_font_family (state))
-        pango_font_description_set_family (font_desc, rsvg_state_get_font_family (state));
-
-    pango_font_description_set_style (font_desc, rsvg_state_get_font_style (state));
-    pango_font_description_set_variant (font_desc, rsvg_state_get_font_variant (state));
-    pango_font_description_set_weight (font_desc, rsvg_state_get_font_weight (state));
-    pango_font_description_set_stretch (font_desc, rsvg_state_get_font_stretch (state));
-
-    rsvg_drawing_ctx_get_dpi (ctx, NULL, &dpi_y);
-    pango_font_description_set_size (font_desc,
-                                     rsvg_drawing_ctx_get_normalized_font_size (ctx) * PANGO_SCALE / dpi_y * 
72);
-
-    layout = pango_layout_new (context);
-    pango_layout_set_font_description (layout, font_desc);
-    pango_font_description_free (font_desc);
-
-    attr_list = pango_attr_list_new ();
-    letter_spacing = rsvg_state_get_letter_spacing (state);
-    pango_attr_list_insert (attr_list,
-                            pango_attr_letter_spacing_new (rsvg_length_normalize (&letter_spacing, ctx) * 
PANGO_SCALE));
-
-    font_decor = rsvg_state_get_font_decor (state);
-    if (font_decor) {
-        if (font_decor->underline) {
-            pango_attr_list_insert (attr_list,
-                                    pango_attr_underline_new (PANGO_UNDERLINE_SINGLE));
-        }
-       if (font_decor->strike) {
-            pango_attr_list_insert (attr_list,
-                                    pango_attr_strikethrough_new (TRUE));
-       }
-    }
-
-    pango_layout_set_attributes (layout, attr_list);
-    pango_attr_list_unref (attr_list);
-
-    pango_layout_set_alignment (layout, (rsvg_state_get_text_dir (state) == PANGO_DIRECTION_LTR) ?
-                                PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT);
-
-    pango_layout_set_text (layout, text, -1);
-
-    g_object_unref (context);
-
-    return layout;
-}
+/* Defined in rust/src/text.rs */
+extern PangoLayout *rsvg_text_create_layout (RsvgDrawingCtx *ctx, const char *text);
 
 static void
 rsvg_text_render_text (RsvgDrawingCtx * ctx, const char *text, gdouble * x, gdouble * y)
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index ffc2a2f..5d5e769 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -140,6 +140,10 @@ pub use structure::{
     rsvg_node_use_new,
 };
 
+pub use text::{
+    rsvg_text_create_layout,
+};
+
 pub use transform::{
     rsvg_parse_transform,
 };
@@ -180,6 +184,7 @@ mod space;
 mod state;
 mod stop;
 mod structure;
+mod text;
 mod transform;
 mod util;
 mod viewbox;
diff --git a/rust/src/text.rs b/rust/src/text.rs
new file mode 100644
index 0000000..24d7823
--- /dev/null
+++ b/rust/src/text.rs
@@ -0,0 +1,102 @@
+use libc;
+use glib::translate::*;
+use pango::{self, ContextExt, LayoutExt};
+use pango_sys;
+
+use drawing_ctx::{self, RsvgDrawingCtx};
+use state::{self, UnicodeBidi};
+
+// FIXME: should the pango crate provide this like PANGO_GRAVITY_IS_VERTICAL() / PANGO_GRAVITY_IS_IMPROPER()?
+fn gravity_is_vertical(gravity: pango::Gravity) -> bool {
+    match gravity {
+        pango::Gravity::East | pango::Gravity::West => true,
+        _ => false
+    }
+}
+
+fn to_pango_units(v: f64) -> i32 {
+    (v * pango::SCALE as f64) as i32
+}
+
+fn create_pango_layout(draw_ctx: *const RsvgDrawingCtx, text: &str) -> pango::Layout {
+    let state = drawing_ctx::get_current_state(draw_ctx);
+    let pango_context = drawing_ctx::get_pango_context(draw_ctx);
+
+    if let Some(lang) = state::get_language(state) {
+        let pango_lang = pango::Language::from_string(&lang);
+        pango_context.set_language(&pango_lang);
+    }
+
+    let unicode_bidi = state::get_unicode_bidi(state);
+    match unicode_bidi {
+        UnicodeBidi::Override | UnicodeBidi::Embed => {
+            pango_context.set_base_dir(state::get_text_dir(state));
+        },
+
+        _ => ()
+    }
+
+    let gravity = state::get_text_gravity(state);
+    if gravity_is_vertical(gravity) {
+        pango_context.set_base_gravity(gravity);
+    }
+
+    let mut font_desc = pango_context.get_font_description().unwrap();
+
+    if let Some(font_family) = state::get_font_family(state) {
+        font_desc.set_family(&font_family);
+    }
+
+    font_desc.set_style(state::get_font_style(state));
+    font_desc.set_variant(state::get_font_variant(state));
+    font_desc.set_weight(state::get_font_weight(state));
+    font_desc.set_stretch(state::get_font_stretch(state));
+
+    let (_, dpi_y) = drawing_ctx::get_dpi(draw_ctx);
+    font_desc.set_size(to_pango_units(drawing_ctx::get_normalized_font_size(draw_ctx) / dpi_y * 72.0));
+
+    let layout = pango::Layout::new(&pango_context);
+    layout.set_font_description(&font_desc);
+
+    let attr_list = pango::AttrList::new();
+
+    attr_list.insert(
+        pango::Attribute::new_letter_spacing(
+            to_pango_units(state::get_letter_spacing(state).normalize(draw_ctx))
+        ).unwrap());
+
+    if let Some(font_decor) = state::get_font_decor(state) {
+        if font_decor.underline {
+            attr_list.insert(pango::Attribute::new_underline(pango::Underline::Single)
+                             .unwrap());
+        }
+
+        if font_decor.strike {
+            attr_list.insert(pango::Attribute::new_strikethrough(true)
+                             .unwrap());
+        }
+    }
+
+    layout.set_attributes(&attr_list);
+
+    layout.set_alignment(
+        match state::get_text_dir(state) {
+            pango::Direction::Ltr => pango::Alignment::Left,
+            _                     => pango::Alignment::Right,
+        }
+    );
+
+    layout.set_text(text);
+
+    layout
+}
+
+#[no_mangle]
+pub extern fn rsvg_text_create_layout(draw_ctx: *const RsvgDrawingCtx,
+                                      text: *const libc::c_char) -> *const pango_sys::PangoLayout {
+    assert!(!text.is_null());
+    let s = unsafe { String::from_glib_none(text) };
+    let layout = create_pango_layout(draw_ctx, &s);
+
+    layout.to_glib_full()
+}


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