/* Parse a CSS2 style argument */ static svg_status_t _svg_style_parse_nv_pair (svg_style_t *style, const char *nv_pair) { unsigned int i; char *name, *value; svg_status_t status; status = _svg_style_split_nv_pair_alloc (nv_pair, &name, &value); if (status) return status; /* guilty until proven innocent */ /* XXX: Check SVG spec. for this error condition */ status = SVG_STATUS_PARSE_ERROR; for (i=0; i < SVG_ARRAY_SIZE(SVG_STYLE_PARSE_MAP); i++) if (strcmp (SVG_STYLE_PARSE_MAP[i].name, name) == 0) { status = (SVG_STYLE_PARSE_MAP[i].parse) (style, value); break; } free (name); free (value); return status; }
svg_status_t _svg_style_apply_attributes (svg_style_t *style, const char **attributes) { unsigned int i; svg_status_t status; const char *style_str, *str; _svg_attribute_get_string (attributes, "style", &style_str, NULL); if (style_str) { status = _svg_style_parse_style_str (style, style_str); if (status) return status; } for (i=0; i < SVG_ARRAY_SIZE(SVG_STYLE_PARSE_MAP); i++) { const svg_style_parse_map_t *map; map = &SVG_STYLE_PARSE_MAP[i]; _svg_attribute_get_string (attributes, map->name, &str, NULL); if (str) { status = (map->parse) (style, str); if (status) return status; } } return SVG_STATUS_SUCCESS; }
void _svg_parser_sax_start_element (void *closure, const xmlChar *name_unsigned, const xmlChar **attributes_unsigned) { unsigned int i; svg_parser_t *parser = closure; const svg_parser_cb_t *cb; svg_element_t *element; const char *name = (const char *) name_unsigned; const char **attributes = (const char **) attributes_unsigned; if (parser->unknown_element_depth) { parser->unknown_element_depth++; return; } cb = NULL; for (i=0; i < SVG_ARRAY_SIZE (SVG_PARSER_MAP); i++) { if (strcmp (SVG_PARSER_MAP[i].name, name) == 0) { cb = &SVG_PARSER_MAP[i].cb; break; } } if (cb == NULL) { parser->unknown_element_depth++; return; } parser->status = _svg_parser_push_state (parser, cb); if (parser->status) return; parser->status = (cb->parse_element) (parser, attributes, &element); if (parser->status) { if (parser->status == SVGINT_STATUS_UNKNOWN_ELEMENT) parser->status = SVG_STATUS_SUCCESS; return; } parser->status = _svg_element_apply_attributes (element, attributes); if (parser->status) return; if (element->id) _svg_store_element_by_id (parser->svg, element); return; }
svg_status_t _svg_style_init_defaults (svg_style_t *style, svg_t *svg) { int i; svg_status_t status; style->svg = svg; for (i=0; i < SVG_ARRAY_SIZE(SVG_STYLE_PARSE_MAP); i++) { const svg_style_parse_map_t *map; map = &SVG_STYLE_PARSE_MAP[i]; if (map->default_value) { status = (map->parse) (style, map->default_value); if (status) return status; } } return SVG_STATUS_SUCCESS; }
/* 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; }
svgItem* svgParsePath( xmlNodePtr ptXmlNode ) { svgItem *ptItem = NULL; char *szValue, szField[ 16 ]; const char *szFieldStart; svgPathCommand *ptPathCmd, *ptLastPathCmd = NULL; unsigned int uiCmdIdx; int8 iI; svgLength atArgs[ 12 ]; if( ptXmlNode==NULL ) return NULL; if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_PATH )!=0 ) return NULL; // Read common values to all kind of item ptItem = svgNewItem( ptXmlNode ); if( ptItem==NULL ) return NULL; ptItem->tKind = SVG_ITEM_KIND_PATH; // d if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"d" ) )!=NULL ) { ptLastPathCmd = NULL; szFieldStart = svgGetNextPathField( szValue, szField, 16 ); while( szFieldStart!=NULL ) { ptPathCmd = NULL; // What's this command ? if( svgIsRealNumber( szField )!= 0) { // No command so use last command if( ptLastPathCmd!=NULL ) { switch( ptLastPathCmd->tId ) { // MoveTo => LineTo case SVG_PATH_CMD_ID_MOVETO_ABS: case SVG_PATH_CMD_ID_MOVETO_REL: ptPathCmd = svgNewPathCommand( ( ptLastPathCmd->tId==SVG_PATH_CMD_ID_MOVETO_REL ) ? SVG_PATH_CMD_ID_LINETO_REL : SVG_PATH_CMD_ID_LINETO_ABS ); break; // Repeated command default: ptPathCmd = svgNewPathCommand( ptLastPathCmd->tId ); break; } // Search command format for( uiCmdIdx = 0; g_atPathCommandFormat[ uiCmdIdx ].cCommand!='\0'; uiCmdIdx ++ ) { if( g_atPathCommandFormat[ uiCmdIdx ].tId==ptPathCmd->tId ) { break; } } // Since we already read the parameter of the command we don't want to skip when we'll parse the command's parameters. szField[ 0 ] = 0; } } else { // Search command format for( uiCmdIdx = 0; g_atPathCommandFormat[ uiCmdIdx ].cCommand!='\0'; uiCmdIdx ++ ) { if( g_atPathCommandFormat[ uiCmdIdx ].cCommand==szField[ 0 ] ) { ptPathCmd = svgNewPathCommand( g_atPathCommandFormat[ uiCmdIdx ].tId ); break; } } } if (ptPathCmd == NULL) { svgSetLastError( SVG_ERR_NOT_ENOUGH_RAM, "Unrecognized path command '%c'.", szField[ 0 ] ); return ptItem; } // Parse args for( iI = 0; ( iI < g_atPathCommandFormat[ uiCmdIdx ].i8NbrOfArgs ) && ( iI < ( int8 )SVG_ARRAY_SIZE( atArgs ) ); iI ++ ) { atArgs[ iI ].fValue = 0; szFieldStart += strlen( szField ); if( ( szFieldStart = svgGetNextPathField( szFieldStart, szField, 16 ) )!=NULL ) { if( svgIsRealNumber( szField )!= 0) svgStringToCoordinate( szField, &atArgs[ iI ] ); } } // Parse the command parameters switch( ptPathCmd->tId ) { // MoveTo case SVG_PATH_CMD_ID_MOVETO_ABS: case SVG_PATH_CMD_ID_MOVETO_REL: ptPathCmd->tParameters.tMoveTo.tX = atArgs[ 0 ]; ptPathCmd->tParameters.tMoveTo.tY = atArgs[ 1 ]; break; // LineTo case SVG_PATH_CMD_ID_LINETO_ABS: case SVG_PATH_CMD_ID_LINETO_REL: ptPathCmd->tParameters.tLineTo.tX = atArgs[ 0 ]; ptPathCmd->tParameters.tLineTo.tY = atArgs[ 1 ]; break; // Vertical LineTo case SVG_PATH_CMD_ID_VERTICAL_LINETO_ABS: case SVG_PATH_CMD_ID_VERTICAL_LINETO_REL: ptPathCmd->tParameters.tLineTo.tY = atArgs[ 0 ]; break; // Horizontal LineTo case SVG_PATH_CMD_ID_HORIZONTAL_LINETO_ABS: case SVG_PATH_CMD_ID_HORIZONTAL_LINETO_REL: ptPathCmd->tParameters.tLineTo.tX = atArgs[ 0 ]; break; // Cubic CurveTo case SVG_PATH_CMD_ID_CUBIC_CURVETO_ABS: case SVG_PATH_CMD_ID_CUBIC_CURVETO_REL: ptPathCmd->tParameters.tCubicCurveTo.tX1 = atArgs[ 0 ]; ptPathCmd->tParameters.tCubicCurveTo.tY1 = atArgs[ 1 ]; ptPathCmd->tParameters.tCubicCurveTo.tX2 = atArgs[ 2 ]; ptPathCmd->tParameters.tCubicCurveTo.tY2 = atArgs[ 3 ]; ptPathCmd->tParameters.tCubicCurveTo.tX = atArgs[ 4 ]; ptPathCmd->tParameters.tCubicCurveTo.tY = atArgs[ 5 ]; break; // Smooth Cubic CurveTo case SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_ABS: case SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_REL: ptPathCmd->tParameters.tSmoothCubicCurveTo.tX2 = atArgs[ 0 ]; ptPathCmd->tParameters.tSmoothCubicCurveTo.tY2 = atArgs[ 1 ]; ptPathCmd->tParameters.tSmoothCubicCurveTo.tX = atArgs[ 2 ]; ptPathCmd->tParameters.tSmoothCubicCurveTo.tY = atArgs[ 3 ]; break; // Quadratic CurveTo case SVG_PATH_CMD_ID_QUADRATIC_CURVETO_ABS: case SVG_PATH_CMD_ID_QUADRATIC_CURVETO_REL: ptPathCmd->tParameters.tQuadraticCurveTo.tX1 = atArgs[ 0 ]; ptPathCmd->tParameters.tQuadraticCurveTo.tY1 = atArgs[ 1 ]; ptPathCmd->tParameters.tQuadraticCurveTo.tX = atArgs[ 2 ]; ptPathCmd->tParameters.tQuadraticCurveTo.tY = atArgs[ 3 ]; break; // Quadratic Cubic CurveTo case SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_ABS: case SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_REL: ptPathCmd->tParameters.tSmoothQuadraticCurveTo.tX = atArgs[ 0 ]; ptPathCmd->tParameters.tSmoothQuadraticCurveTo.tY = atArgs[ 1 ]; break; // ArcTo case SVG_PATH_CMD_ID_ARCTO_ABS: case SVG_PATH_CMD_ID_ARCTO_REL: ptPathCmd->tParameters.tArcTo.tRadiusX = atArgs[ 0 ]; ptPathCmd->tParameters.tArcTo.tRadiusY = atArgs[ 1 ]; ptPathCmd->tParameters.tArcTo.tXAxisAngle = atArgs[ 2 ]; ptPathCmd->tParameters.tArcTo.tLargeArcFlag = atArgs[ 3 ]; ptPathCmd->tParameters.tArcTo.tSweepFlag = atArgs[ 4 ]; ptPathCmd->tParameters.tArcTo.tX = atArgs[ 5 ]; ptPathCmd->tParameters.tArcTo.tY = atArgs[ 6 ]; break; // No parameters case SVG_PATH_CMD_ID_CLOSEPATH: default: break; } // Store the new command into the command list if( ptItem->tParameters.tPath.ptFirstCommand==NULL ) ptItem->tParameters.tPath.ptFirstCommand = ptPathCmd; if( ptLastPathCmd!=NULL ) ptLastPathCmd->ptNextCommand = ptPathCmd; ptLastPathCmd = ptPathCmd; // Next szFieldStart += strlen( szField ); szFieldStart = svgGetNextPathField( szFieldStart, szField, 16 ); } } return ptItem; }
svg_status_t _svg_color_init_from_str (svg_color_t *color, const char *str) { unsigned int r=0, g=0, b=0; svg_status_t status; svg_color_map_t *map; /* XXX: Need to check SVG spec. for this error case */ if (str == NULL || str[0] == '\0') return _svg_color_init_rgb (color, 0, 0, 0); if (strcmp (str, "currentColor") == 0) { _svg_color_init_rgb (color, 0, 0, 0); color->is_current_color = 1; return SVG_STATUS_SUCCESS; } color->is_current_color = 0; if (str[0] == '#') { str++; if (strlen(str) >= 6) { r = _svg_color_get_two_hex_digits (str); str += 2; g = _svg_color_get_two_hex_digits (str); str += 2; b = _svg_color_get_two_hex_digits (str); } else if (strlen(str) >= 3) { r = _svg_color_get_hex_digit (str); r += (r << 4); str++; g = _svg_color_get_hex_digit (str); g += (g << 4); str++; b = _svg_color_get_hex_digit (str); b += (b << 4); } return _svg_color_init_rgb (color, r, g, b); } _svg_str_skip_space (&str); if (strncmp (str, "rgb", 3) == 0) { str += 3; _svg_str_skip_space (&str); _svg_str_skip_char (&str, '('); status = _svg_color_parse_component (&str, &r); if (status) return status; _svg_str_skip_char (&str, ','); status = _svg_color_parse_component (&str, &g); if (status) return status; _svg_str_skip_char (&str, ','); status = _svg_color_parse_component (&str, &b); if (status) return status; _svg_str_skip_char (&str, ')'); return _svg_color_init_rgb (color, r, g, b); } map = (svg_color_map_t *)bsearch (str, SVG_COLOR_MAP, SVG_ARRAY_SIZE(SVG_COLOR_MAP), sizeof (svg_color_map_t), _svg_color_cmp); /* default to black on failed lookup */ if (map == NULL) return _svg_color_init_rgb (color, 0, 0, 0); *color = map->color; return SVG_STATUS_SUCCESS; }