return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- x = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &x);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- y = svgtiny_parse_length(attr, state.viewport_height, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_height,
+ &y);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- r = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &r);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- x = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &x);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- y = svgtiny_parse_length(attr, state.viewport_height, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_height,
+ &y);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- rx = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &rx);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- ry = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &ry);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- x1 = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &x1);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- y1 = svgtiny_parse_length(attr, state.viewport_height, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_height,
+ &y1);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- x2 = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ &x2);
}
dom_string_unref(attr);
return svgtiny_LIBDOM_ERROR;
}
if (attr != NULL) {
- y2 = svgtiny_parse_length(attr, state.viewport_height, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_height,
+ &y2);
}
dom_string_unref(attr);
exc = dom_element_get_attribute(node, state.interned_x, &attr);
if (exc == DOM_NO_ERR && attr != NULL) {
- *x = svgtiny_parse_length(attr, state.viewport_width, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ x);
dom_string_unref(attr);
}
exc = dom_element_get_attribute(node, state.interned_y, &attr);
if (exc == DOM_NO_ERR && attr != NULL) {
- *y = svgtiny_parse_length(attr, state.viewport_height, state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_height,
+ y);
dom_string_unref(attr);
}
exc = dom_element_get_attribute(node, state.interned_width, &attr);
if (exc == DOM_NO_ERR && attr != NULL) {
- *width = svgtiny_parse_length(attr, state.viewport_width,
- state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_width,
+ width);
dom_string_unref(attr);
}
exc = dom_element_get_attribute(node, state.interned_height, &attr);
if (exc == DOM_NO_ERR && attr != NULL) {
- *height = svgtiny_parse_length(attr, state.viewport_height,
- state);
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state.viewport_height,
+ height);
dom_string_unref(attr);
}
}
-/**
- * Parse a length as a number of pixels.
- */
-
-static float _svgtiny_parse_length(const char *s, int viewport_size,
- const struct svgtiny_parse_state state)
-{
- int num_length = strspn(s, "0123456789+-.");
- const char *unit = s + num_length;
- float n = atof((const char *) s);
- float font_size = 20; /*css_len2px(&state.style.font_size.value.length, 0);*/
-
- UNUSED(state);
-
- if (unit[0] == 0) {
- return n;
- } else if (unit[0] == '%') {
- return n / 100.0 * viewport_size;
- } else if (unit[0] == 'e' && unit[1] == 'm') {
- return n * font_size;
- } else if (unit[0] == 'e' && unit[1] == 'x') {
- return n / 2.0 * font_size;
- } else if (unit[0] == 'p' && unit[1] == 'x') {
- return n;
- } else if (unit[0] == 'p' && unit[1] == 't') {
- return n * 1.25;
- } else if (unit[0] == 'p' && unit[1] == 'c') {
- return n * 15.0;
- } else if (unit[0] == 'm' && unit[1] == 'm') {
- return n * 3.543307;
- } else if (unit[0] == 'c' && unit[1] == 'm') {
- return n * 35.43307;
- } else if (unit[0] == 'i' && unit[1] == 'n') {
- return n * 90;
- }
-
- return 0;
-}
-
-float svgtiny_parse_length(dom_string *s, int viewport_size,
- const struct svgtiny_parse_state state)
-{
- char *ss = strndup(dom_string_data(s), dom_string_byte_length(s));
- float ret = _svgtiny_parse_length(ss, viewport_size, state);
- free(ss);
- return ret;
-}
-
/**
* Parse paint attributes, if present.
*/
-
void svgtiny_parse_paint_attributes(dom_element *node,
struct svgtiny_parse_state *state)
{
exc = dom_element_get_attribute(node, state->interned_stroke_width, &attr);
if (exc == DOM_NO_ERR && attr != NULL) {
- state->stroke_width = svgtiny_parse_length(attr,
- state->viewport_width, *state);
+ float stroke_width;
+ svgtiny_parse_length(dom_string_data(attr),
+ dom_string_byte_length(attr),
+ state->viewport_width,
+ &stroke_width);
+ state->stroke_width = stroke_width;
dom_string_unref(attr);
}
}
if ((s = strstr(style, "stroke-width:"))) {
s += 13;
- while (*s == ' ')
- s++;
- value = strndup(s, strcspn(s, "; "));
- state->stroke_width = _svgtiny_parse_length(value,
- state->viewport_width, *state);
- free(value);
+ float stroke_width;
+ svgtiny_parse_length(s,
+ strcspn(s, "; "),
+ state->viewport_width,
+ &stroke_width);
+ state->stroke_width = stroke_width;
}
free(style);
dom_string_unref(attr);
grad->gradient_transform.d = 1;
grad->gradient_transform.e = 0;
grad->gradient_transform.f = 0;
-
+
exc = dom_string_create_interned((const uint8_t *) id,
strlen(id), &id_str);
if (exc != DOM_NO_ERR)
return;
-
+
exc = dom_document_get_element_by_id(state->document, id_str,
&gradient);
dom_string_unref(id_str);
#endif
return;
}
-
+
exc = dom_node_get_node_name(gradient, &name);
if (exc != DOM_NO_ERR) {
dom_node_unref(gradient);
return;
}
-
+
if (dom_string_isequal(name, state->interned_linearGradient))
svgtiny_parse_linear_gradient(gradient, grad, state);
-
+
dom_node_unref(gradient);
dom_string_unref(name);
dom_string *attr;
dom_exception exc;
dom_nodelist *stops;
-
+
exc = dom_element_get_attribute(linear, state->interned_href, &attr);
if (exc == DOM_NO_ERR && attr != NULL) {
if (dom_string_data(attr)[0] == (uint8_t) '#') {
grad->gradient_y2 = attr;
attr = NULL;
}
-
+
exc = dom_element_get_attribute(linear, state->interned_gradientUnits,
&attr);
if (exc == DOM_NO_ERR && attr != NULL) {
- grad->gradient_user_space_on_use =
+ grad->gradient_user_space_on_use =
dom_string_isequal(attr,
state->interned_userSpaceOnUse);
dom_string_unref(attr);
}
-
+
exc = dom_element_get_attribute(linear,
state->interned_gradientTransform,
&attr);
grad->gradient_transform.f = f;
dom_string_unref(attr);
}
-
+
exc = dom_element_get_elements_by_tag_name(linear,
state->interned_stop,
&stops);
dom_nodelist_unref(stops);
goto no_more_stops;
}
-
+
for (stopnr = 0; stopnr < listlen; ++stopnr) {
dom_element *stop;
float offset = -1;
if (i == svgtiny_MAX_STOPS)
break;
}
-
+
dom_nodelist_unref(stops);
}
no_more_stops:
#endif
if (!grad->gradient_user_space_on_use) {
- gradient_x0 = object_x0 +
- svgtiny_parse_length(grad->gradient_x1,
- object_x1 - object_x0, *state);
- gradient_y0 = object_y0 +
- svgtiny_parse_length(grad->gradient_y1,
- object_y1 - object_y0, *state);
- gradient_x1 = object_x0 +
- svgtiny_parse_length(grad->gradient_x2,
- object_x1 - object_x0, *state);
- gradient_y1 = object_y0 +
- svgtiny_parse_length(grad->gradient_y2,
- object_y1 - object_y0, *state);
+ svgtiny_parse_length(dom_string_data(grad->gradient_x1),
+ dom_string_byte_length(grad->gradient_x1),
+ object_x1 - object_x0,
+ &gradient_x0);
+ gradient_x0 += object_x0;
+
+ svgtiny_parse_length(dom_string_data(grad->gradient_y1),
+ dom_string_byte_length(grad->gradient_y1),
+ object_y1 - object_y0,
+ &gradient_y0);
+ gradient_y0 += object_y0;
+
+ svgtiny_parse_length(dom_string_data(grad->gradient_x2),
+ dom_string_byte_length(grad->gradient_x2),
+ object_x1 - object_x0,
+ &gradient_x1);
+ gradient_x1 += object_x0;
+
+ svgtiny_parse_length(dom_string_data(grad->gradient_y2),
+ dom_string_byte_length(grad->gradient_y2),
+ object_y1 - object_y0,
+ &gradient_y1);
+ gradient_y1 += object_y0;
} else {
- gradient_x0 = svgtiny_parse_length(grad->gradient_x1,
- state->viewport_width, *state);
- gradient_y0 = svgtiny_parse_length(grad->gradient_y1,
- state->viewport_height, *state);
- gradient_x1 = svgtiny_parse_length(grad->gradient_x2,
- state->viewport_width, *state);
- gradient_y1 = svgtiny_parse_length(grad->gradient_y2,
- state->viewport_height, *state);
+ svgtiny_parse_length(dom_string_data(grad->gradient_x1),
+ dom_string_byte_length(grad->gradient_x1),
+ state->viewport_width,
+ &gradient_x0);
+ svgtiny_parse_length(dom_string_data(grad->gradient_y1),
+ dom_string_byte_length(grad->gradient_y1),
+ state->viewport_height,
+ &gradient_y0);
+ svgtiny_parse_length(dom_string_data(grad->gradient_x2),
+ dom_string_byte_length(grad->gradient_x2),
+ state->viewport_width,
+ &gradient_x1);
+ svgtiny_parse_length(dom_string_data(grad->gradient_y2),
+ dom_string_byte_length(grad->gradient_y2),
+ state->viewport_height,
+ &gradient_y1);
}
gradient_dx = gradient_x1 - gradient_x0;
gradient_dy = gradient_y1 - gradient_y0;
return svgtiny_OK;
}
-
+
/* render triangles */
stop_count = grad->linear_gradient_stop_count;
assert(2 <= stop_count);
inv[4] = (m[2]*m[5] - m[3]*m[4]) / determinant;
inv[5] = (m[1]*m[4] - m[0]*m[5]) / determinant;
}
-
return svgtiny_OK;
}
+
+
+/**
+ * Parse a length as a number of pixels.
+ */
+svgtiny_code
+svgtiny_parse_length(const char *text,
+ size_t textlen,
+ int viewport_size,
+ float *length)
+{
+ svgtiny_code err;
+ float number;
+ const char *unit = NULL;
+ int unitlen;
+ float font_size = 20; /*css_len2px(&state.style.font_size.value.length, 0);*/
+
+ err = svgtiny_parse_number(text, textlen, &unit, &number);
+ if (err != svgtiny_OK) {
+ unitlen = -1;
+ } else {
+ unitlen = (text + textlen) - unit;
+ }
+
+ /* discount whitespace on the end of the unit */
+ while(unitlen > 0) {
+ if ((unit[unitlen - 1] != 0x20) &&
+ (unit[unitlen - 1] != 0x09) &&
+ (unit[unitlen - 1] != 0x0A) &&
+ (unit[unitlen - 1] != 0x0D)) {
+ break;
+ }
+ unitlen--;
+ }
+
+ /* decode the unit */
+ *length = 0;
+ switch (unitlen) {
+ case 0:
+ /* no unit, assume pixels */
+ *length = number;
+ break;
+ case 1:
+ if (unit[0] == '%') {
+ /* percentage of viewport */
+ *length = number / 100.0 * viewport_size;
+ }
+ break;
+
+ case 2:
+ if (unit[0] == 'e' && unit[1] == 'm') {
+ *length = number * font_size;
+ } else if (unit[0] == 'e' && unit[1] == 'x') {
+ *length = number / 2.0 * font_size;
+ } else if (unit[0] == 'p' && unit[1] == 'x') {
+ *length = number;
+ } else if (unit[0] == 'p' && unit[1] == 't') {
+ *length = number * 1.25;
+ } else if (unit[0] == 'p' && unit[1] == 'c') {
+ *length = number * 15.0;
+ } else if (unit[0] == 'm' && unit[1] == 'm') {
+ *length = number * 3.543307;
+ } else if (unit[0] == 'c' && unit[1] == 'm') {
+ *length = number * 35.43307;
+ } else if (unit[0] == 'i' && unit[1] == 'n') {
+ *length = number * 90;
+ }
+ break;
+
+ default:
+ /* unknown unit */
+ break;
+ }
+
+ return svgtiny_OK;
+}