From 421e7d357831d852bb5ce50bd1729cad12b13dbf Mon Sep 17 00:00:00 2001 From: Andrew Sidwell Date: Fri, 11 Jul 2008 18:34:36 +0000 Subject: Make at least a good start on SVG support (commented-out in the spec). Move foreign attribute name processing to in_foreign_content.c. svn path=/trunk/hubbub/; revision=4614 --- src/treebuilder/in_body.c | 9 +- src/treebuilder/in_foreign_content.c | 184 +++++++++++++++++++++++++++++++++++ src/treebuilder/internal.h | 7 +- src/treebuilder/treebuilder.c | 73 +------------- 4 files changed, 200 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/treebuilder/in_body.c b/src/treebuilder/in_body.c index c6c907d..f45e2c8 100644 --- a/src/treebuilder/in_body.c +++ b/src/treebuilder/in_body.c @@ -315,13 +315,18 @@ bool process_start_tag(hubbub_treebuilder *treebuilder, } } else if (type == RP || type == RT) { /** \todo ruby */ - } else if (type == MATH) { + } else if (type == MATH || type == SVG) { hubbub_tag tag = token->data.tag; reconstruct_active_formatting_list(treebuilder); adjust_foreign_attributes(treebuilder, &tag); - tag.ns = HUBBUB_NS_MATHML; + if (type == SVG) { + adjust_svg_attributes(treebuilder, &tag); + tag.ns = HUBBUB_NS_SVG; + } else { + tag.ns = HUBBUB_NS_MATHML; + } if (token->data.tag.self_closing) { insert_element_no_push(treebuilder, &tag); diff --git a/src/treebuilder/in_foreign_content.c b/src/treebuilder/in_foreign_content.c index c400c1f..ac42b4a 100644 --- a/src/treebuilder/in_foreign_content.c +++ b/src/treebuilder/in_foreign_content.c @@ -12,6 +12,190 @@ #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" +#include "utils/string.h" + + +/*** Attribute-correction stuff ***/ + +#define S(s) s, SLEN(s) + +static const struct +{ + const char *attr; + size_t attr_len; + const char *proper; +} svg_attributes[] = { + { S("attributename"), "attributeName" }, + { S("attributetype"), "attributeType" }, + { S("basefrequency"), "baseFrequency" }, + { S("baseprofile"), "baseProfile" }, + { S("calcmode"), "calcMode" }, + { S("clippathunits"), "clipPathUnits" }, + { S("contentscripttype"), "contentScriptType" }, + { S("contentstyletype"), "contentStyleType" }, + { S("diffuseconstant"), "diffuseConstant" }, + { S("edgemode"), "edgeMode" }, + { S("externalresourcesrequired"), "externalResourcesRequired" }, + { S("filterres"), "filterRes" }, + { S("filterunits"), "filterUnits" }, + { S("glyphref"), "glyphRef" }, + { S("gradienttransform"), "gradientTransform" }, + { S("gradientunits"), "gradientUnits" }, + { S("kernelmatrix"), "kernelMatrix" }, + { S("kernelunitlength"), "kernelUnitLength" }, + { S("keypoints"), "keyPoints" }, + { S("keysplines"), "keySplines" }, + { S("keytimes"), "keyTimes" }, + { S("lengthadjust"), "lengthAdjust" }, + { S("limitingconeangle"), "limitingConeAngle" }, + { S("markerheight"), "markerHeight" }, + { S("markerunits"), "markerUnits" }, + { S("markerwidth"), "markerWidth" }, + { S("maskcontentunits"), "maskContentUnits" }, + { S("maskunits"), "maskUnits" }, + { S("numoctaves"), "numOctaves" }, + { S("pathlength"), "pathLength" }, + { S("patterncontentunits"), "patternContentUnits" }, + { S("patterntransform"), "patternTransform" }, + { S("patternunits"), "patternUnits" }, + { S("pointsatx"), "pointsAtX" }, + { S("pointsaty"), "pointsAtY" }, + { S("pointsatz"), "pointsAtZ" }, + { S("preservealpha"), "preserveAlpha" }, + { S("preserveaspectratio"), "preserveAspectRatio" }, + { S("primitiveunits"), "primitiveUnits" }, + { S("refx"), "refX" }, + { S("refy"), "refY" }, + { S("repeatcount"), "repeatCount" }, + { S("repeatdur"), "repeatDur" }, + { S("requiredextensions"), "requiredExtensions" }, + { S("requiredfeatures"), "requiredFeatures" }, + { S("specularconstant"), "specularConstant" }, + { S("specularexponent"), "specularExponent" }, + { S("spreadmethod"), "spreadMethod" }, + { S("startoffset"), "startOffset" }, + { S("stddeviation"), "stdDeviation" }, + { S("stitchtiles"), "stitchTiles" }, + { S("surfacescale"), "surfaceScale" }, + { S("systemlanguage"), "systemLanguage" }, + { S("tablevalues"), "tableValues" }, + { S("targetx"), "targetX" }, + { S("targety"), "targetY" }, + { S("textlength"), "textLength" }, + { S("viewbox"), "viewBox" }, + { S("viewtarget"), "viewTarget" }, + { S("xchannelselector"), "xChannelSelector" }, + { S("ychannelselector"), "yChannelSelector" }, + { S("zoomandpan"), "zoomAndPan" }, +}; + +#undef S + +#define N_ELEMENTS(x) (sizeof(x) / sizeof((x)[0])) + + +/** + * Adjust SVG attributes. + * + * \param treebuilder Treebuilder instance + * \param tag Tag to adjust the attributes of + */ +void adjust_svg_attributes(hubbub_treebuilder *treebuilder, + hubbub_tag *tag) +{ + for (size_t i = 0; i < tag->n_attributes; i++) { + hubbub_attribute *attr = &tag->attributes[i]; + + uint8_t *name = (uint8_t *) treebuilder->input_buffer + + attr->name.data.off; + size_t len = attr->name.len; + + for (size_t j = 0; j < N_ELEMENTS(svg_attributes); j++) { + if (hubbub_string_match(name, len, + (uint8_t *)svg_attributes[j].attr, + svg_attributes[j].attr_len)) { + attr->name.type = HUBBUB_STRING_PTR; + attr->name.data.ptr = + (uint8_t *)svg_attributes[j].proper; + } + } + } +} + + + +#define S(s) (uint8_t *) s, SLEN(s) + +/** + * Adjust foreign attributes. + * + * \param treebuilder Treebuilder instance + * \param tag Tag to adjust the attributes of + */ +void adjust_foreign_attributes(hubbub_treebuilder *treebuilder, + hubbub_tag *tag) +{ + for (size_t i = 0; i < tag->n_attributes; i++) { + hubbub_attribute *attr = &tag->attributes[i]; + const uint8_t *name = treebuilder->input_buffer + + attr->name.data.off; + + /* 10 == strlen("xlink:href") */ + if (attr->name.len >= 10 && + strncmp((char *) name, "xlink:", + SLEN("xlink:")) == 0) { + size_t len = attr->name.len - 6; + name += 6; + + if (hubbub_string_match(name, len, S("actutate")) || + hubbub_string_match(name, len, + S("arcrole")) || + hubbub_string_match(name, len, + S("href")) || + hubbub_string_match(name, len, + S("role")) || + hubbub_string_match(name, len, + S("show")) || + hubbub_string_match(name, len, + S("title")) || + hubbub_string_match(name, len, + S("type"))) { + attr->ns = HUBBUB_NS_XLINK; + attr->name.data.off += 6; + attr->name.len -= 6; + } + /* 8 == strlen("xml:base") */ + } else if (attr->name.len >= 8 && + strncmp((char *) name, "xml:", SLEN("xml:")) == 0) { + size_t len = attr->name.len - 4; + name += 4; + + if (hubbub_string_match(name, len, S("base")) || + hubbub_string_match(name, len, + S("lang")) || + hubbub_string_match(name, len, + S("space"))) { + attr->ns = HUBBUB_NS_XML; + attr->name.data.off += 4; + attr->name.len -= 4; + } + } else if (hubbub_string_match(name, attr->name.len, + S("xmlns")) || + hubbub_string_match(name, attr->name.len, + S("xmlns:xlink"))) { + attr->ns = HUBBUB_NS_XMLNS; + attr->name.data.off += 6; + attr->name.len -= 6; + } + + } +} + +#undef S + + + +/*** Foreign content insertion mode ***/ /** diff --git a/src/treebuilder/internal.h b/src/treebuilder/internal.h index 04ef26b..3d65db7 100644 --- a/src/treebuilder/internal.h +++ b/src/treebuilder/internal.h @@ -30,6 +30,8 @@ typedef enum CODE, LABEL, RP, RT, RUBY, SPAN, SUB, SUP, VAR, XMP, /* MathML */ MATH, MGLYPH, MALIGNMARK, MI, MO, MN, MS, MTEXT, +/* SVG */ + SVG, UNKNOWN, } element_type; @@ -172,10 +174,13 @@ bool formatting_list_replace(hubbub_treebuilder *treebuilder, element_type type, void *node, uint32_t stack_index, element_type *otype, void **onode, uint32_t *ostack_index); +/* in_foreign_content.c */ +void adjust_svg_attributes(hubbub_treebuilder *treebuilder, + hubbub_tag *tag); void adjust_foreign_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag); -/* This one's in in_body.c */ +/* in_body.c */ void aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node); #ifndef NDEBUG diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c index 799c914..516c28e 100644 --- a/src/treebuilder/treebuilder.c +++ b/src/treebuilder/treebuilder.c @@ -38,7 +38,7 @@ static const struct { { "IMAGE", IMAGE }, { "IMG", IMG }, { "INPUT", INPUT }, { "ISINDEX", ISINDEX }, { "LI", LI }, { "LINK", LINK }, - { "LISTING", LISTING }, { "MATH", MATH }, + { "LISTING", LISTING }, { "MENU", MENU }, { "META", META }, { "NOEMBED", NOEMBED }, { "NOFRAMES", NOFRAMES }, { "NOSCRIPT", NOSCRIPT }, @@ -63,8 +63,8 @@ static const struct { { "NOBR", NOBR }, { "S", S }, { "SMALL", SMALL }, { "STRIKE", STRIKE }, { "STRONG", STRONG }, { "TT", TT }, - { "U", U }, - { "XMP", XMP }, + { "U", U }, { "XMP", XMP }, + { "MATH", MATH }, { "SVG", SVG }, }; @@ -1348,73 +1348,6 @@ bool formatting_list_replace(hubbub_treebuilder *treebuilder, return true; } -/** - * Adjust foreign attributes. - * - * \param treebuilder Treebuilder instance - * \param tag Tag to adjust the attributes of - */ -void adjust_foreign_attributes(hubbub_treebuilder *treebuilder, - hubbub_tag *tag) -{ - for (size_t i = 0; i < tag->n_attributes; i++) { - hubbub_attribute *attr = &tag->attributes[i]; - const uint8_t *name = treebuilder->input_buffer + - attr->name.data.off; - -#define S(s) (uint8_t *) s, SLEN(s) - - /* 10 == strlen("xlink:href") */ - if (attr->name.len >= 10 && - strncmp((char *) name, "xlink:", - SLEN("xlink:")) == 0) { - size_t len = attr->name.len - 6; - name += 6; - - if (hubbub_string_match(name, len, S("actutate")) || - hubbub_string_match(name, len, - S("arcrole")) || - hubbub_string_match(name, len, - S("href")) || - hubbub_string_match(name, len, - S("role")) || - hubbub_string_match(name, len, - S("show")) || - hubbub_string_match(name, len, - S("title")) || - hubbub_string_match(name, len, - S("type"))) { - attr->ns = HUBBUB_NS_XLINK; - attr->name.data.off += 6; - attr->name.len -= 6; - } - /* 8 == strlen("xml:base") */ - } else if (attr->name.len >= 8 && - strncmp((char *) name, "xml:", SLEN("xml:")) == 0) { - size_t len = attr->name.len - 4; - name += 4; - - if (hubbub_string_match(name, len, S("base")) || - hubbub_string_match(name, len, - S("lang")) || - hubbub_string_match(name, len, - S("space"))) { - attr->ns = HUBBUB_NS_XML; - attr->name.data.off += 4; - attr->name.len -= 4; - } - } else if (hubbub_string_match(name, attr->name.len, - S("xmlns")) || - hubbub_string_match(name, attr->name.len, - S("xmlns:xlink"))) { - attr->ns = HUBBUB_NS_XMLNS; - attr->name.data.off += 6; - attr->name.len -= 6; - } - -#undef S - } -} #ifndef NDEBUG -- cgit v1.2.3