From ccfaafdc59f88d185fe5cd5c3a83bf6364c361a5 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 7 Aug 2017 11:20:55 +0200 Subject: Add support for imported style sheets via @import to Inkscape. --- src/sp-style-elem.cpp | 171 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 53 deletions(-) (limited to 'src/sp-style-elem.cpp') diff --git a/src/sp-style-elem.cpp b/src/sp-style-elem.cpp index c15f810e9..c87b5436d 100644 --- a/src/sp-style-elem.cpp +++ b/src/sp-style-elem.cpp @@ -6,6 +6,12 @@ #include "sp-root.h" #include "attributes.h" #include "style.h" + +// For external style sheets +#include "io/resource.h" +#include +#include + using Inkscape::XML::TEXT_NODE; SPStyleElem::SPStyleElem() : SPObject() { @@ -124,13 +130,15 @@ struct ParseTmp CRStyleSheet *const stylesheet; StmtType stmtType; CRStatement *currStmt; + SPDocument *const document; // Need file location for '@import' unsigned magic; static unsigned const ParseTmp_magic = 0x23474397; // from /dev/urandom - ParseTmp(CRStyleSheet *const stylesheet) : + ParseTmp(CRStyleSheet *const stylesheet, SPDocument *const document) : stylesheet(stylesheet), stmtType(NO_STMT), currStmt(NULL), + document(document), magic(ParseTmp_magic) { } @@ -145,6 +153,70 @@ struct ParseTmp } }; +CRParser* +parser_init(CRStyleSheet *const stylesheet, SPDocument *const document); + +static void +import_style_cb (CRDocHandler *a_handler, + GList *a_media_list, + CRString *a_uri, + CRString *a_uri_default_ns, + CRParsingLocation *a_location) +{ + /* a_uri_default_ns is set to NULL and is unused by libcroco */ + + // Get document + g_return_if_fail(a_handler && a_uri); + g_return_if_fail(a_handler->app_data != NULL); + ParseTmp &parse_tmp = *static_cast(a_handler->app_data); + g_return_if_fail(parse_tmp.hasMagic()); + + SPDocument* document = parse_tmp.document; + if (!document) { + std::cerr << "import_style_cb: No document!" << std::endl; + return; + } + if (!document->getURI()) { + std::cerr << "import_style_cb: Document URI is NULL" << std::endl; + return; + } + + // Get file + Glib::ustring import_file = + Inkscape::IO::Resource::get_filename (document->getURI(), a_uri->stryng->str); + + // Parse file + CRStyleSheet *stylesheet = cr_stylesheet_new (NULL); + CRParser *parser = parser_init(stylesheet, document); + CRStatus const parse_status = + cr_parser_parse_file (parser, reinterpret_cast(import_file.c_str()), CR_UTF_8); + if (parse_status == CR_OK) { + cr_stylesheet_append_import (document->style_sheet, stylesheet); + } else { + std::cerr << "import_style_cb: Could not parse: " << import_file << std::endl; + cr_stylesheet_destroy (stylesheet); + } + + // Need to delete ParseTmp created by parser_init() + CRDocHandler *sac_handler = NULL; + cr_parser_get_sac_handler (parser, &sac_handler); + ParseTmp *parse_new = reinterpret_cast(sac_handler->app_data); + cr_parser_destroy(parser); + delete parse_new; +}; + +/* NOT USED, incomplete libcroco implementation */ +static void +import_style_result_cb (CRDocHandler *a_this, + GList *a_media_list, + CRString *a_uri, + CRString *a_uri_default_ns, + CRStyleSheet *a_sheet) +{ + /* a_uri_default_ns and a_sheet are set to NULL and are unused by libcroco */ + std::cerr << "import_style_result_cb: unimplemented" << std::endl; +}; + static void start_selector_cb(CRDocHandler *a_handler, CRSelector *a_sel_list) @@ -251,6 +323,26 @@ property_cb(CRDocHandler *const a_handler, g_return_if_fail(append_status == CR_OK); } +CRParser* +parser_init(CRStyleSheet *const stylesheet, SPDocument *const document) { + + ParseTmp *parse_tmp = new ParseTmp(stylesheet, document); + + CRDocHandler *sac_handler = cr_doc_handler_new(); + sac_handler->app_data = parse_tmp; + sac_handler->import_style = import_style_cb; + sac_handler->start_selector = start_selector_cb; + sac_handler->end_selector = end_selector_cb; + sac_handler->start_font_face = start_font_face_cb; + sac_handler->end_font_face = end_font_face_cb; + sac_handler->property = property_cb; + + CRParser *parser = cr_parser_new (NULL); + cr_parser_set_sac_handler(parser, sac_handler); + + return parser; +} + void update_style_recursively( SPObject *object ) { if (object) { // std::cout << "update_style_recursively: " @@ -265,52 +357,35 @@ void update_style_recursively( SPObject *object ) { } void SPStyleElem::read_content() { - /* fixme: If there's more than one