static svg_status_t _svg_style_split_nv_pair_alloc (const char *nv_pair, char **name, char **value) { char *colon; const char *v_start; *name = strdup (nv_pair); if (*name == NULL) return SVG_STATUS_NO_MEMORY; colon = strchr (*name, ':'); if (colon == NULL) { free (*name); *name = NULL; *value = NULL; return SVG_STATUS_PARSE_ERROR; } *colon = '\0'; v_start = nv_pair + (colon - (char *) *name) + 1; while (_svg_ascii_isspace (*v_start)) v_start++; *value = strdup (v_start); if (*value == NULL) return SVG_STATUS_NO_MEMORY; return SVG_STATUS_SUCCESS; }
void _svg_str_skip_space (const char **str) { const char *s = *str; while (_svg_ascii_isspace (*s)) s++; *str = s; }
void _svg_str_skip_space_or_char (const char **str, char c) { const char *s = *str; while (_svg_ascii_isspace (*s) || *s == c) s++; *str = s; }
/* The following parse function is: Copyright (C) 2000 Eazel, Inc. Copyright (C) 2002 Dom Lachowicz <*****@*****.**> Author: Raph Levien <*****@*****.**> Parse an SVG transform string into an affine matrix. Reference: SVG working draft dated 1999-07-06, section 8.5. */ extern svg_status_t _svg_transform_parse_str (svg_transform_t *transform, const char *str) { intptr_t idx; svg_status_t status; char keyword[32]; double args[6]; int n_args; unsigned int key_len; svg_transform_t tmp_transform; status = _svg_transform_init (transform); if (status) return status; idx = 0; while (str[idx]) { /* skip initial whitespace */ while (_svg_ascii_isspace (str[idx]) || str[idx] == ',') idx++; /* parse keyword */ for (key_len = 0; key_len < sizeof (keyword); key_len++) { char c; c = str[idx]; if (_svg_ascii_isalpha (c) || c == '-') keyword[key_len] = str[idx++]; else break; } /* XXX: This size limitation looks bogus */ if (key_len >= sizeof (keyword)) return SVG_STATUS_PARSE_ERROR; keyword[key_len] = '\0'; /* skip whitespace */ while (_svg_ascii_isspace (str[idx])) idx++; if (str[idx] != '(') return SVG_STATUS_PARSE_ERROR; idx++; for (n_args = 0; ; n_args++) { char c; const char *end_ptr; /* skip whitespace */ while (_svg_ascii_isspace (str[idx])) idx++; c = str[idx]; if (_svg_ascii_isdigit (c) || c == '+' || c == '-' || c == '.') { if (n_args == SVG_ARRAY_SIZE (args)) return SVG_STATUS_PARSE_ERROR; args[n_args] = _svg_ascii_strtod (str + idx, &end_ptr); idx = end_ptr - str; while (_svg_ascii_isspace (str[idx])) idx++; /* skip optional comma */ if (str[idx] == ',') idx++; } else if (c == ')') break; else return SVG_STATUS_PARSE_ERROR; } idx++; /* ok, have parsed keyword and args, now modify the transform */ if (strcmp (keyword, "matrix") == 0) { if (n_args != 6) return SVG_STATUS_PARSE_ERROR; _svg_transform_init_matrix (&tmp_transform, args[0], args[1], args[2], args[3], args[4], args[5]); _svg_transform_multiply_into_right (&tmp_transform, transform); } else if (strcmp (keyword, "translate") == 0) { if (n_args == 1) args[1] = 0; else if (n_args != 2) return SVG_STATUS_PARSE_ERROR; _svg_transform_add_translate (transform, args[0], args[1]); } else if (strcmp (keyword, "scale") == 0) { if (n_args == 1) args[1] = args[0]; else if (n_args != 2) return SVG_STATUS_PARSE_ERROR; _svg_transform_add_scale (transform, args[0], args[1]); } else if (strcmp (keyword, "rotate") == 0) { if (n_args != 1) return SVG_STATUS_PARSE_ERROR; _svg_transform_add_rotate (transform, args[0]); } else if (strcmp (keyword, "skewX") == 0) { if (n_args != 1) return SVG_STATUS_PARSE_ERROR; _svg_transform_add_skew_x (transform, args[0]); } else if (strcmp (keyword, "skewY") == 0) { if (n_args != 1) return SVG_STATUS_PARSE_ERROR; _svg_transform_add_skew_y (transform, args[0]); } else return SVG_STATUS_PARSE_ERROR; } return SVG_STATUS_SUCCESS; }
/** * svg_ascii_strtod: * @nptr: the string to convert to a numeric value. * @endptr: if non-%NULL, it returns the character after * the last character used in the conversion. * * Converts a string to a #double value. * This function behaves like the standard strtod() function * does in the C locale. It does this without actually * changing the current locale, since that would not be * thread-safe. * * This function is typically used when reading configuration files or * other non-user input that should be locale independent. To handle * input from the user you should normally use the locale-sensitive * system strtod() function. * * If the correct value would cause overflow, plus or minus %HUGE_VAL * is returned (according to the sign of the value), and %ERANGE is * stored in %errno. If the correct value would cause underflow, * zero is returned and %ERANGE is stored in %errno. * * This function resets %errno before calling strtod() so that * you can reliably detect overflow and underflow. * * Return value: the #double value. **/ double _svg_ascii_strtod (const char *nptr, const char **endptr) { char *fail_pos; double val; struct lconv *locale_data; const char *decimal_point; long decimal_point_len; const char *p, *decimal_point_pos; const char *end = NULL; /* Silence gcc */ if (nptr == NULL) return 0; fail_pos = NULL; locale_data = localeconv (); decimal_point = locale_data->decimal_point; decimal_point_len = strlen (decimal_point); decimal_point_pos = NULL; if (decimal_point[0] != '.' || decimal_point[1] != 0) { p = nptr; /* Skip leading space */ while (_svg_ascii_isspace (*p)) p++; /* Skip leading optional sign */ if (*p == '+' || *p == '-') p++; if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; /* HEX - find the (optional) decimal point */ while (_svg_ascii_isxdigit (*p)) p++; if (*p == '.') { decimal_point_pos = p++; while (_svg_ascii_isxdigit (*p)) p++; if (*p == 'p' || *p == 'P') p++; if (*p == '+' || *p == '-') p++; while (_svg_ascii_isdigit (*p)) p++; end = p; } } else { while (_svg_ascii_isdigit (*p)) p++; if (*p == '.') { decimal_point_pos = p++; while (_svg_ascii_isdigit (*p)) p++; if (*p == 'e' || *p == 'E') p++; if (*p == '+' || *p == '-') p++; while (_svg_ascii_isdigit (*p)) p++; end = p; } } /* For the other cases, we need not convert the decimal point */ } /* Set errno to zero, so that we can distinguish zero results and underflows */ errno = 0; if (decimal_point_pos) { char *copy, *c; /* We need to convert the '.' to the locale specific decimal point */ copy = malloc (end - nptr + 1 + decimal_point_len); c = copy; memcpy (c, nptr, decimal_point_pos - nptr); c += decimal_point_pos - nptr; memcpy (c, decimal_point, decimal_point_len); c += decimal_point_len; memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); c += end - (decimal_point_pos + 1); *c = 0; val = strtod (copy, &fail_pos); if (fail_pos) { if (fail_pos > decimal_point_pos) fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1); else fail_pos = (char *)nptr + (fail_pos - copy); } free (copy); } else val = strtod (nptr, &fail_pos); if (endptr) *endptr = fail_pos; return val; }