summaryrefslogtreecommitdiff
path: root/src/treebuilder
diff options
context:
space:
mode:
authorAndrew Sidwell <andy@entai.co.uk>2008-07-11 18:34:36 +0000
committerAndrew Sidwell <andy@entai.co.uk>2008-07-11 18:34:36 +0000
commit421e7d357831d852bb5ce50bd1729cad12b13dbf (patch)
treeffe6e32797d170c5e3627c6227e764a52b96d12a /src/treebuilder
parent76eeba6e538eb6ca44910bdfb5c1900cfb78b076 (diff)
downloadlibhubbub-421e7d357831d852bb5ce50bd1729cad12b13dbf.tar.gz
libhubbub-421e7d357831d852bb5ce50bd1729cad12b13dbf.tar.bz2
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
Diffstat (limited to 'src/treebuilder')
-rw-r--r--src/treebuilder/in_body.c9
-rw-r--r--src/treebuilder/in_foreign_content.c184
-rw-r--r--src/treebuilder/internal.h7
-rw-r--r--src/treebuilder/treebuilder.c73
4 files changed, 200 insertions, 73 deletions
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