├── .gitignore ├── Makefile ├── README.txt ├── docs ├── libsvg2-features.odt └── readme.txt ├── examples ├── Makefile └── parse.c ├── include ├── parser │ ├── svg_parser.h │ ├── svg_parser_circle.h │ ├── svg_parser_desc.h │ ├── svg_parser_ellipse.h │ ├── svg_parser_group.h │ ├── svg_parser_line.h │ ├── svg_parser_path.h │ ├── svg_parser_polygon.h │ ├── svg_parser_polyline.h │ ├── svg_parser_rect.h │ └── svg_parser_title.h ├── svg.h ├── svg_errors.h ├── svg_string.h ├── svg_types.h └── svg_xml.h ├── ressources ├── drawing3.svg ├── path.svg └── samples.svg └── sources ├── Makefile ├── parser ├── svg_parser.c ├── svg_parser_circle.c ├── svg_parser_desc.c ├── svg_parser_ellipse.c ├── svg_parser_group.c ├── svg_parser_line.c ├── svg_parser_path.c ├── svg_parser_polygon.c ├── svg_parser_polyline.c ├── svg_parser_rect.c └── svg_parser_title.c ├── svg.c ├── svg_errors.c ├── svg_string.c ├── svg_types.c └── svg_xml.c /.gitignore: -------------------------------------------------------------------------------- 1 | /eclipse/ 2 | /bin/ 3 | /objs/ 4 | /.cproject 5 | /.project 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Common tools 2 | ECHO=echo 3 | RM=rm -rf 4 | MV=mv 5 | MKDIR=mkdir 6 | PROMPT="> " 7 | DOXY=doxygen 8 | CC=gcc 9 | 10 | CROSS_COMPILE:= 11 | 12 | # Define directories and source files 13 | LIBSVG2_DIR:=$(CURDIR)/sources 14 | EXAMPLES_DIR:=$(CURDIR)/examples 15 | BINDIR:=$(CURDIR)/bin 16 | OBJDIR:=$(CURDIR)/objs 17 | INCDIR_BASE:=$(CURDIR)/include 18 | INCDIR:=${shell find $(INCDIR_BASE) -type d -print | grep -v .svn } 19 | DOCSDIR:=$(CURDIR)/docs 20 | AUTODIRS:=$(BINDIR) $(OBJDIR) $(DOCSDIR) 21 | LIBSVG2_AFILE:=$(BINDIR)/libsvg2.a 22 | 23 | 24 | # include directories 25 | CFLAGS:=$(CFLAGS) -I$(INCDIR) $(shell xml2-config --cflags) 26 | 27 | # Linker options 28 | LDFLAGS:=-L$(BINDIR) $(shell xml2-config --libs) 29 | 30 | # Adds flags to CFLAGS 31 | ifdef NDEBUG 32 | CFLAGS:=$(CFLAGS) -Wall -Wextra -Wconversion -O3 -DNDEBUG 33 | else 34 | CFLAGS:=$(CFLAGS) -Wall -Wextra -Wconversion -O0 -g -rdynamic 35 | endif 36 | 37 | export 38 | 39 | .PHONY: all help libsvg2 examples docs clean mrproper directories directories_pre directories_post 40 | 41 | all: directories libsvg2 examples 42 | 43 | libsvg2: directories 44 | @$(MAKE) -C $(LIBSVG2_DIR) 45 | 46 | examples: directories libsvg2 47 | @$(MAKE) -C $(EXAMPLES_DIR) 48 | 49 | clean: 50 | @$(MAKE) -C $(LIBSVG2_DIR) $@ 51 | @$(MAKE) -C $(EXAMPLES_DIR) $@ 52 | 53 | mrproper: 54 | @$(MAKE) -C $(LIBSVG2_DIR) $@ 55 | @$(MAKE) -C $(EXAMPLES_DIR) $@ 56 | -@$(RM) $(BINDIR) 57 | -@$(RM) $(OBJDIR) 58 | -@$(RM) $(DOCSDIR) 59 | 60 | directories: directories_pre $(AUTODIRS) directories_post 61 | 62 | directories_pre: 63 | @$(ECHO) -- Checking directories -- 64 | 65 | directories_post: 66 | @$(ECHO) -- directories done -- 67 | 68 | $(AUTODIRS): 69 | @$(ECHO) -n $(PROMPT) 70 | $(MKDIR) -p $@ 71 | 72 | docs: 73 | @$(DOXY) ./libsvg2.doxyfile 74 | 75 | help: 76 | @$(ECHO) "Rules" 77 | @$(ECHO) "-----" 78 | @$(ECHO) "all Build all rules but documentation." 79 | @$(ECHO) "clean Delete objects files." 80 | @$(ECHO) "docs Build documentation." 81 | @$(ECHO) "examples Compile examples." 82 | @$(ECHO) "libsvg2 Compile libsvg2 library." 83 | @$(ECHO) "help Display this page." 84 | @$(ECHO) "mrproper Perform a clean and delete binary files as well." 85 | @$(ECHO) "" 86 | @$(ECHO) "Variables" 87 | @$(ECHO) "---------" 88 | @$(ECHO) "CROSS_COMPILE Compiler prefix. (eg. sh4-linux-)." 89 | 90 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | libsvg2 - SVG Parser and renderer. 2 | 3 | Description 4 | ----------- 5 | libsvg2 is a SVG parser and renderer written in C. 6 | It is hosted on GitHub at https://github.com/agambier/libsvg2.git 7 | 8 | Dependencies 9 | ------------ 10 | libsvg2 depends on libxml2 (http://www.xmlsoft.org/). 11 | 12 | Supported OSes 13 | -------------- 14 | libsvg2 has been compiled and tested for the following OSes but it should 15 | be easy to port it for other OSes. 16 | - Linux 17 | 18 | History 19 | ------- 20 | Created by Alexandre Gambier . 21 | -------------------------------------------------------------------------------- /docs/libsvg2-features.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agambier/libsvg2/1963585a2ca3d9f80d64dffc837c9d84f6092e0f/docs/libsvg2-features.odt -------------------------------------------------------------------------------- /docs/readme.txt: -------------------------------------------------------------------------------- 1 | This folder will contains library documentation and tutorials... 2 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # Define directories 2 | EXAMPLES_OBJDIR:=$(OBJDIR)/examples 3 | AUTODIRS:=$(EXAMPLES_OBJDIR) 4 | 5 | # Define source files and object files 6 | CFILES:=${shell find ${CURDIR} -name "*.c" -print} 7 | OFILES:=$(patsubst %.c,%.o,$(CFILES)) 8 | OFILES:=$(notdir $(OFILES)) 9 | OFILES:=$(addprefix $(EXAMPLES_OBJDIR)/,$(OFILES)) 10 | OUTFILES:=$(patsubst %.c,%,$(CFILES)) 11 | OUTFILES:=$(notdir $(OUTFILES)) 12 | OUTFILES:=$(addprefix $(BINDIR)/,$(OUTFILES)) 13 | CFLAGS:=$(CFLAGS) 14 | LDFLAGS:=-lsvg2 $(LDFLAGS) -L$(BINDIR) 15 | # Define sub-directories 16 | VPATH:=$(dir $(CFILES)) $(INCDIR) 17 | 18 | .PHONY: all clean mrproper examples_pre examples_post directories directories_pre directories_post 19 | 20 | all: directories examples_pre $(OUTFILES) examples_post 21 | 22 | examples_pre: 23 | @$(ECHO) "-- Building examples --" 24 | 25 | examples_post: $(OUTFILES) 26 | @$(ECHO) "-- examples done --" 27 | 28 | $(BINDIR)/%: %.c $(LIBSVG2_AFILE) 29 | @$(ECHO) -n $(PROMPT)"("$(notdir $<)" 1/2) " 30 | $(CROSS_COMPILE)$(CC) $(CFLAGS) $(addprefix -I,$(INCDIR)) -c $< -o $(EXAMPLES_OBJDIR)/$(notdir $@).o 31 | @$(ECHO) -n $(PROMPT)"("$(notdir $<)" 2/2) " 32 | $(CROSS_COMPILE)$(CC) $(EXAMPLES_OBJDIR)/$(notdir $@).o $(LDFLAGS) -o $@ 33 | 34 | 35 | clean: 36 | @$(RM) $(EXAMPLES_OBJDIR) 37 | 38 | mrproper: clean 39 | @$(RM) $(OUTFILES) 40 | 41 | directories: directories_pre $(AUTODIRS) directories_post 42 | 43 | directories_pre: 44 | @$(ECHO) -- Checking directories -- 45 | 46 | directories_post: 47 | @$(ECHO) -- directories done -- 48 | 49 | $(AUTODIRS): 50 | @$(ECHO) -n $(PROMPT) 51 | $(MKDIR) -p $@ 52 | -------------------------------------------------------------------------------- /examples/parse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "svg.h" 3 | 4 | int main( int iargc, char **argv ) 5 | { 6 | svgDrawing *ptSvg; 7 | svgItem *ptItem; 8 | int iLevel,j; 9 | 10 | if( iargc<2 ) 11 | return -1; 12 | 13 | // Open the SVG file 14 | ptSvg = svgOpenFile( argv[ 1 ] ); 15 | if( ptSvg==NULL ) { 16 | printf( "ERROR(%d): %s.\n", svgGetLastError(), svgGetLastErrorDescription() ); 17 | return -1; 18 | } 19 | 20 | // Display the SVG item as a tree 21 | printf( "Nbr of items : %d\n", ptSvg->tItemList.ui32Count ); 22 | 23 | iLevel = 0; 24 | ptItem = ptSvg->tItemList.ptItem; 25 | while( ptItem!=NULL ) 26 | { 27 | printf( "|" ); 28 | for( j=0; jszId ); 31 | 32 | // walk through the tree 33 | if( ptItem->ptFirstChild!=NULL ) { 34 | ptItem = ptItem->ptFirstChild; 35 | iLevel ++; 36 | } 37 | else { 38 | if( ptItem->ptNextItem!=NULL ) 39 | ptItem = ptItem->ptNextItem; 40 | else if( ptItem->ptParent!=NULL ) { 41 | ptItem = ptItem->ptParent->ptNextItem; 42 | if( iLevel > 0 ) 43 | iLevel --; 44 | } 45 | else 46 | ptItem = NULL; 47 | } 48 | } 49 | 50 | 51 | svgFreeDrawing( ptSvg ); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /include/parser/svg_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_h__ 2 | #define __svg_parser_h__ 3 | 4 | #include 5 | #include 6 | #include "svg.h" 7 | #include "svg_types.h" 8 | #include "svg_parser_circle.h" 9 | #include "svg_parser_desc.h" 10 | #include "svg_parser_group.h" 11 | #include "svg_parser_line.h" 12 | #include "svg_parser_path.h" 13 | #include "svg_parser_rect.h" 14 | #include "svg_parser_title.h" 15 | #include "svg_parser_ellipse.h" 16 | #include "svg_parser_polyline.h" 17 | #include "svg_parser_polygon.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" 21 | { 22 | #endif 23 | 24 | 25 | svgItem* svgNewItem( xmlNodePtr ptXmlNode ); 26 | svgError svgParseFile( xmlNodePtr ptXmlNode, svgDrawing *ptDrawing ); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | 33 | #endif // __svg_parser_h__ 34 | -------------------------------------------------------------------------------- /include/parser/svg_parser_circle.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_circle_h__ 2 | #define __svg_parser_circle_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_CIRCLE "circle" 13 | 14 | svgItem* svgParseCircle( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_circle_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_desc.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_desc_h__ 2 | #define __svg_parser_desc_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_DESC "desc" 13 | 14 | svgItem* svgParseDesc( xmlNodePtr ptXmlNode ); 15 | 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | 22 | #endif // __svg_parser_desc_h__ 23 | -------------------------------------------------------------------------------- /include/parser/svg_parser_ellipse.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_ellipse_h__ 2 | #define __svg_parser_ellipse_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_ELLIPSE "ellipse" 13 | 14 | svgItem* svgParseEllipse( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_ellipse_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_group.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_group_h__ 2 | #define __svg_parser_group_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_GROUP "g" 13 | 14 | svgItem* svgParseGroup( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_group_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_line.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_line_h__ 2 | #define __svg_parser_line_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_LINE "line" 13 | 14 | svgItem* svgParseLine( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_line_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_path.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_path_h__ 2 | #define __svg_parser_path_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_PATH "path" 13 | 14 | svgItem* svgParsePath( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_path_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_polygon.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_polygon_h__ 2 | #define __svg_parser_polygon_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_POLYGON "polygon" 13 | 14 | svgItem* svgParsePolygon( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_polygon_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_polyline.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_polyline_h__ 2 | #define __svg_parser_polyline_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_POLYLINE "polyline" 13 | 14 | svgItem* svgParsePolyline( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_polyline_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_rect.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_rect_h__ 2 | #define __svg_parser_rect_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_RECT "rect" 13 | 14 | svgItem* svgParseRect( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_rect_h__ 22 | -------------------------------------------------------------------------------- /include/parser/svg_parser_title.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_parser_title_h__ 2 | #define __svg_parser_title_h__ 3 | 4 | #include "svg.h" 5 | #include "svg_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #define SVG_TAG_TITLE "title" 13 | 14 | svgItem* svgParseTitle( xmlNodePtr ptXmlNode ); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_parser_title_h__ 22 | -------------------------------------------------------------------------------- /include/svg.h: -------------------------------------------------------------------------------- 1 | /* 2 | svg.h: Public interface for libsvg2 3 | 4 | Copyright (C) 2012 Alexandre Gambier 5 | 6 | This program is free software and licensed under the GNU Lesser GPL (LGPL). 7 | 8 | This program is distributed WITHOUT ANY WARRANTY. 9 | 10 | FIXME: Finish this header... 11 | FIXME: Use doxygen to generate API documenation. 12 | */ 13 | 14 | #ifndef __svg_h__ 15 | #define __svg_h__ 16 | 17 | #include "svg_types.h" 18 | #include "svg_errors.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | typedef enum _svgItemKind { 25 | SVG_ITEM_KIND_GROUP = 0, 26 | SVG_ITEM_KIND_PATH, 27 | SVG_ITEM_KIND_RECT, 28 | SVG_ITEM_KIND_CIRCLE, 29 | SVG_ITEM_KIND_ELLIPSE, 30 | SVG_ITEM_KIND_LINE, 31 | SVG_ITEM_KIND_POLYLINE, 32 | SVG_ITEM_KIND_POLYGON, 33 | SVG_ITEM_KIND_TITLE, 34 | SVG_ITEM_KIND_DESC, 35 | } svgItemKind ; 36 | 37 | typedef struct _svgItem { 38 | svgItemKind tKind; 39 | char *szId; 40 | struct _svgItem *ptParent; /* Parent item */ 41 | struct _svgItem *ptFirstChild; /* Next child, usually when item is a group */ 42 | struct _svgItem *ptLastChild; /* Last child, usually when item is a group */ 43 | struct _svgItem *ptNextItem; /* Next item stored as a tree */ 44 | struct _svgItem *ptNextUnsortedItem; /* Next item but not stored as a tree */ 45 | 46 | union { 47 | svgTitle tTitle; /* tKind==SVG_ITEM_KIND_TITLE */ 48 | svgDesc tDesc; /* tKind==SVG_ITEM_KIND_DESC */ 49 | svgLine tLine; /* tKind==SVG_ITEM_KIND_LINE */ 50 | svgRect tRect; /* tKind==SVG_ITEM_KIND_RECT */ 51 | svgCircle tCircle; /* tKind==SVG_ITEM_KIND_CIRCLE */ 52 | svgPath tPath; /* tKind==SVG_ITEM_KIND_PATH */ 53 | svgEllipse tEllipse; /* tKind==SVG_ITEM_KIND_ELLIPSE */ 54 | svgPolyline tPolyline; /* tKind==SVG_ITEM_KIND_POLYLINE */ 55 | svgPolygon tPolygon; /* tKind==SVG_ITEM_KIND_POLYGON */ 56 | } tParameters ; 57 | } svgItem ; 58 | 59 | typedef struct _svgItemList { 60 | svgItem *ptItem; /* First item */ 61 | uint32 ui32Count; /* Number of items */ 62 | } svgItemList ; 63 | 64 | typedef struct _svgDrawing { 65 | char *szVersion; 66 | char *szId; 67 | svgCoordinate tX; 68 | svgCoordinate tY; 69 | svgLength tWidth; 70 | svgLength tHeight; 71 | svgItemList tItemList; 72 | } svgDrawing ; 73 | 74 | svgDrawing* svgOpenFile( const char *szFile ); 75 | void svgFreeDrawing( svgDrawing *ptDrawing ); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif // __svg_h__ 82 | -------------------------------------------------------------------------------- /include/svg_errors.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_errors_h__ 2 | #define __svg_errors_h__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #if defined( NDEBUG ) 9 | #define SVG_DEBUG_PRINTF( fmt, args... ) ( (void ) 0 ) 10 | #else 11 | #define SVG_DEBUG_PRINTF( fmt, args... ) printf( "%s():%d:" fmt, __FUNCTION__, __LINE__, ##args ) 12 | #endif // NDEBUG 13 | 14 | 15 | typedef enum _svgError { 16 | SVG_ERR_SUCCESS = 0, 17 | SVG_ERR_INVALID_PARAMETER, 18 | SVG_ERR_NO_SUCH_FILE, 19 | SVG_ERR_BAD_FILE_FORMAT, 20 | SVG_ERR_NOT_ENOUGH_RAM, 21 | } svgError ; 22 | 23 | svgError svgSetLastError( svgError, const char *szDesc, ... ); 24 | svgError svgGetLastError( void ); 25 | char* svgGetLastErrorDescription( void ); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif // __svg_errors_h__ 32 | -------------------------------------------------------------------------------- /include/svg_string.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_string_h__ 2 | #define __svg_string_h__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | const char* svgGetNextPathField( const char *szData, char *szField, int n ); 9 | const char* svgGetNextPointField( const char *szData, char *szField, int n ); 10 | char svgIsCommand( char c ); 11 | char svgIsRealNumber( const char *szString ); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | 18 | #endif // __svg_string_h__ 19 | -------------------------------------------------------------------------------- /include/svg_types.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_types_h__ 2 | #define __svg_types_h__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define SVG_UNUSED( a ) (void)(a); 9 | 10 | #define SVG_ARRAY_SIZE( a ) ( sizeof( ( a ) ) / sizeof( ( a )[ 0 ] ) ) 11 | 12 | #if defined( __GNUC__ ) 13 | #include 14 | typedef int8_t int8; 15 | typedef uint8_t uint8; 16 | typedef int16_t int16; 17 | typedef uint16_t uint16; 18 | typedef int32_t int32; 19 | typedef uint32_t uint32; 20 | typedef int64_t int64; 21 | typedef uint64_t uint64; 22 | #else 23 | #error Please define type sizes according to your architecture and compiler. 24 | #endif // __GNUC__ 25 | 26 | // ----- SVG Types ----- 27 | // Types defined by SVG standard (http://www.w3.org/TR/2011/REC-SVG11-20110816). 28 | 29 | // -- SVG length -- 30 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/types.html#Length) 31 | typedef enum _svgLengthUnit { 32 | SVG_LENGTH_UNIT_NONE = 0, 33 | SVG_LENGTH_UNIT_PX, 34 | SVG_LENGTH_UNIT_EM, 35 | SVG_LENGTH_UNIT_EX, 36 | SVG_LENGTH_UNIT_IN, 37 | SVG_LENGTH_UNIT_CM, 38 | SVG_LENGTH_UNIT_MM, 39 | SVG_LENGTH_UNIT_PT, 40 | SVG_LENGTH_UNIT_PC, 41 | SVG_LENGTH_UNIT_PERCENT 42 | } svgLengthUnit ; 43 | 44 | typedef struct _svgLength { 45 | svgLengthUnit tUnit; 46 | float fValue; 47 | } svgLength ; 48 | 49 | void svgStringToLength( const char *szValue, svgLength *ptLength ); 50 | 51 | // -- SVG Coordinate -- 52 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/types.html#DataTypeCoordinate) 53 | typedef svgLength svgCoordinate; 54 | #define svgStringToCoordinate( _value_, _coordinate_ ) svgStringToLength( ( _value_ ), ( _coordinate_ ) ) 55 | 56 | // -- Basic point -- 57 | typedef struct _svgPoint { 58 | svgCoordinate tX; 59 | svgCoordinate tY; 60 | struct _svgPoint *ptNextPoint; 61 | } svgPoint ; 62 | 63 | // ----- SVG Objects ----- 64 | 65 | // -- Title -- 66 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/struct.html#DescriptionAndTitleElements) 67 | typedef struct _svgTitle { 68 | char *szText; 69 | } svgTitle ; 70 | 71 | // -- Description -- 72 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/struct.html#DescriptionAndTitleElements) 73 | typedef struct _svgDesc { 74 | char *szText; 75 | } svgDesc ; 76 | 77 | // -- Line -- 78 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/shapes.html#LineElement) 79 | typedef struct _svgLine { 80 | svgCoordinate tX1; 81 | svgCoordinate tY1; 82 | svgCoordinate tX2; 83 | svgCoordinate tY2; 84 | } svgLine ; 85 | 86 | // -- Rect -- 87 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/shapes.html#RectElement) 88 | typedef struct _svgRect { 89 | svgCoordinate tX; 90 | svgCoordinate tY; 91 | svgLength tWidth; 92 | svgLength tHeight; 93 | svgLength tRadiusX; 94 | svgLength tRadiusY; 95 | } svgRect ; 96 | 97 | // -- Circle -- 98 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/shapes.html#CircleElement) 99 | typedef struct _svgCircle { 100 | svgCoordinate tX; 101 | svgCoordinate tY; 102 | svgLength tRadius; 103 | } svgCircle ; 104 | 105 | // -- Ellipse -- 106 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/shapes.html#EllipseElement) 107 | typedef struct _svgEllipse { 108 | svgCoordinate tX; 109 | svgCoordinate tY; 110 | svgLength tRadiusX; 111 | svgLength tRadiusY; 112 | } svgEllipse ; 113 | 114 | // -- Polyline -- 115 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/shapes.html#PolylineElement) 116 | typedef struct _svgPolyline { 117 | svgPoint tFirstPoint; 118 | } svgPolyline ; 119 | 120 | // -- Polygon -- 121 | // http://www.w3.org/TR/2011/REC-SVG11-20110816/shapes.html#PolygonElement 122 | typedef struct _svgPolygon { 123 | svgPoint tFirstPoint; 124 | } svgPolygon ; 125 | 126 | // -- Path Command -- 127 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathData) 128 | typedef enum _svgPathCommandId { 129 | SVG_PATH_CMD_ID_MOVETO_ABS = 0, 130 | SVG_PATH_CMD_ID_MOVETO_REL, 131 | SVG_PATH_CMD_ID_LINETO_ABS, 132 | SVG_PATH_CMD_ID_LINETO_REL, 133 | SVG_PATH_CMD_ID_VERTICAL_LINETO_ABS, 134 | SVG_PATH_CMD_ID_VERTICAL_LINETO_REL, 135 | SVG_PATH_CMD_ID_HORIZONTAL_LINETO_ABS, 136 | SVG_PATH_CMD_ID_HORIZONTAL_LINETO_REL, 137 | SVG_PATH_CMD_ID_CUBIC_CURVETO_ABS, 138 | SVG_PATH_CMD_ID_CUBIC_CURVETO_REL, 139 | SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_ABS, 140 | SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_REL, 141 | SVG_PATH_CMD_ID_QUADRATIC_CURVETO_ABS, 142 | SVG_PATH_CMD_ID_QUADRATIC_CURVETO_REL, 143 | SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_ABS, 144 | SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_REL, 145 | SVG_PATH_CMD_ID_ARCTO_ABS, 146 | SVG_PATH_CMD_ID_ARCTO_REL, 147 | SVG_PATH_CMD_ID_CLOSEPATH, 148 | SVG_PATH_CMD_ID_END_OF_ENUM 149 | } svgPathCommandId ; 150 | 151 | // -- Commands format -- 152 | typedef struct _svgPathCommandFormat { 153 | char cCommand; 154 | int8 i8NbrOfArgs; 155 | svgPathCommandId tId; 156 | } svgPathCommandFormat ; 157 | 158 | extern const svgPathCommandFormat g_atPathCommandFormat[]; 159 | 160 | // -- Path : MoveTo -- 161 | typedef struct _svgPathCommand_MoveTo { 162 | svgCoordinate tX; 163 | svgCoordinate tY; 164 | } svgPathCommand_MoveTo ; 165 | 166 | // -- Path : LineTo -- 167 | typedef struct _svgPathCommand_Lineto { 168 | svgCoordinate tX; /* Unused if SVG_PATH_CMD_ID_VERTICAL_LINETO_xxx */ 169 | svgCoordinate tY; /* Unused if SVG_PATH_CMD_ID_HORIZONTAL_LINETO_xxx */ 170 | } svgPathCommand_Lineto ; 171 | 172 | // -- Path : CubicCurveTo -- 173 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathDataCubicBezierCommands) 174 | typedef struct _svgPathCommand_CubicCurveTo { 175 | svgCoordinate tX; 176 | svgCoordinate tY; 177 | svgCoordinate tX1; 178 | svgCoordinate tY1; 179 | svgCoordinate tX2; 180 | svgCoordinate tY2; 181 | } svgPathCommand_CubicCurveTo ; 182 | 183 | // -- Path : SmoothCubicCurveTo -- 184 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathDataCubicBezierCommands) 185 | typedef struct _svgPathCommand_SmoothCubicCurveTo { 186 | svgCoordinate tX; 187 | svgCoordinate tY; 188 | svgCoordinate tX2; 189 | svgCoordinate tY2; 190 | } svgPathCommand_SmoothCubicCurveTo ; 191 | 192 | // -- Path : QuadraticCurveTo -- 193 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathDataQuadraticBezierCommands) 194 | typedef struct _svgPathCommand_QuadraticCurveTo { 195 | svgCoordinate tX; 196 | svgCoordinate tY; 197 | svgCoordinate tX1; 198 | svgCoordinate tY1; 199 | } svgPathCommand_QuadraticCurveTo ; 200 | 201 | // -- Path : SmoothQuadraticCurveTo -- 202 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathDataQuadraticBezierCommands) 203 | typedef struct _svgPathCommand_SmoothQuadraticCurveTo { 204 | svgCoordinate tX; 205 | svgCoordinate tY; 206 | } svgPathCommand_SmoothQuadraticCurveTo ; 207 | 208 | // -- Path : Arc -- 209 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathDataEllipticalArcCommands) 210 | typedef struct _svgPathCommand_ArcTo { 211 | svgCoordinate tX; 212 | svgCoordinate tY; 213 | svgCoordinate tRadiusX; 214 | svgCoordinate tRadiusY; 215 | svgCoordinate tXAxisAngle; 216 | svgCoordinate tLargeArcFlag; 217 | svgCoordinate tSweepFlag; 218 | } svgPathCommand_ArcTo ; 219 | 220 | // -- Path Command -- 221 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathData) 222 | typedef struct _svgPathCommand { 223 | svgPathCommandId tId; 224 | 225 | union { 226 | svgPathCommand_MoveTo tMoveTo; /* tId==SVG_PATH_CMD_ID_MOVETO_xxx */ 227 | svgPathCommand_Lineto tLineTo; /* tId==SVG_PATH_CMD_ID_LINETO_xxx */ 228 | svgPathCommand_CubicCurveTo tCubicCurveTo; /* tId==SVG_PATH_CMD_ID_CUBIC_CURVETO_xxx */ 229 | svgPathCommand_SmoothCubicCurveTo tSmoothCubicCurveTo; /* tId==SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_xxx */ 230 | svgPathCommand_QuadraticCurveTo tQuadraticCurveTo; /* tId==SVG_PATH_CMD_ID_QUADRATIC_CURVETO_xxx */ 231 | svgPathCommand_SmoothQuadraticCurveTo tSmoothQuadraticCurveTo; /* tId==SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_xxx */ 232 | svgPathCommand_ArcTo tArcTo; /* tId==SVG_PATH_CMD_ID_ARCTO_xxx */ 233 | } tParameters ; 234 | 235 | struct _svgPathCommand *ptNextCommand; 236 | } svgPathCommand ; 237 | 238 | // -- Path -- 239 | // (http://www.w3.org/TR/2011/REC-SVG11-20110816/paths.html#PathElement) 240 | typedef struct _svgPath { 241 | svgPathCommand *ptFirstCommand; 242 | } svgPath; 243 | 244 | #ifdef __cplusplus 245 | } 246 | #endif 247 | 248 | #endif // __svg_types_h__ 249 | -------------------------------------------------------------------------------- /include/svg_xml.h: -------------------------------------------------------------------------------- 1 | #ifndef __svg_xml_h__ 2 | #define __svg_xml_h__ 3 | 4 | #include 5 | #include 6 | 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | xmlNodePtr GetChild( xmlNodePtr ptXmlNode, xmlElementType tType, char *szChildName ); 14 | 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | 21 | #endif // __svg_xml_h__ 22 | -------------------------------------------------------------------------------- /ressources/drawing3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 13 | 17 | 21 | 23 | This is a what kind of basic shapes.. 25 | Basic shapes 27 | 29 | 36 | 43 | 44 | 48 | 49 | 56 | 58 | 62 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /ressources/path.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | Example triangle01- simple example of a 'path' 7 | A path that draws a triangle 8 | 10 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ressources/samples.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 13 | 21 | 29 | 37 | 38 | -------------------------------------------------------------------------------- /sources/Makefile: -------------------------------------------------------------------------------- 1 | # Define directories 2 | LIBSVG2_OBJDIR:=$(OBJDIR)/libsvg2 3 | AUTODIRS:=$(LIBSVG2_OBJDIR) 4 | 5 | # Define source files and object files 6 | CFILES:=${shell find ${CURDIR} -name "*.c" -print} 7 | OFILES:=$(patsubst %.c,%.o,$(CFILES)) 8 | OFILES:=$(notdir $(OFILES)) 9 | OFILES:=$(addprefix $(LIBSVG2_OBJDIR)/,$(OFILES)) 10 | CFLAGS:=$(CFLAGS) 11 | 12 | # Define sub-directories 13 | VPATH:=$(dir $(CFILES)) $(INCDIR) 14 | 15 | .PHONY: all clean mrproper libsvg2_pre libsvg2_post directories directories_pre directories_post 16 | 17 | all: directories libsvg2_pre $(LIBSVG2_AFILE) libsvg2_post 18 | 19 | libsvg2_pre: directories 20 | @$(ECHO) "-- Building $(notdir $(LIBSVG2_AFILE)) --" 21 | @$(ECHO) -n $(PROMPT) 22 | 23 | libsvg2_post: $(LIBSVG2_AFILE) 24 | @$(ECHO) "-- $(notdir $(LIBSVG2_AFILE)) done --" 25 | 26 | $(LIBSVG2_AFILE): $(OFILES) 27 | @$(ECHO) -n $(PROMPT)"("$(notdir $(LIBSVG2_AFILE))") " 28 | $(CROSS_COMPILE)$(AR) rcs $(LIBSVG2_AFILE) $(OFILES) 29 | 30 | $(LIBSVG2_OBJDIR)/%.o: %.c %.h libsvg2_pre 31 | @$(ECHO) -n $(PROMPT)"("$(notdir $<)") " 32 | $(CROSS_COMPILE)$(CC) $(CFLAGS) $(addprefix -I,$(INCDIR)) -c $< -o $@ 33 | 34 | clean: 35 | @$(RM) $(LIBSVG2_OBJDIR) 36 | 37 | mrproper: clean 38 | @$(RM) $(LIBSVG2_AFILE) 39 | 40 | directories: directories_pre $(AUTODIRS) directories_post 41 | 42 | directories_pre: 43 | @$(ECHO) -- Checking directories -- 44 | 45 | directories_post: $(AUTODIRS) 46 | @$(ECHO) -- directories done -- 47 | 48 | $(AUTODIRS): directories_pre 49 | @$(ECHO) -n $(PROMPT) 50 | $(MKDIR) -p $@ 51 | -------------------------------------------------------------------------------- /sources/parser/svg_parser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_types.h" 5 | #include "svg_xml.h" 6 | #include "svg_string.h" 7 | 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | svgItem* svgNewItem( xmlNodePtr ptXmlNode ) 14 | { 15 | svgItem *ptItem = NULL; 16 | char *szValue; 17 | 18 | if( ptXmlNode==NULL ) 19 | return NULL; 20 | 21 | ptItem = ( svgItem* )malloc( sizeof( *ptItem ) ); 22 | if( ptItem==NULL ) 23 | { 24 | svgSetLastError( SVG_ERR_NOT_ENOUGH_RAM, "Not enough RAM to create SVG drawing." ); 25 | return NULL; 26 | } 27 | memset( ptItem, 0, sizeof( *ptItem ) ); 28 | 29 | // ID 30 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"id" ) )!=NULL ) 31 | ptItem->szId = strdup( szValue ); 32 | 33 | return ptItem; 34 | } 35 | 36 | svgError svgParseFile( xmlNodePtr ptXmlRoot, svgDrawing *ptDrawing ) 37 | { 38 | svgItem *ptNewItem; /* New parsed item */ 39 | svgItem *ptLastItem; /* Last created item */ 40 | svgItem *ptCurrentParent; /* Current parent, NULL if root level */ 41 | svgItem *ptLastBrother; /* Last item that should be the brother of the new parsed item */ 42 | svgItem *ptLastRootLevelItem; /* Last item on the root level */ 43 | xmlNodePtr ptXmlNode; 44 | 45 | if( ptXmlRoot==NULL ) 46 | return svgSetLastError( SVG_ERR_INVALID_PARAMETER, "ptXmlRoot can't be NULL" ); 47 | if( ptDrawing==NULL ) 48 | return svgSetLastError( SVG_ERR_INVALID_PARAMETER, "ptDrawing can't be NULL" ); 49 | 50 | // Parse SVG file 51 | ptCurrentParent = NULL; 52 | ptLastItem = NULL; 53 | ptLastBrother = NULL; 54 | ptLastRootLevelItem = NULL; 55 | ptXmlNode = ptXmlRoot->xmlChildrenNode; 56 | while( ptXmlNode ) { 57 | 58 | ptNewItem = NULL; 59 | 60 | if( ptXmlNode->type == XML_ELEMENT_NODE ) { 61 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_TITLE )==0 ) { 62 | // Group 63 | ptNewItem = svgParseTitle( ptXmlNode ); 64 | } 65 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_DESC )==0 ) { 66 | // Group 67 | ptNewItem = svgParseDesc( ptXmlNode ); 68 | } 69 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_GROUP )==0 ) { 70 | // Group 71 | ptNewItem = svgParseGroup( ptXmlNode ); 72 | } 73 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_PATH )==0 ) { 74 | // Path 75 | ptNewItem = svgParsePath( ptXmlNode ); 76 | } 77 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_RECT )==0 ) { 78 | // Rectangle 79 | ptNewItem = svgParseRect( ptXmlNode ); 80 | } 81 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_CIRCLE )==0 ) { 82 | // Circle 83 | ptNewItem = svgParseCircle( ptXmlNode ); 84 | } 85 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_ELLIPSE )==0 ) { 86 | // Ellipse 87 | ptNewItem = svgParseEllipse( ptXmlNode ); 88 | } 89 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_LINE )==0 ) { 90 | // Line 91 | ptNewItem = svgParseLine( ptXmlNode ); 92 | } 93 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_POLYLINE )==0 ) { 94 | // Polyline 95 | ptNewItem = svgParsePolyline( ptXmlNode ); 96 | } 97 | else if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_POLYGON )==0 ) { 98 | // Polygon 99 | ptNewItem = svgParsePolygon( ptXmlNode ); 100 | } 101 | else { 102 | SVG_DEBUG_PRINTF( "Unknown or unsupported SVG item : %s\n", ptXmlNode->name ); 103 | } 104 | 105 | if( ptNewItem!=NULL ) 106 | { 107 | // Is it the first item ? 108 | if( ptDrawing->tItemList.ptItem==NULL ) 109 | ptDrawing->tItemList.ptItem = ptNewItem; 110 | 111 | // Add it to the parent 112 | if( ptCurrentParent!=NULL ) { 113 | // Link it to its brother "same level" 114 | ptLastBrother = ptCurrentParent->ptLastChild; 115 | 116 | if( ptCurrentParent->ptFirstChild==NULL ) 117 | ptCurrentParent->ptFirstChild = ptNewItem; 118 | 119 | ptCurrentParent->ptLastChild = ptNewItem; 120 | } 121 | else { 122 | ptLastBrother = ptLastRootLevelItem; 123 | ptLastRootLevelItem = ptNewItem; 124 | } 125 | 126 | if( ptLastBrother!=NULL && ptLastBrother->ptParent==ptCurrentParent ) 127 | ptLastBrother->ptNextItem = ptNewItem; 128 | 129 | ptNewItem->ptParent = ptCurrentParent; 130 | 131 | // Link current item with previous one 132 | if( ptLastItem!=NULL ) 133 | ptLastItem->ptNextUnsortedItem = ptNewItem; 134 | 135 | ptLastItem = ptNewItem; 136 | ptDrawing->tItemList.ui32Count ++; 137 | 138 | // We have to parse its children 139 | if( ptXmlNode->xmlChildrenNode!=NULL ) { 140 | ptXmlNode = ptXmlNode->xmlChildrenNode; 141 | ptCurrentParent = ptNewItem; 142 | } 143 | } 144 | } 145 | 146 | // Next node 147 | if( ptXmlNode->next!=NULL ) 148 | ptXmlNode = ptXmlNode->next; 149 | else { 150 | // Maybe we have get back to a upper level in the tree 151 | if( ptXmlNode->parent!=NULL ) 152 | ptXmlNode = ptXmlNode->parent->next; 153 | else 154 | ptXmlNode = NULL; 155 | 156 | if( ptCurrentParent!=NULL ) 157 | ptCurrentParent = ptCurrentParent->ptParent; 158 | } 159 | } 160 | 161 | return svgSetLastError( SVG_ERR_SUCCESS, NULL ); 162 | } 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_circle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseCircle( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | char *szValue; 12 | 13 | if( ptXmlNode==NULL ) 14 | return NULL; 15 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_CIRCLE )!=0 ) 16 | return NULL; 17 | 18 | // Read common values to all kind of item 19 | ptItem = svgNewItem( ptXmlNode ); 20 | if( ptItem==NULL ) 21 | return NULL; 22 | 23 | ptItem->tKind = SVG_ITEM_KIND_CIRCLE; 24 | 25 | // x 26 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"cx" ) )!=NULL ) 27 | svgStringToCoordinate( szValue, &ptItem->tParameters.tCircle.tX ); 28 | // Y 29 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"cy" ) )!=NULL ) 30 | svgStringToCoordinate( szValue, &ptItem->tParameters.tCircle.tY ); 31 | // radius 32 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"r" ) )!=NULL ) 33 | svgStringToLength( szValue, &ptItem->tParameters.tCircle.tRadius ); 34 | 35 | 36 | return ptItem; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_desc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseDesc( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | xmlNodePtr ptXmlValue; 12 | 13 | if( ptXmlNode==NULL ) 14 | return NULL; 15 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_DESC )!=0 ) 16 | return NULL; 17 | 18 | // Read common values to all kind of item 19 | ptItem = svgNewItem( ptXmlNode ); 20 | if( ptItem==NULL ) 21 | return NULL; 22 | 23 | ptItem->tKind = SVG_ITEM_KIND_DESC; 24 | 25 | if( ( ptXmlValue = GetChild( ptXmlNode, XML_TEXT_NODE, "text" ) )!=NULL ) { 26 | if( ptXmlValue->content!=NULL ) 27 | ptItem->tParameters.tTitle.szText = strdup( ( char* )ptXmlValue->content ); 28 | } 29 | 30 | return ptItem; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_ellipse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseEllipse( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | char *szValue; 12 | 13 | if( ptXmlNode==NULL ) 14 | return NULL; 15 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_ELLIPSE )!=0 ) 16 | return NULL; 17 | 18 | // Read common values to all kind of item 19 | ptItem = svgNewItem( ptXmlNode ); 20 | if( ptItem==NULL ) 21 | return NULL; 22 | 23 | ptItem->tKind = SVG_ITEM_KIND_ELLIPSE; 24 | 25 | // cx 26 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"cx" ) )!=NULL ) 27 | svgStringToCoordinate( szValue, &ptItem->tParameters.tEllipse.tX ); 28 | // cY 29 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"cy" ) )!=NULL ) 30 | svgStringToCoordinate( szValue, &ptItem->tParameters.tEllipse.tY ); 31 | // RadiusX 32 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"rx" ) )!=NULL ) 33 | svgStringToLength( szValue, &ptItem->tParameters.tEllipse.tRadiusX ); 34 | // RadiusY 35 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"ry" ) )!=NULL ) 36 | svgStringToLength( szValue, &ptItem->tParameters.tEllipse.tRadiusY ); 37 | 38 | 39 | return ptItem; 40 | } 41 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_group.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseGroup( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | 12 | if( ptXmlNode==NULL ) 13 | return NULL; 14 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_GROUP )!=0 ) 15 | return NULL; 16 | 17 | // Read common values to all kind of item 18 | ptItem = svgNewItem( ptXmlNode ); 19 | if( ptItem==NULL ) 20 | return NULL; 21 | 22 | ptItem->tKind = SVG_ITEM_KIND_GROUP; 23 | 24 | return ptItem; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_line.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseLine( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | char *szValue; 12 | 13 | if( ptXmlNode==NULL ) 14 | return NULL; 15 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_LINE )!=0 ) 16 | return NULL; 17 | 18 | // Read common values to all kind of item 19 | ptItem = svgNewItem( ptXmlNode ); 20 | if( ptItem==NULL ) 21 | return NULL; 22 | 23 | ptItem->tKind = SVG_ITEM_KIND_LINE; 24 | 25 | // x1 26 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"x1" ) )!=NULL ) 27 | svgStringToCoordinate( szValue, &ptItem->tParameters.tLine.tX1 ); 28 | // Y1 29 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"y1" ) )!=NULL ) 30 | svgStringToCoordinate( szValue, &ptItem->tParameters.tLine.tY1 ); 31 | // X2 32 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"x2" ) )!=NULL ) 33 | svgStringToCoordinate( szValue, &ptItem->tParameters.tLine.tX2 ); 34 | // Y2 35 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"y2" ) )!=NULL ) 36 | svgStringToCoordinate( szValue, &ptItem->tParameters.tLine.tY2 ); 37 | 38 | 39 | return ptItem; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_path.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_types.h" 5 | #include "svg_string.h" 6 | 7 | 8 | svgPathCommand* svgNewPathCommand( svgPathCommandId tId ) 9 | { 10 | svgPathCommand *ptCmd = NULL; 11 | 12 | ptCmd = ( svgPathCommand* )malloc( sizeof( *ptCmd ) ); 13 | if( ptCmd==NULL ) 14 | { 15 | svgSetLastError( SVG_ERR_NOT_ENOUGH_RAM, "Not enough RAM to create path command." ); 16 | return NULL; 17 | } 18 | memset( ptCmd, 0, sizeof( *ptCmd ) ); 19 | 20 | ptCmd->tId = tId; 21 | 22 | return ptCmd; 23 | } 24 | 25 | svgItem* svgParsePath( xmlNodePtr ptXmlNode ) 26 | { 27 | svgItem *ptItem = NULL; 28 | char *szValue, szField[ 16 ]; 29 | const char *szFieldStart; 30 | svgPathCommand *ptPathCmd, *ptLastPathCmd = NULL; 31 | unsigned int uiCmdIdx; 32 | int8 iI; 33 | svgLength atArgs[ 12 ]; 34 | 35 | if( ptXmlNode==NULL ) 36 | return NULL; 37 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_PATH )!=0 ) 38 | return NULL; 39 | 40 | // Read common values to all kind of item 41 | ptItem = svgNewItem( ptXmlNode ); 42 | if( ptItem==NULL ) 43 | return NULL; 44 | 45 | ptItem->tKind = SVG_ITEM_KIND_PATH; 46 | 47 | // d 48 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"d" ) )!=NULL ) { 49 | ptLastPathCmd = NULL; 50 | szFieldStart = svgGetNextPathField( szValue, szField, 16 ); 51 | while( szFieldStart!=NULL ) { 52 | 53 | ptPathCmd = NULL; 54 | 55 | // What's this command ? 56 | if( svgIsRealNumber( szField )!= 0) { 57 | 58 | // No command so use last command 59 | if( ptLastPathCmd!=NULL ) { 60 | 61 | switch( ptLastPathCmd->tId ) { 62 | // MoveTo => LineTo 63 | case SVG_PATH_CMD_ID_MOVETO_ABS: 64 | case SVG_PATH_CMD_ID_MOVETO_REL: 65 | ptPathCmd = svgNewPathCommand( ( ptLastPathCmd->tId==SVG_PATH_CMD_ID_MOVETO_REL ) ? SVG_PATH_CMD_ID_LINETO_REL : SVG_PATH_CMD_ID_LINETO_ABS ); 66 | break; 67 | // Repeated command 68 | default: 69 | ptPathCmd = svgNewPathCommand( ptLastPathCmd->tId ); 70 | break; 71 | } 72 | 73 | // Search command format 74 | for( uiCmdIdx = 0; g_atPathCommandFormat[ uiCmdIdx ].cCommand!='\0'; uiCmdIdx ++ ) { 75 | if( g_atPathCommandFormat[ uiCmdIdx ].tId==ptPathCmd->tId ) { 76 | break; 77 | } 78 | } 79 | 80 | // Since we already read the parameter of the command we don't want to skip when we'll parse the command's parameters. 81 | szField[ 0 ] = 0; 82 | } 83 | } 84 | else { 85 | // Search command format 86 | for( uiCmdIdx = 0; g_atPathCommandFormat[ uiCmdIdx ].cCommand!='\0'; uiCmdIdx ++ ) { 87 | if( g_atPathCommandFormat[ uiCmdIdx ].cCommand==szField[ 0 ] ) { 88 | ptPathCmd = svgNewPathCommand( g_atPathCommandFormat[ uiCmdIdx ].tId ); 89 | break; 90 | } 91 | } 92 | } 93 | 94 | if (ptPathCmd == NULL) { 95 | svgSetLastError( SVG_ERR_NOT_ENOUGH_RAM, "Unrecognized path command '%c'.", szField[ 0 ] ); 96 | return ptItem; 97 | } 98 | 99 | // Parse args 100 | for( iI = 0; ( iI < g_atPathCommandFormat[ uiCmdIdx ].i8NbrOfArgs ) && ( iI < ( int8 )SVG_ARRAY_SIZE( atArgs ) ); iI ++ ) { 101 | atArgs[ iI ].fValue = 0; 102 | szFieldStart += strlen( szField ); 103 | if( ( szFieldStart = svgGetNextPathField( szFieldStart, szField, 16 ) )!=NULL ) { 104 | if( svgIsRealNumber( szField )!= 0) 105 | svgStringToCoordinate( szField, &atArgs[ iI ] ); 106 | } 107 | } 108 | 109 | // Parse the command parameters 110 | switch( ptPathCmd->tId ) { 111 | // MoveTo 112 | case SVG_PATH_CMD_ID_MOVETO_ABS: 113 | case SVG_PATH_CMD_ID_MOVETO_REL: 114 | ptPathCmd->tParameters.tMoveTo.tX = atArgs[ 0 ]; 115 | ptPathCmd->tParameters.tMoveTo.tY = atArgs[ 1 ]; 116 | break; 117 | 118 | // LineTo 119 | case SVG_PATH_CMD_ID_LINETO_ABS: 120 | case SVG_PATH_CMD_ID_LINETO_REL: 121 | ptPathCmd->tParameters.tLineTo.tX = atArgs[ 0 ]; 122 | ptPathCmd->tParameters.tLineTo.tY = atArgs[ 1 ]; 123 | break; 124 | 125 | // Vertical LineTo 126 | case SVG_PATH_CMD_ID_VERTICAL_LINETO_ABS: 127 | case SVG_PATH_CMD_ID_VERTICAL_LINETO_REL: 128 | ptPathCmd->tParameters.tLineTo.tY = atArgs[ 0 ]; 129 | break; 130 | 131 | // Horizontal LineTo 132 | case SVG_PATH_CMD_ID_HORIZONTAL_LINETO_ABS: 133 | case SVG_PATH_CMD_ID_HORIZONTAL_LINETO_REL: 134 | ptPathCmd->tParameters.tLineTo.tX = atArgs[ 0 ]; 135 | break; 136 | 137 | // Cubic CurveTo 138 | case SVG_PATH_CMD_ID_CUBIC_CURVETO_ABS: 139 | case SVG_PATH_CMD_ID_CUBIC_CURVETO_REL: 140 | ptPathCmd->tParameters.tCubicCurveTo.tX1 = atArgs[ 0 ]; 141 | ptPathCmd->tParameters.tCubicCurveTo.tY1 = atArgs[ 1 ]; 142 | ptPathCmd->tParameters.tCubicCurveTo.tX2 = atArgs[ 2 ]; 143 | ptPathCmd->tParameters.tCubicCurveTo.tY2 = atArgs[ 3 ]; 144 | ptPathCmd->tParameters.tCubicCurveTo.tX = atArgs[ 4 ]; 145 | ptPathCmd->tParameters.tCubicCurveTo.tY = atArgs[ 5 ]; 146 | break; 147 | 148 | // Smooth Cubic CurveTo 149 | case SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_ABS: 150 | case SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_REL: 151 | ptPathCmd->tParameters.tSmoothCubicCurveTo.tX2 = atArgs[ 0 ]; 152 | ptPathCmd->tParameters.tSmoothCubicCurveTo.tY2 = atArgs[ 1 ]; 153 | ptPathCmd->tParameters.tSmoothCubicCurveTo.tX = atArgs[ 2 ]; 154 | ptPathCmd->tParameters.tSmoothCubicCurveTo.tY = atArgs[ 3 ]; 155 | break; 156 | 157 | // Quadratic CurveTo 158 | case SVG_PATH_CMD_ID_QUADRATIC_CURVETO_ABS: 159 | case SVG_PATH_CMD_ID_QUADRATIC_CURVETO_REL: 160 | ptPathCmd->tParameters.tQuadraticCurveTo.tX1 = atArgs[ 0 ]; 161 | ptPathCmd->tParameters.tQuadraticCurveTo.tY1 = atArgs[ 1 ]; 162 | ptPathCmd->tParameters.tQuadraticCurveTo.tX = atArgs[ 2 ]; 163 | ptPathCmd->tParameters.tQuadraticCurveTo.tY = atArgs[ 3 ]; 164 | break; 165 | 166 | // Quadratic Cubic CurveTo 167 | case SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_ABS: 168 | case SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_REL: 169 | ptPathCmd->tParameters.tSmoothQuadraticCurveTo.tX = atArgs[ 0 ]; 170 | ptPathCmd->tParameters.tSmoothQuadraticCurveTo.tY = atArgs[ 1 ]; 171 | break; 172 | 173 | // ArcTo 174 | case SVG_PATH_CMD_ID_ARCTO_ABS: 175 | case SVG_PATH_CMD_ID_ARCTO_REL: 176 | ptPathCmd->tParameters.tArcTo.tRadiusX = atArgs[ 0 ]; 177 | ptPathCmd->tParameters.tArcTo.tRadiusY = atArgs[ 1 ]; 178 | ptPathCmd->tParameters.tArcTo.tXAxisAngle = atArgs[ 2 ]; 179 | ptPathCmd->tParameters.tArcTo.tLargeArcFlag = atArgs[ 3 ]; 180 | ptPathCmd->tParameters.tArcTo.tSweepFlag = atArgs[ 4 ]; 181 | ptPathCmd->tParameters.tArcTo.tX = atArgs[ 5 ]; 182 | ptPathCmd->tParameters.tArcTo.tY = atArgs[ 6 ]; 183 | break; 184 | 185 | // No parameters 186 | case SVG_PATH_CMD_ID_CLOSEPATH: 187 | default: 188 | break; 189 | } 190 | 191 | // Store the new command into the command list 192 | if( ptItem->tParameters.tPath.ptFirstCommand==NULL ) 193 | ptItem->tParameters.tPath.ptFirstCommand = ptPathCmd; 194 | 195 | if( ptLastPathCmd!=NULL ) 196 | ptLastPathCmd->ptNextCommand = ptPathCmd; 197 | 198 | ptLastPathCmd = ptPathCmd; 199 | 200 | // Next 201 | szFieldStart += strlen( szField ); 202 | szFieldStart = svgGetNextPathField( szFieldStart, szField, 16 ); 203 | } 204 | } 205 | 206 | 207 | return ptItem; 208 | } 209 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_polygon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParsePolygon( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | const char *szValue; 12 | svgPoint *ptNewPoint = NULL, *ptLastPoint = NULL; 13 | 14 | if( ptXmlNode==NULL ) 15 | return NULL; 16 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_POLYGON )!=0 ) 17 | return NULL; 18 | 19 | // Read common values to all kind of item 20 | ptItem = svgNewItem( ptXmlNode ); 21 | if( ptItem==NULL ) 22 | return NULL; 23 | 24 | ptItem->tKind = SVG_ITEM_KIND_POLYGON; 25 | 26 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"points" ) )!=NULL ) { 27 | char szField[ 16 ]; 28 | const char* szFieldStart = svgGetNextPointField( szValue, szField, 16 ); 29 | 30 | while( szFieldStart!=NULL ) { 31 | // First point ? 32 | if( ptNewPoint==NULL ) 33 | ptNewPoint = &ptItem->tParameters.tPolygon.tFirstPoint; 34 | else 35 | ptNewPoint = ( svgPoint* )malloc( sizeof( *ptNewPoint ) ); 36 | memset( ptNewPoint, 0, sizeof( *ptNewPoint ) ); 37 | 38 | // X 39 | svgStringToCoordinate( szField, &ptNewPoint->tX ); 40 | 41 | // Y 42 | szFieldStart += strlen( szField ); 43 | szFieldStart = svgGetNextPointField( szFieldStart, szField, 16 ); 44 | svgStringToCoordinate( szField, &ptNewPoint->tY ); 45 | 46 | // Link with last point 47 | if( ptLastPoint!=NULL ) 48 | ptLastPoint->ptNextPoint = ptNewPoint; 49 | ptLastPoint = ptNewPoint; 50 | 51 | // Next X 52 | szFieldStart += strlen( szField ); 53 | szFieldStart = svgGetNextPointField( szFieldStart, szField, 16 ); 54 | } 55 | } 56 | 57 | return ptItem; 58 | } 59 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_polyline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParsePolyline( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | char *szValue, szField[ 16 ]; 12 | const char *szFieldStart; 13 | svgPoint *ptNewPoint = NULL, *ptLastPoint = NULL; 14 | 15 | if( ptXmlNode==NULL ) 16 | return NULL; 17 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_POLYLINE )!=0 ) 18 | return NULL; 19 | 20 | // Read common values to all kind of item 21 | ptItem = svgNewItem( ptXmlNode ); 22 | if( ptItem==NULL ) 23 | return NULL; 24 | 25 | ptItem->tKind = SVG_ITEM_KIND_POLYLINE; 26 | 27 | // Points 28 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"points" ) )!=NULL ) { 29 | 30 | szFieldStart = svgGetNextPointField( szValue, szField, 16 ); 31 | 32 | while( szFieldStart!=NULL ) { 33 | // First point ? 34 | if( ptNewPoint==NULL ) 35 | ptNewPoint = &ptItem->tParameters.tPolyline.tFirstPoint; 36 | else 37 | ptNewPoint = ( svgPoint* )malloc( sizeof( *ptNewPoint ) ); 38 | memset( ptNewPoint, 0, sizeof( *ptNewPoint ) ); 39 | 40 | // X 41 | svgStringToCoordinate( szField, &ptNewPoint->tX ); 42 | 43 | // Y 44 | szFieldStart += strlen( szField ); 45 | szFieldStart = svgGetNextPointField( szFieldStart, szField, 16 ); 46 | svgStringToCoordinate( szField, &ptNewPoint->tY ); 47 | 48 | // Link with last point 49 | if( ptLastPoint!=NULL ) 50 | ptLastPoint->ptNextPoint = ptNewPoint; 51 | ptLastPoint = ptNewPoint; 52 | 53 | // Next X 54 | szFieldStart += strlen( szField ); 55 | szFieldStart = svgGetNextPointField( szFieldStart, szField, 16 ); 56 | } 57 | } 58 | 59 | return ptItem; 60 | } 61 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_rect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseRect( xmlNodePtr ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | char *szValue; 12 | 13 | if( ptXmlNode==NULL ) 14 | return NULL; 15 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_RECT )!=0 ) 16 | return NULL; 17 | 18 | // Read common values to all kind of item 19 | ptItem = svgNewItem( ptXmlNode ); 20 | if( ptItem==NULL ) 21 | return NULL; 22 | 23 | ptItem->tKind = SVG_ITEM_KIND_RECT; 24 | 25 | // x 26 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"x" ) )!=NULL ) 27 | svgStringToCoordinate( szValue, &ptItem->tParameters.tRect.tX ); 28 | // y 29 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"y" ) )!=NULL ) 30 | svgStringToCoordinate( szValue, &ptItem->tParameters.tRect.tY ); 31 | // width 32 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"width" ) )!=NULL ) 33 | svgStringToLength( szValue, &ptItem->tParameters.tRect.tWidth ); 34 | // height 35 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"height" ) )!=NULL ) 36 | svgStringToLength( szValue, &ptItem->tParameters.tRect.tHeight ); 37 | // rx 38 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"rx" ) )!=NULL ) 39 | svgStringToLength( szValue, &ptItem->tParameters.tRect.tRadiusX ); 40 | // ry 41 | if( ( szValue = ( char* )xmlGetProp( ptXmlNode, ( xmlChar* )"ry" ) )!=NULL ) 42 | svgStringToLength( szValue, &ptItem->tParameters.tRect.tRadiusY ); 43 | 44 | return ptItem; 45 | } 46 | -------------------------------------------------------------------------------- /sources/parser/svg_parser_title.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_parser.h" 4 | #include "svg_xml.h" 5 | #include "svg_types.h" 6 | #include "svg_string.h" 7 | 8 | svgItem* svgParseTitle( xmlNode * ptXmlNode ) 9 | { 10 | svgItem *ptItem = NULL; 11 | xmlNodePtr ptXmlValue; 12 | 13 | if( ptXmlNode==NULL ) 14 | return NULL; 15 | if( strcmp( ( char* )ptXmlNode->name, SVG_TAG_TITLE )!=0 ) 16 | return NULL; 17 | 18 | // Read common values to all kind of item 19 | ptItem = svgNewItem( ptXmlNode ); 20 | if( ptItem==NULL ) 21 | return NULL; 22 | 23 | ptItem->tKind = SVG_ITEM_KIND_TITLE; 24 | 25 | if( ( ptXmlValue = GetChild( ptXmlNode, XML_TEXT_NODE, "text" ) )!=NULL ) { 26 | if( ptXmlValue->content!=NULL ) 27 | ptItem->tParameters.tTitle.szText = strdup( ( char* )ptXmlValue->content ); 28 | } 29 | 30 | return ptItem; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /sources/svg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "svg.h" 7 | #include "svg_parser.h" 8 | 9 | svgDrawing* svgOpenFile( const char *szFile ) 10 | { 11 | svgDrawing *ptDrawing = NULL; 12 | xmlDocPtr ptXml = NULL; 13 | xmlNodePtr ptXmlRoot; 14 | char *szValue; 15 | 16 | // check parameters 17 | if( szFile==NULL ) { 18 | svgSetLastError( SVG_ERR_INVALID_PARAMETER, "szFile can't be NULL." ); 19 | goto _exit; 20 | } 21 | if( access( szFile, F_OK )!=0 ) { 22 | svgSetLastError( SVG_ERR_NO_SUCH_FILE, "No such file." ); 23 | goto _exit; 24 | } 25 | 26 | // Open SVG file 27 | ptXml = xmlParseFile( szFile ); 28 | if( ptXml==NULL ) { 29 | svgSetLastError( SVG_ERR_BAD_FILE_FORMAT, "Can't parse XML file." ); 30 | goto _exit; 31 | } 32 | 33 | ptXmlRoot = xmlDocGetRootElement( ptXml ); 34 | if( ptXmlRoot==NULL ) { 35 | svgSetLastError( SVG_ERR_BAD_FILE_FORMAT, "Can't get XML root node." ); 36 | goto _exit; 37 | } 38 | if( strcmp( ( char* )ptXmlRoot->name, "svg" )!=0 ) { 39 | svgSetLastError( SVG_ERR_BAD_FILE_FORMAT, "Can't get SVG root node." ); 40 | goto _exit; 41 | } 42 | 43 | // Initialize SVG drawing 44 | ptDrawing = ( svgDrawing* )malloc( sizeof( *ptDrawing ) ); 45 | if( ptDrawing==NULL ) { 46 | svgSetLastError( SVG_ERR_NOT_ENOUGH_RAM, "Not enough RAM to create SVG drawing." ); 47 | goto _exit; 48 | } 49 | memset( ptDrawing, 0, sizeof( *ptDrawing ) ); 50 | 51 | // SVG's version number 52 | if( ( szValue = ( char* )xmlGetProp( ptXmlRoot, ( xmlChar* )"version" ) )!=NULL ) 53 | ptDrawing->szVersion = strdup( szValue ); 54 | // SVG's ID 55 | if( ( szValue = ( char* )xmlGetProp( ptXmlRoot, ( xmlChar* )"id" ) )!=NULL ) 56 | ptDrawing->szId = strdup( szValue ); 57 | // SVG's X coordinate 58 | if( ( szValue = ( char* )xmlGetProp( ptXmlRoot, ( xmlChar* )"x" ) )!=NULL ) 59 | svgStringToCoordinate( szValue, &ptDrawing->tX ); 60 | // SVG's Y coordinate 61 | if( ( szValue = ( char* )xmlGetProp( ptXmlRoot, ( xmlChar* )"y" ) )!=NULL ) 62 | svgStringToCoordinate( szValue, &ptDrawing->tY ); 63 | // SVG's Width 64 | ptDrawing->tWidth.fValue = 100; 65 | ptDrawing->tWidth.tUnit = SVG_LENGTH_UNIT_PERCENT; 66 | if( ( szValue = ( char* )xmlGetProp( ptXmlRoot, ( xmlChar* )"width" ) )!=NULL ) 67 | svgStringToLength( szValue, &ptDrawing->tWidth ); 68 | // SVG's Height 69 | ptDrawing->tHeight.fValue = 100; 70 | ptDrawing->tHeight.tUnit = SVG_LENGTH_UNIT_PERCENT; 71 | if( ( szValue = ( char* )xmlGetProp( ptXmlRoot, ( xmlChar* )"height" ) )!=NULL ) 72 | svgStringToLength( szValue, &ptDrawing->tHeight ); 73 | 74 | 75 | // Parse the svg objects 76 | svgParseFile( ptXmlRoot, ptDrawing ); 77 | 78 | _exit: 79 | // Free memory 80 | if( ptXml!=NULL ) 81 | xmlFreeDoc( ptXml ); 82 | 83 | return ptDrawing; 84 | } 85 | 86 | void svgFreeItem( svgItem *ptItem ) 87 | { 88 | svgPathCommand *ptPathCmd, *ptNextPathCmd; 89 | svgPoint *ptPoint, *ptNextPoint; 90 | if( ptItem==NULL ) 91 | return; 92 | 93 | if( ptItem->szId!=NULL ) 94 | free( ptItem->szId ); 95 | 96 | switch( ptItem->tKind ) 97 | { 98 | case SVG_ITEM_KIND_GROUP: 99 | break; 100 | case SVG_ITEM_KIND_PATH: 101 | ptPathCmd = ptItem->tParameters.tPath.ptFirstCommand; 102 | while( ptPathCmd!=NULL ) { 103 | ptNextPathCmd = ptPathCmd->ptNextCommand; 104 | free( ptPathCmd ); 105 | ptPathCmd = ptNextPathCmd; 106 | } 107 | break; 108 | case SVG_ITEM_KIND_RECT: 109 | break; 110 | case SVG_ITEM_KIND_CIRCLE: 111 | break; 112 | case SVG_ITEM_KIND_ELLIPSE: 113 | break; 114 | case SVG_ITEM_KIND_LINE: 115 | break; 116 | case SVG_ITEM_KIND_POLYLINE: 117 | ptPoint = ptItem->tParameters.tPolyline.tFirstPoint.ptNextPoint; 118 | while( ptPoint!=NULL ) { 119 | ptNextPoint = ptPoint->ptNextPoint; 120 | free( ptPoint ); 121 | ptPoint = ptNextPoint; 122 | } 123 | break; 124 | case SVG_ITEM_KIND_POLYGON: 125 | ptPoint = ptItem->tParameters.tPolygon.tFirstPoint.ptNextPoint; 126 | while( ptPoint!=NULL ) { 127 | ptNextPoint = ptPoint->ptNextPoint; 128 | free( ptPoint ); 129 | ptPoint = ptNextPoint; 130 | } 131 | break; 132 | case SVG_ITEM_KIND_TITLE: 133 | if( ptItem->tParameters.tTitle.szText!=NULL ) 134 | free( ptItem->tParameters.tTitle.szText ); 135 | break; 136 | case SVG_ITEM_KIND_DESC: 137 | if( ptItem->tParameters.tTitle.szText!=NULL ) 138 | free( ptItem->tParameters.tDesc.szText ); 139 | break; 140 | } 141 | 142 | free( ptItem ); 143 | } 144 | 145 | void svgFreeDrawing( svgDrawing *ptDrawing ) 146 | { 147 | svgItem *ptItem, *ptNextItem; 148 | if( ptDrawing==NULL ) 149 | return; 150 | 151 | // Common attributes 152 | if( ptDrawing->szId!=NULL ) 153 | free( ptDrawing->szId ); 154 | if( ptDrawing->szVersion!=NULL ) 155 | free( ptDrawing->szVersion ); 156 | 157 | // Free items...We use the unsorted list to make it simpler 158 | ptItem = ptDrawing->tItemList.ptItem; 159 | while( ptItem!=NULL ){ 160 | // since we'll free the current item we must store the location to the next one 161 | ptNextItem = ptItem->ptNextUnsortedItem; 162 | svgFreeItem( ptItem ); 163 | 164 | // Next 165 | ptItem = ptNextItem; 166 | } 167 | 168 | free( ptDrawing ); 169 | } 170 | 171 | -------------------------------------------------------------------------------- /sources/svg_errors.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "svg_errors.h" 5 | 6 | static svgError g_tLastError = SVG_ERR_SUCCESS; 7 | static char g_szLastErrorDesc[ 128 ] = "No error"; 8 | 9 | svgError svgSetLastError( svgError tError, const char *szDesc, ... ) 10 | { 11 | va_list tVaList; 12 | 13 | if( szDesc!=NULL ) { 14 | va_start( tVaList, szDesc ); 15 | vsprintf( g_szLastErrorDesc, szDesc, tVaList ); 16 | va_end( tVaList ); 17 | } 18 | else 19 | g_szLastErrorDesc[ 0 ] = '\0'; 20 | 21 | g_tLastError = tError; 22 | return tError; 23 | } 24 | 25 | svgError svgGetLastError( void ) 26 | { 27 | return g_tLastError; 28 | } 29 | 30 | char* svgGetLastErrorDescription( void ) 31 | { 32 | return g_szLastErrorDesc; 33 | } 34 | -------------------------------------------------------------------------------- /sources/svg_string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "svg_string.h" 7 | #include "svg_types.h" 8 | 9 | const char* svgSkipWS( const char* szStart, const char *szEOF ); 10 | const char* svgSkipDigits( const char* szStart, const char* szEOF ); 11 | 12 | 13 | const char* svgGetNextPathField( const char *szData, char *szField, int n ) 14 | { 15 | const char *szStart = NULL, *szEnd = NULL, *szEOF = szData + n - 1; 16 | 17 | if( szData==NULL || szField==NULL ) 18 | return NULL; 19 | 20 | szField[ 0 ] = '\0'; 21 | 22 | // Search for the start of the field 23 | szStart = szData; 24 | szStart = svgSkipWS(szStart, szEOF); 25 | if( szStart==szEOF || *szStart=='\0' ) 26 | return NULL; 27 | 28 | if ( *szStart==',' ) { 29 | szStart ++; 30 | szStart = svgSkipWS(szStart, szEOF); 31 | if( szStart==szEOF || *szStart=='\0' ) 32 | return NULL; 33 | } else if ( svgIsCommand( *szStart ) ) { 34 | szField[ 0 ] = *szStart; 35 | szField[ 1 ] = 0; 36 | return szStart; 37 | } 38 | 39 | // Search for the end 40 | szEnd = szStart; 41 | if (szEnd != szEOF && ( *szEnd=='-' || *szEnd =='+' ) ) 42 | szEnd ++; 43 | szEnd = svgSkipDigits( szEnd, szEOF ); 44 | if (szEnd != szEOF && *szEnd == '.') { 45 | szEnd ++; 46 | szEnd = svgSkipDigits( szEnd, szEOF ); 47 | } 48 | // TODO: handle exponent 49 | 50 | assert( szEnd - szStart < n ); 51 | strncpy( szField, szStart, ( size_t )( szEnd - szStart ) ); 52 | szField[ szEnd - szStart ] = 0; 53 | 54 | return szStart; 55 | } 56 | 57 | const char* svgGetNextPointField( const char *szData, char *szField, int n ) 58 | { 59 | const char *szStart = NULL, *szEnd = NULL, *szEOF = szData + n - 1; 60 | 61 | if( szData==NULL || szField==NULL ) 62 | return NULL; 63 | 64 | szField[ 0 ] = '\0'; 65 | 66 | // Search for the start of the field 67 | szStart = szData; 68 | szStart = svgSkipWS(szStart, szEOF); 69 | if( szStart==szEOF || *szStart=='\0' ) 70 | return NULL; 71 | 72 | if ( *szStart==',' ) { 73 | szStart ++; 74 | szStart = svgSkipWS(szStart, szEOF); 75 | if( szStart==szEOF || *szStart=='\0' ) 76 | return NULL; 77 | } 78 | 79 | // Search for the end 80 | szEnd = szStart; 81 | if (szEnd != szEOF && ( *szEnd=='-' || *szEnd =='+' ) ) 82 | szEnd ++; 83 | szEnd = svgSkipDigits( szEnd, szEOF ); 84 | if (szEnd != szEOF && *szEnd == '.') { 85 | szEnd ++; 86 | szEnd = svgSkipDigits( szEnd, szEOF ); 87 | } 88 | // TODO: handle exponent 89 | 90 | assert( szEnd - szStart < n ); 91 | strncpy( szField, szStart, ( size_t )( szEnd - szStart ) ); 92 | szField[ szEnd - szStart ] = 0; 93 | 94 | return szStart; 95 | } 96 | 97 | char svgIsCommand( char c ) 98 | { 99 | int i; 100 | for( i = 0; g_atPathCommandFormat[ i ].cCommand!='\0'; i ++ ) { 101 | if( g_atPathCommandFormat[ i].cCommand==c ) 102 | return 1; 103 | } 104 | return 0; 105 | } 106 | 107 | char svgIsRealNumber( const char *szString ) 108 | { 109 | if( szString==NULL ) 110 | return 0; 111 | 112 | if ( *szString=='-' || *szString =='+' ) 113 | szString ++; 114 | 115 | szString = svgSkipDigits( szString, NULL ); 116 | if (*szString == '.') { 117 | szString ++; 118 | szString = svgSkipDigits( szString, NULL ); 119 | } 120 | 121 | // If we reach the end of the string that means it was a real number 122 | if( *szString=='\0' ) 123 | return 1; 124 | 125 | return 0; 126 | } 127 | 128 | const char* svgSkipWS( const char* szStart, const char *szEOF ) 129 | { 130 | const char* szEnd = szStart; 131 | while( szEnd!=szEOF && *szEnd!='\0' && isspace( *szEnd ) ) { 132 | szEnd ++; 133 | } 134 | return szEnd; 135 | } 136 | 137 | const char* svgSkipDigits( const char* szStart, const char* szEOF ) 138 | { 139 | const char* szEnd = szStart; 140 | while( szEnd!=szEOF && *szEnd!='\0' && isdigit( *szEnd ) ) { 141 | szEnd ++; 142 | } 143 | return szEnd; 144 | } 145 | -------------------------------------------------------------------------------- /sources/svg_types.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "svg_types.h" 5 | #include "svg_errors.h" 6 | 7 | const svgPathCommandFormat g_atPathCommandFormat[] = { 8 | { 'M', 2, SVG_PATH_CMD_ID_MOVETO_ABS }, 9 | { 'm', 2, SVG_PATH_CMD_ID_MOVETO_REL }, 10 | { 'L', 2, SVG_PATH_CMD_ID_LINETO_ABS }, 11 | { 'l', 2, SVG_PATH_CMD_ID_LINETO_REL }, 12 | { 'V', 1, SVG_PATH_CMD_ID_VERTICAL_LINETO_ABS }, 13 | { 'v', 1, SVG_PATH_CMD_ID_VERTICAL_LINETO_REL }, 14 | { 'H', 1, SVG_PATH_CMD_ID_HORIZONTAL_LINETO_ABS }, 15 | { 'h', 1, SVG_PATH_CMD_ID_HORIZONTAL_LINETO_REL }, 16 | { 'C', 6, SVG_PATH_CMD_ID_CUBIC_CURVETO_ABS }, 17 | { 'c', 6, SVG_PATH_CMD_ID_CUBIC_CURVETO_REL }, 18 | { 'S', 4, SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_ABS }, 19 | { 's', 4, SVG_PATH_CMD_ID_SMOOTH_CUBIC_CURVETO_REL }, 20 | { 'Q', 4, SVG_PATH_CMD_ID_QUADRATIC_CURVETO_ABS }, 21 | { 'q', 4, SVG_PATH_CMD_ID_QUADRATIC_CURVETO_REL }, 22 | { 'T', 2, SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_ABS }, 23 | { 't', 2, SVG_PATH_CMD_ID_SMOOTH_QUADRATIC_CURVETO_REL }, 24 | { 'A', 7, SVG_PATH_CMD_ID_ARCTO_ABS }, 25 | { 'a', 7, SVG_PATH_CMD_ID_ARCTO_REL }, 26 | { 'Z', 0, SVG_PATH_CMD_ID_CLOSEPATH }, 27 | { 'z', 0, SVG_PATH_CMD_ID_CLOSEPATH }, 28 | { '\0', 0, 0 }, 29 | }; 30 | 31 | 32 | void svgStringToLength( const char *szValue, svgLength *ptLength ) 33 | { 34 | char szUnit[ 8 ] = ""; 35 | 36 | if( szValue==NULL || ptLength==NULL ) 37 | return; 38 | 39 | memset( ptLength, 0, sizeof( *ptLength ) ); 40 | sscanf( szValue, "%f%s", &ptLength->fValue, szUnit ); 41 | 42 | ptLength->tUnit = SVG_LENGTH_UNIT_NONE; 43 | if( szUnit[ 0 ]=='\0' ) 44 | return; 45 | 46 | if( strcmp( szUnit, "em" )==0 ) 47 | ptLength->tUnit = SVG_LENGTH_UNIT_EM; 48 | else if( strcmp( szUnit, "ex" )==0 ) 49 | ptLength->tUnit = SVG_LENGTH_UNIT_EX; 50 | else if( strcmp( szUnit, "in" )==0 ) 51 | ptLength->tUnit = SVG_LENGTH_UNIT_IN; 52 | else if( strcmp( szUnit, "cm" )==0 ) 53 | ptLength->tUnit = SVG_LENGTH_UNIT_CM; 54 | else if( strcmp( szUnit, "mm" )==0 ) 55 | ptLength->tUnit = SVG_LENGTH_UNIT_MM; 56 | else if( strcmp( szUnit, "pt" )==0 ) 57 | ptLength->tUnit = SVG_LENGTH_UNIT_PT; 58 | else if( strcmp( szUnit, "pc" )==0 ) 59 | ptLength->tUnit = SVG_LENGTH_UNIT_PC; 60 | else if( strcmp( szUnit, "%" )==0 ) 61 | ptLength->tUnit = SVG_LENGTH_UNIT_PERCENT; 62 | else if( strcmp( szUnit, "px" )==0 ) 63 | ptLength->tUnit = SVG_LENGTH_UNIT_PX; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /sources/svg_xml.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "svg_xml.h" 4 | 5 | xmlNodePtr GetChild( xmlNodePtr ptXmlNode, xmlElementType tType, char *szChildName ) 6 | { 7 | xmlNodePtr ptXmlChild; 8 | 9 | if( ptXmlNode==NULL || szChildName==NULL ) 10 | return NULL; 11 | 12 | ptXmlChild = ptXmlNode->children; 13 | while( ptXmlChild!=NULL ) 14 | { 15 | if( ptXmlChild->type==tType && strcmp( ( char* )ptXmlChild->name, szChildName )==0 ) 16 | break; 17 | } 18 | 19 | return ptXmlChild; 20 | } 21 | --------------------------------------------------------------------------------