[librsvg: 3/8] css.rs: Move most of the libcroco callbacks to Rust



commit 114a7d9b67669338b5911ca85a732f6e4ec8616c
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Sep 25 10:05:04 2018 -0500

    css.rs: Move most of the libcroco callbacks to Rust

 Makefile.am                  |   1 -
 librsvg/rsvg-load.c          |   5 +-
 librsvg/rsvg-private.h       |   6 ++
 librsvg/rsvg-styles.c        | 156 +------------------------------------------
 librsvg/rsvg-styles.h        |  40 -----------
 rsvg_internals/src/croco.rs  |   2 +-
 rsvg_internals/src/css.rs    | 136 ++++++++++++++++++++++++++++++++-----
 rsvg_internals/src/handle.rs |   4 ++
 rsvg_internals/src/lib.rs    |   7 +-
 9 files changed, 142 insertions(+), 215 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 285a90d5..2e5d2e88 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
        librsvg/rsvg-size-callback.c            \
        librsvg/rsvg-size-callback.h            \
        librsvg/rsvg-styles.c                   \
-       librsvg/rsvg-styles.h                   \
        librsvg/rsvg.h                          \
        $(NULL)
 
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 9287ad0e..44e1f670 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -28,7 +28,6 @@
 
 #include "rsvg-attributes.h"
 #include "rsvg-load.h"
-#include "rsvg-styles.h"
 
 typedef enum {
     LOAD_STATE_START,
@@ -184,7 +183,7 @@ style_handler_free (RsvgSaxHandler * self)
     RsvgSaxHandlerStyle *z = (RsvgSaxHandlerStyle *) self;
 
     if (z->is_text_css)
-        rsvg_parse_cssbuffer (z->load->handle, z->style->str, z->style->len);
+        rsvg_css_parse_into_handle (z->load->handle, z->style->str, z->style->len);
 
     g_string_free (z->style, TRUE);
     g_free (z);
@@ -933,7 +932,7 @@ sax_processing_instruction_cb (void *user_data, const xmlChar * target, const xm
                 if (style_data &&
                     mime_type &&
                     strcmp (mime_type, "text/css") == 0) {
-                    rsvg_parse_cssbuffer (load->handle, style_data, style_data_len);
+                    rsvg_css_parse_into_handle (load->handle, style_data, style_data_len);
                 }
 
                 g_free (mime_type);
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 5c2c61e1..e5c94c4d 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -206,6 +206,12 @@ void rsvg_css_styles_define (RsvgCssStyles *styles,
                              const char *style_value,
                              gboolean important);
 
+/* Implemented in rsvg_internals/src/css.rs */
+G_GNUC_INTERNAL
+void rsvg_css_parse_into_handle (RsvgHandle *handle,
+                                 const char *buf,
+                                 gsize len);
+
 /* Implemented in rsvg_internals/src/structure.rs */
 G_GNUC_INTERNAL
 gboolean rsvg_node_svg_get_size (RsvgNode *node, double dpi_x, double dpi_y, int *out_width, int 
*out_height);
diff --git a/librsvg/rsvg-styles.c b/librsvg/rsvg-styles.c
index e296fb50..c009ce95 100644
--- a/librsvg/rsvg-styles.c
+++ b/librsvg/rsvg-styles.c
@@ -32,163 +32,10 @@
 #include "rsvg-attributes.h"
 #include "rsvg-private.h"
 #include "rsvg-css.h"
-#include "rsvg-styles.h"
 
 #include <libcroco/libcroco.h>
 
-
-typedef struct _CSSUserData {
-    RsvgHandle *handle;
-    CRSelector *selector;
-} CSSUserData;
-
-static void
-css_user_data_init (CSSUserData *user_data, RsvgHandle *handle)
-{
-    user_data->handle = handle;
-    user_data->selector = NULL;
-}
-
-static void
-ccss_start_selector (CRDocHandler * a_handler, CRSelector * a_selector_list)
-{
-    CSSUserData *user_data;
-
-    g_return_if_fail (a_handler);
-
-    user_data = (CSSUserData *) a_handler->app_data;
-    cr_selector_ref (a_selector_list);
-    user_data->selector = a_selector_list;
-}
-
-static void
-ccss_end_selector (CRDocHandler * a_handler, CRSelector * a_selector_list)
-{
-    CSSUserData *user_data;
-
-    g_return_if_fail (a_handler);
-
-    user_data = (CSSUserData *) a_handler->app_data;
-
-    cr_selector_unref (user_data->selector);
-    user_data->selector = NULL;
-}
-
-static void
-ccss_property (CRDocHandler * a_handler, CRString * a_name, CRTerm * a_expr, gboolean important)
-{
-    CSSUserData *user_data;
-    gchar *name = NULL;
-    size_t len = 0;
-
-    g_return_if_fail (a_handler);
-
-    user_data = (CSSUserData *) a_handler->app_data;
-
-    if (a_name && a_expr && user_data->selector) {
-        CRSelector *cur;
-        for (cur = user_data->selector; cur; cur = cur->next) {
-            if (cur->simple_sel) {
-                gchar *selector = (gchar *) cr_simple_sel_to_string (cur->simple_sel);
-                if (selector) {
-                    gchar *prop_name, *prop_value;
-                    name = (gchar *) cr_string_peek_raw_str (a_name);
-                    len = cr_string_peek_raw_str_len (a_name);
-                    prop_name = g_strndup (name, len);
-                    prop_value = (gchar *)cr_term_to_string (a_expr);
-                    rsvg_css_styles_define (user_data->handle->priv->css_styles,
-                                           selector,
-                                           prop_name,
-                                           prop_value,
-                                           important);
-                    g_free (selector);
-                    g_free (prop_name);
-                    g_free (prop_value);
-                }
-            }
-        }
-    }
-}
-
-static void
-ccss_error (CRDocHandler * a_handler)
-{
-    /* yup, like i care about CSS parsing errors ;-)
-       ignore, chug along */
-    g_message (_("CSS parsing error\n"));
-}
-
-static void
-ccss_unrecoverable_error (CRDocHandler * a_handler)
-{
-    /* yup, like i care about CSS parsing errors ;-)
-       ignore, chug along */
-    g_message (_("CSS unrecoverable error\n"));
-}
-
-static void
- ccss_import_style (CRDocHandler * a_this,
-                    GList * a_media_list,
-                    CRString * a_uri, CRString * a_uri_default_ns, CRParsingLocation * a_location);
-
-static void
-init_sac_handler (CRDocHandler * a_handler)
-{
-    a_handler->start_document = NULL;
-    a_handler->end_document = NULL;
-    a_handler->import_style = ccss_import_style;
-    a_handler->namespace_declaration = NULL;
-    a_handler->comment = NULL;
-    a_handler->start_selector = ccss_start_selector;
-    a_handler->end_selector = ccss_end_selector;
-    a_handler->property = ccss_property;
-    a_handler->start_font_face = NULL;
-    a_handler->end_font_face = NULL;
-    a_handler->start_media = NULL;
-    a_handler->end_media = NULL;
-    a_handler->start_page = NULL;
-    a_handler->end_page = NULL;
-    a_handler->ignorable_at_rule = NULL;
-    a_handler->error = ccss_error;
-    a_handler->unrecoverable_error = ccss_unrecoverable_error;
-}
-
-void
-rsvg_parse_cssbuffer (RsvgHandle *handle, const char *buff, size_t buflen)
-{
-    CRParser *parser = NULL;
-    CRDocHandler *css_handler = NULL;
-    CSSUserData user_data;
-
-    if (buff == NULL || buflen == 0)
-        return;
-
-    css_handler = cr_doc_handler_new ();
-    init_sac_handler (css_handler);
-
-    css_user_data_init (&user_data, handle);
-    css_handler->app_data = &user_data;
-
-    /* TODO: fix libcroco to take in const strings */
-    parser = cr_parser_new_from_buf ((guchar *) buff, (gulong) buflen, CR_UTF_8, FALSE);
-    if (parser == NULL) {
-        cr_doc_handler_unref (css_handler);
-        return;
-    }
-
-    cr_parser_set_sac_handler (parser, css_handler);
-    cr_doc_handler_unref (css_handler);
-
-    cr_parser_set_use_core_grammar (parser, FALSE);
-    cr_parser_parse (parser);
-
-    /* FIXME: we aren't reporting errors in the CSS; we have no way to know if
-     * we should print the "buff" for diagnostics.
-     */
-
-    cr_parser_destroy (parser);
-}
-
+#if 0
 static void
 ccss_import_style (CRDocHandler * a_this,
                    GList * a_media_list,
@@ -219,6 +66,7 @@ ccss_import_style (CRDocHandler * a_this,
     g_free (stylesheet_data);
     g_free (mime_type);
 }
+#endif
 
 /* This is defined like this so that we can export the Rust function... just for
  * the benefit of rsvg-convert.c
diff --git a/rsvg_internals/src/croco.rs b/rsvg_internals/src/croco.rs
index 4ee67e72..3d551398 100644
--- a/rsvg_internals/src/croco.rs
+++ b/rsvg_internals/src/croco.rs
@@ -13,7 +13,7 @@ pub type CRTerm = gpointer;
 pub type CRStatus = u32;
 
 pub type CREncoding = u32;
-pub const CREncoding_CR_UTF_8: CREncoding = 5;
+pub const CR_UTF_8: CREncoding = 5;
 
 #[repr(C)]
 pub struct CRParsingLocation {
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index 689cfcbd..991c3788 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -1,14 +1,17 @@
 use std::collections::hash_map::Entry;
 use std::collections::HashMap;
-use std::str::FromStr;
+use std::ptr;
+use std::slice;
+use std::str::{self, FromStr};
 
 use libc;
 
 use glib::translate::*;
-use glib_sys::{self, gboolean, GList};
+use glib_sys::{self, gboolean, gpointer, GList};
 
 use attributes::Attribute;
 use croco::*;
+use handle::{self, RsvgHandle};
 use state::State;
 use util::utf8_cstr;
 
@@ -78,6 +81,42 @@ impl CssStyles {
     }
 }
 
+struct DocHandlerData {
+    handle: *mut RsvgHandle,
+    selector: *mut CRSelector,
+}
+
+fn parse_into_handle(handle: *mut RsvgHandle, buf: &str) {
+    unsafe {
+        let handler_data = DocHandlerData {
+            handle,
+            selector: ptr::null_mut(),
+        };
+
+        let doc_handler = cr_doc_handler_new();
+        init_cr_doc_handler(&mut *doc_handler);
+
+        (*doc_handler).app_data = &handler_data as *const _ as gpointer;
+
+        let buf_ptr = buf.as_ptr() as *mut _;
+        let buf_len = buf.len() as u64;
+
+        let parser = cr_parser_new_from_buf(buf_ptr, buf_len, CR_UTF_8, false.to_glib());
+        if parser.is_null() {
+            cr_doc_handler_unref(doc_handler);
+            return;
+        }
+
+        cr_parser_set_sac_handler(parser, doc_handler);
+        cr_doc_handler_unref(doc_handler);
+
+        cr_parser_set_use_core_grammar(parser, false.to_glib());
+        cr_parser_parse(parser);
+
+        cr_parser_destroy(parser);
+    }
+}
+
 fn init_cr_doc_handler(handler: &mut CRDocHandler) {
     handler.import_style = Some(css_import_style);
     handler.start_selector = Some(css_start_selector);
@@ -88,24 +127,37 @@ fn init_cr_doc_handler(handler: &mut CRDocHandler) {
 }
 
 unsafe extern "C" fn css_import_style(
-    a_this: *mut CRDocHandler,
-    a_media_list: *mut GList,
-    a_uri: CRString,
-    a_uri_default_ns: CRString,
-    a_location: CRParsingLocation,
+    _a_this: *mut CRDocHandler,
+    _a_media_list: *mut GList,
+    _a_uri: CRString,
+    _a_uri_default_ns: CRString,
+    _a_location: CRParsingLocation,
 ) {
     unimplemented!();
 }
 
+unsafe fn get_doc_handler_data<'a>(doc_handler: *mut CRDocHandler) -> &'a mut DocHandlerData {
+    &mut *((*doc_handler).app_data as *mut DocHandlerData)
+}
+
 unsafe extern "C" fn css_start_selector(
     a_this: *mut CRDocHandler,
     a_selector_list: *mut CRSelector,
 ) {
-    unimplemented!();
+    let handler_data = get_doc_handler_data(a_this);
+
+    cr_selector_ref(a_selector_list);
+    handler_data.selector = a_selector_list;
 }
 
-unsafe extern "C" fn css_end_selector(a_this: *mut CRDocHandler, a_selector_list: *mut CRSelector) {
-    unimplemented!();
+unsafe extern "C" fn css_end_selector(
+    a_this: *mut CRDocHandler,
+    _a_selector_list: *mut CRSelector,
+) {
+    let handler_data = get_doc_handler_data(a_this);
+
+    cr_selector_unref(handler_data.selector);
+    handler_data.selector = ptr::null_mut();
 }
 
 unsafe extern "C" fn css_property(
@@ -114,15 +166,51 @@ unsafe extern "C" fn css_property(
     a_expression: CRTerm,
     a_is_important: gboolean,
 ) {
-    unimplemented!();
+    let handler_data = get_doc_handler_data(a_this);
+
+    if a_name.is_null() || a_expression.is_null() || handler_data.selector.is_null() {
+        return;
+    }
+
+    let mut cur_sel = handler_data.selector;
+    while !cur_sel.is_null() {
+        let simple_sel = (*cur_sel).simple_sel;
+
+        if !simple_sel.is_null() {
+            let raw_selector_name = cr_simple_sel_to_string(simple_sel) as *mut libc::c_char;
+
+            if !raw_selector_name.is_null() {
+                let prop_name_ptr = cr_string_peek_raw_str(a_name);
+                let prop_name_len = cr_string_peek_raw_str_len(a_name) as usize;
+
+                let prop_name_bytes =
+                    slice::from_raw_parts(prop_name_ptr as *const u8, prop_name_len);
+                let prop_name = str::from_utf8_unchecked(prop_name_bytes);
+
+                let prop_value =
+                    <String as FromGlibPtrFull<_>>::from_glib_full(cr_term_to_string(a_expression));
+
+                let selector_name =
+                    <String as FromGlibPtrFull<_>>::from_glib_full(raw_selector_name);
+
+                let important = from_glib(a_is_important);
+
+                let styles = handle::get_css_styles_mut(handler_data.handle);
+
+                styles.define(&selector_name, prop_name, &prop_value, important);
+            }
+        }
+
+        cur_sel = (*cur_sel).next;
+    }
 }
 
-unsafe extern "C" fn css_error(a_this: *mut CRDocHandler) {
-    unimplemented!();
+unsafe extern "C" fn css_error(_a_this: *mut CRDocHandler) {
+    println!("CSS parsing error");
 }
 
-unsafe extern "C" fn css_unrecoverable_error(a_this: *mut CRDocHandler) {
-    unimplemented!();
+unsafe extern "C" fn css_unrecoverable_error(_a_this: *mut CRDocHandler) {
+    println!("CSS unrecoverable error");
 }
 
 #[no_mangle]
@@ -157,3 +245,21 @@ pub extern "C" fn rsvg_css_styles_define(
 
     styles.define(selector, prop_name, prop_value, from_glib(important));
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_css_parse_into_handle(
+    handle: *mut RsvgHandle,
+    buf: *const libc::c_char,
+    len: usize,
+) {
+    assert!(!handle.is_null());
+
+    if buf.is_null() || len == 0 {
+        return;
+    }
+
+    let bytes = slice::from_raw_parts(buf as *const u8, len);
+    let utf8 = str::from_utf8_unchecked(bytes);
+
+    parse_into_handle(handle, utf8);
+}
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index c17b6bad..f77a4d9f 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -48,3 +48,7 @@ pub fn load_extern(handle: *const RsvgHandle, uri: &str) -> *const RsvgHandle {
 pub fn get_css_styles<'a>(handle: *const RsvgHandle) -> &'a CssStyles {
     unsafe { &*(rsvg_handle_get_css_styles(handle) as *const CssStyles) }
 }
+
+pub fn get_css_styles_mut<'a>(handle: *const RsvgHandle) -> &'a mut CssStyles {
+    unsafe { &mut *(rsvg_handle_get_css_styles(handle) as *mut CssStyles) }
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index cc5691e5..c0147338 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -27,7 +27,12 @@ extern crate downcast_rs;
 
 pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
 
-pub use css::{rsvg_css_styles_define, rsvg_css_styles_free, rsvg_css_styles_new};
+pub use css::{
+    rsvg_css_parse_into_handle,
+    rsvg_css_styles_define,
+    rsvg_css_styles_free,
+    rsvg_css_styles_new,
+};
 
 pub use defs::{rsvg_defs_free, rsvg_defs_lookup, rsvg_defs_new};
 


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