sp-style-elem.cpp revision 34bbe9388eab58e6a7ab25d664595e0ed3b8dee8
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#include <libcroco/cr-parser.h>
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#include "xml/node-event-vector.h"
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#include "xml/repr.h"
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#include "document.h"
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#include "sp-style-elem.h"
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#include "attributes.h"
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelenusing Inkscape::XML::TEXT_NODE;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelenstatic void sp_style_elem_init(SPStyleElem *style_elem);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void sp_style_elem_class_init(SPStyleElemClass *klass);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void sp_style_elem_build(SPObject *object, SPDocument *doc, Inkscape::XML::Node *repr);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void sp_style_elem_set(SPObject *object, unsigned const key, gchar const *const value);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void sp_style_elem_read_content(SPObject *);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic Inkscape::XML::Node *sp_style_elem_write(SPObject *, Inkscape::XML::Node *, guint flags);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic SPObjectClass *parent_class;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freeGType
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freesp_style_elem_get_type()
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free static GType type = 0;
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen if (!type) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen GTypeInfo info = {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen sizeof(SPStyleElemClass),
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen NULL, /* base_init */
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen NULL, /* base_finalize */
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen (GClassInitFunc) sp_style_elem_class_init,
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen NULL, /* class_finalize */
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen NULL, /* class_data */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free sizeof(SPStyleElem),
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free 16, /* n_preallocs */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free (GInstanceInitFunc) sp_style_elem_init,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free NULL, /* value_table */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free };
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen type = g_type_register_static(SP_TYPE_OBJECT, "SPStyleElem", &info, (GTypeFlags) 0);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free return type;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freesp_style_elem_class_init(SPStyleElemClass *klass)
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parent_class = (SPObjectClass *)g_type_class_ref(SP_TYPE_OBJECT);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* FIXME */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free klass->build = sp_style_elem_build;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free klass->set = sp_style_elem_set;
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen klass->read_content = sp_style_elem_read_content;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free klass->write = sp_style_elem_write;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freesp_style_elem_init(SPStyleElem *style_elem)
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free media_set_all(style_elem->media);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free style_elem->is_css = false;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freesp_style_elem_set(SPObject *object, unsigned const key, gchar const *const value)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(object);
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen SPStyleElem &style_elem = *SP_STYLE_ELEM(object);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen switch (key) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free case SP_ATTR_TYPE: {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (!value) {
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen /* TODO: `type' attribute is required. Give error message as per
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free style_elem.is_css = false;
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen } else {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* fixme: determine what whitespace is allowed. Will probably need to ask on SVG
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free * list; though the relevant RFC may give info on its lexer. */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free style_elem.is_css = ( g_ascii_strncasecmp(value, "text/css", 8) == 0
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free && ( value[8] == '\0' ||
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free value[8] == ';' ) );
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free break;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#if 0 /* unfinished */
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen case SP_ATTR_MEDIA: {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_media(style_elem, value);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free break;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free#endif
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* title is ignored. */
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen default: {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (parent_class->set) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parent_class->set(object, key, value);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free break;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelenchild_add_rm_cb(Inkscape::XML::Node *, Inkscape::XML::Node *, Inkscape::XML::Node *,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free void *const data)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free sp_style_elem_read_content(static_cast<SPObject *>(data));
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
dca8db2be67c87ad222c2c58cca33d3e57f1b650tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freecontent_changed_cb(Inkscape::XML::Node *, gchar const *, gchar const *,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free void *const data)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen sp_style_elem_read_content(static_cast<SPObject *>(data));
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freechild_order_changed_cb(Inkscape::XML::Node *, Inkscape::XML::Node *,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free Inkscape::XML::Node *, Inkscape::XML::Node *,
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen void *const data)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free sp_style_elem_read_content(static_cast<SPObject *>(data));
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic Inkscape::XML::Node *
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freesp_style_elem_write(SPObject *const object, Inkscape::XML::Node *repr, guint const flags)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free repr = sp_repr_new("svg:style");
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_val_if_fail(object, repr);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free SPStyleElem &style_elem = *SP_STYLE_ELEM(object);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (flags & SP_OBJECT_WRITE_BUILD) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_warning("nyi: Forming <style> content for SP_OBJECT_WRITE_BUILD.");
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* fixme: Consider having the CRStyleSheet be a member of SPStyleElem, and then
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free pretty-print to a string s, then repr->addChild(sp_repr_new_text(s), NULL). */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (style_elem.is_css) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free repr->setAttribute("type", "text/css");
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free /* todo: media */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (((SPObjectClass *) parent_class)->write)
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen ((SPObjectClass *) parent_class)->write(object, repr, flags);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen return repr;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free/** Returns the concatenation of the content of the text children of the specified object. */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic GString *
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freeconcat_children(Inkscape::XML::Node const &repr)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free GString *ret = g_string_sized_new(0);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // effic: 0 is just to catch bugs. Increase to something reasonable.
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free for (Inkscape::XML::Node const *rch = repr.firstChild(); rch != NULL; rch = rch->next()) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if ( rch->type() == TEXT_NODE ) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ret = g_string_append(ret, rch->content());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free return ret;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free/* Callbacks for SAC-style libcroco parser. */
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freeenum StmtType { NO_STMT, FONT_FACE_STMT, NORMAL_RULESET_STMT };
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestruct ParseTmp
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRStyleSheet *const stylesheet;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free StmtType stmtType;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRStatement *currStmt;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free unsigned magic;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free static unsigned const ParseTmp_magic = 0x23474397; // from /dev/urandom
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen ParseTmp(CRStyleSheet *const stylesheet) :
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen stylesheet(stylesheet),
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen stmtType(NO_STMT),
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free currStmt(NULL),
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free magic(ParseTmp_magic)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free { }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free bool hasMagic() const {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free return magic == ParseTmp_magic;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ~ParseTmp()
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(hasMagic());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free magic = 0;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free};
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestart_selector_cb(CRDocHandler *a_handler,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRSelector *a_sel_list)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(a_handler && a_sel_list);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(a_handler->app_data != NULL);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(parse_tmp.hasMagic());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if ( (parse_tmp.currStmt != NULL)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free || (parse_tmp.stmtType != NO_STMT) ) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_warning("Expecting currStmt==NULL and stmtType==0 (NO_STMT) at start of ruleset, but found currStmt=%p, stmtType=%u",
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType));
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // fixme: Check whether we need to unref currStmt if non-NULL.
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRStatement *ruleset = cr_statement_new_ruleset(parse_tmp.stylesheet, a_sel_list, NULL, NULL);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(ruleset && ruleset->type == RULESET_STMT);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.stmtType = NORMAL_RULESET_STMT;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.currStmt = ruleset;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freeend_selector_cb(CRDocHandler *a_handler,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRSelector *a_sel_list)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(a_handler && a_sel_list);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(a_handler->app_data != NULL);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(parse_tmp.hasMagic());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRStatement *const ruleset = parse_tmp.currStmt;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (parse_tmp.stmtType == NORMAL_RULESET_STMT
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free && ruleset
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen && ruleset->type == RULESET_STMT
94bd7adc978850d91de1a92a8b5c05d01162a74cJohan B. C. Engelen && ruleset->kind.ruleset->sel_list == a_sel_list)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.stylesheet->statements = cr_statement_append(parse_tmp.stylesheet->statements,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ruleset);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free } else {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_warning("Found stmtType=%u, stmt=%p, stmt.type=%u, ruleset.sel_list=%p, a_sel_list=%p.",
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free unsigned(parse_tmp.stmtType),
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ruleset,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free unsigned(ruleset->type),
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ruleset->kind.ruleset->sel_list,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free a_sel_list);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.currStmt = NULL;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.stmtType = NO_STMT;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestart_font_face_cb(CRDocHandler *a_handler,
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free CRParsingLocation *)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(a_handler->app_data != NULL);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(parse_tmp.hasMagic());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (parse_tmp.stmtType != NO_STMT || parse_tmp.currStmt != NULL) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_warning("Expecting currStmt==NULL and stmtType==0 (NO_STMT) at start of @font-face, but found currStmt=%p, stmtType=%u",
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType));
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // fixme: Check whether we need to unref currStmt if non-NULL.
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.stmtType = FONT_FACE_STMT;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.currStmt = NULL;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free}
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freestatic void
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-freeend_font_face_cb(CRDocHandler *a_handler)
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free{
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(a_handler->app_data != NULL);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data);
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_return_if_fail(parse_tmp.hasMagic());
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free if (parse_tmp.stmtType != FONT_FACE_STMT || parse_tmp.currStmt != NULL) {
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free g_warning("Expecting currStmt==NULL and stmtType==1 (FONT_FACE_STMT) at end of @font-face, but found currStmt=%p, stmtType=%u",
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType));
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free // fixme: Check whether we need to unref currStmt if non-NULL.
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.currStmt = NULL;
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free }
895229950881e4c5be06fc7999ed0ef9aea62e92tavmjong-free parse_tmp.stmtType = NO_STMT;
}
static void
property_cb(CRDocHandler *const a_handler,
CRString *const a_name,
CRTerm *const a_value, int const a_important)
{
g_return_if_fail(a_handler && a_name);
g_return_if_fail(a_handler->app_data != NULL);
ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data);
g_return_if_fail(parse_tmp.hasMagic());
if (parse_tmp.stmtType == FONT_FACE_STMT) {
if (parse_tmp.currStmt != NULL) {
g_warning("Found non-NULL currStmt %p though stmtType==FONT_FACE_STMT.", parse_tmp.currStmt);
}
/* We currently ignore @font-face descriptors. */
return;
}
CRStatement *const ruleset = parse_tmp.currStmt;
g_return_if_fail(ruleset
&& ruleset->type == RULESET_STMT
&& parse_tmp.stmtType == NORMAL_RULESET_STMT);
CRDeclaration *const decl = cr_declaration_new(ruleset, cr_string_dup(a_name), a_value);
g_return_if_fail(decl);
decl->important = a_important;
CRStatus const append_status = cr_statement_ruleset_append_decl(ruleset, decl);
g_return_if_fail(append_status == CR_OK);
}
static void
sp_style_elem_read_content(SPObject *const object)
{
SPStyleElem &style_elem = *SP_STYLE_ELEM(object);
/* fixme: If there's more than one <style> element in a document, then the document stylesheet
* will be set to a random one of them, even switching between them.
*
* However, I don't see in the spec what's supposed to happen when there are multiple <style>
* elements. The wording suggests that <style>'s content should be a full stylesheet.
* http://www.w3.org/TR/REC-CSS2/cascade.html#cascade says that "The author specifies style
* sheets for a source document according to the conventions of the document language. For
* instance, in HTML, style sheets may be included in the document or linked externally."
* (Note the plural in both sentences.) Whereas libcroco's CRCascade allows only one author
* stylesheet. CRStyleSheet has no next/prev members that I can see, nor can I see any append
* stuff.
*
* Dodji replies "right, that's *bug*"; just an unexpected oversight.
*/
GString *const text = concat_children(*style_elem.repr);
CRParser *parser = cr_parser_new_from_buf(reinterpret_cast<guchar *>(text->str), text->len,
CR_UTF_8, FALSE);
/* I see a cr_statement_parse_from_buf for returning a CRStatement*, but no corresponding
cr_stylesheet_parse_from_buf. And cr_statement_parse_from_buf takes a char*, not a
CRInputBuf, and doesn't provide a way for calling it in a loop over the one buffer.
(I.e. it doesn't tell us where it got up to in the buffer.)
There's also the generic cr_parser_parse_stylesheet (or just cr_parser_parse), but that
just calls user-supplied callbacks rather than constructing a CRStylesheet.
*/
CRDocHandler *sac_handler = cr_doc_handler_new();
// impl: ref_count inited to 0, so cr_parser_destroy suffices to delete sac_handler.
g_return_if_fail(sac_handler); // out of memory
CRStyleSheet *const stylesheet = cr_stylesheet_new(NULL);
ParseTmp parse_tmp(stylesheet);
sac_handler->app_data = &parse_tmp;
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;
/* todo: start_media, end_media. */
/* todo: Test error condition. */
cr_parser_set_sac_handler(parser, sac_handler);
CRStatus const parse_status = cr_parser_parse(parser);
g_assert(sac_handler->app_data == &parse_tmp);
if (parse_status == CR_OK) {
cr_cascade_set_sheet(style_elem.document->style_cascade, stylesheet, ORIGIN_AUTHOR);
} else {
if (parse_status != CR_PARSING_ERROR) {
g_printerr("parsing error code=%u\n", unsigned(parse_status));
/* Better than nothing. TODO: Improve libcroco's error handling. At a minimum, add a
strerror-like function so that we can give a string rather than an integer. */
/* TODO: Improve error diagnosis stuff in inkscape. We'd like a panel showing the
errors/warnings/unsupported features of the current document. */
}
}
cr_parser_destroy(parser);
//object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
/**
* Does addListener(fns, data) on \a repr and all of its descendents.
*/
static void
rec_add_listener(Inkscape::XML::Node &repr,
Inkscape::XML::NodeEventVector const *const fns, void *const data)
{
repr.addListener(fns, data);
for (Inkscape::XML::Node *child = repr.firstChild(); child != NULL; child = child->next()) {
rec_add_listener(*child, fns, data);
}
}
static void
sp_style_elem_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
{
sp_style_elem_read_content(object);
sp_object_read_attr(object, "type");
sp_object_read_attr(object, "media");
static Inkscape::XML::NodeEventVector const nodeEventVector = {
child_add_rm_cb, // child_added
child_add_rm_cb, // child_removed
NULL, // attr_changed
content_changed_cb, // content_changed
child_order_changed_cb, // order_changed
};
rec_add_listener(*repr, &nodeEventVector, object);
if (((SPObjectClass *) parent_class)->build) {
((SPObjectClass *) parent_class)->build(object, document, repr);
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :