Externalise sublibrairy from basic repository ewol

This commit is contained in:
Edouard DUPIN 2012-07-17 10:25:23 +02:00
commit 5d199e05c9
31 changed files with 3278 additions and 0 deletions

32
Android.mk Normal file
View File

@ -0,0 +1,32 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# name of the librairy
LOCAL_MODULE := parsersvg
# name of the dependency
LOCAL_STATIC_LIBRARIES := libetk libagg libtinyxml
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
ifeq ($(DEBUG),1)
LOCAL_CFLAGS := -D__PLATFORM__Android \
-DSVG_DEBUG_LEVEL=3 \
-DPARSER_SVG_VERSION_TAG_NAME="\"???-debug\"" \
else
LOCAL_CFLAGS := -D__PLATFORM__Android \
-DSVG_DEBUG_LEVEL=1 \
-DPARSER_SVG_VERSION_TAG_NAME="\"???-release\""
endif
# load the common sources file of the platform
include $(LOCAL_PATH)/file.mk
LOCAL_SRC_FILES := $(FILE_LIST)
include $(BUILD_STATIC_LIBRARY)

29
Linux.mk Normal file
View File

@ -0,0 +1,29 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# name of the librairy
LOCAL_MODULE := parsersvg
# name of the dependency
LOCAL_STATIC_LIBRARIES := etk agg tinyxml
LOCAL_C_INCLUDES :=
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
ifeq ($(DEBUG),1)
LOCAL_CFLAGS := -D__PLATFORM__Linux \
-DSVG_DEBUG_LEVEL=3 \
-Wall
else
LOCAL_CFLAGS := -D__PLATFORM__Linux \
-DSVG_DEBUG_LEVEL=1
endif
# load the common sources file of the platform
include $(LOCAL_PATH)/file.mk
LOCAL_SRC_FILES := $(FILE_LIST)
include $(BUILD_STATIC_LIBRARY)

16
file.mk Normal file
View File

@ -0,0 +1,16 @@
FILE_LIST = parserSVG/Base.cpp \
parserSVG/Circle.cpp \
parserSVG/Debug.cpp \
parserSVG/Ellipse.cpp \
parserSVG/Group.cpp \
parserSVG/Line.cpp \
parserSVG/parserSVG.cpp \
parserSVG/Path.cpp \
parserSVG/Polygon.cpp \
parserSVG/Polyline.cpp \
parserSVG/Rectangle.cpp \
parserSVG/Renderer.cpp \
parserSVG/Stroking.cpp \
parserSVG/Text.cpp

469
parserSVG/Base.cpp Normal file
View File

@ -0,0 +1,469 @@
/**
*******************************************************************************
* @file parserSVG/Base.cpp
* @brief basic Element parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Base.h>
#include <math.h>
svg::Base::Base(PaintState parentPaintState)
{
// copy the parent painting properties ...
m_paint = parentPaintState;
}
/**
* @brief Parse the transform balise C String.
* @param[in] inputString String data inside the transform attribute
* @param[in,out] baseMatrice matrice that must be update
* @return ---
*/
void svg::Base::ParseTransform(TiXmlNode *node)
{
SVG_CHECK_INOUT(node);
const char * inputString = (char*)node->ToElement()->Attribute("transform");
if (NULL == inputString) {
return;
}
SVG_VERBOSE("find transform : \"" << inputString << "\"");
char tmpData[2048];
for (int32_t iii=0; inputString[iii]!='\0' && iii<2047; iii++) {
if (inputString[iii] == ',') {
tmpData[iii] = ' ';
} else {
tmpData[iii] = inputString[iii];
}
// end of the string ...
tmpData[iii+1] = '\0';
}
SVG_VERBOSE("find transform : \"" << tmpData << "\"");
double matrix[6];
float angle, xxx, yyy;
int32_t n;
char * pointerOnData = tmpData;
while (*pointerOnData) {
if (sscanf(pointerOnData, "matrix (%lf %lf %lf %lf %lf %lf) %n", &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5], &n) == 6) {
m_transformMatrix.load_from(matrix);
} else if (sscanf(pointerOnData, "translate (%f %f) %n", &xxx, &yyy, &n) == 2) {
m_transformMatrix *= agg::trans_affine_translation(xxx, yyy);
SVG_VERBOSE("Translate : " << xxx << ", " << yyy);
} else if (sscanf(pointerOnData, "translate (%f) %n", &xxx, &n) == 1) {
m_transformMatrix *= agg::trans_affine_translation(xxx, 0);
SVG_VERBOSE("Translate : " << xxx << ", " << 0);
} else if (sscanf(pointerOnData, "scale (%f %f) %n", &xxx, &yyy, &n) == 2) {
m_transformMatrix *= agg::trans_affine_scaling(xxx, yyy);
SVG_VERBOSE("Scale : " << xxx << ", " << yyy);
} else if (sscanf(pointerOnData, "scale (%f) %n", &xxx, &n) == 1) {
m_transformMatrix *= agg::trans_affine_scaling(xxx, xxx);
SVG_VERBOSE("Scale : " << xxx << ", " << xxx);
} else if (sscanf(pointerOnData, "rotate (%f %f %f) %n", &angle, &xxx, &yyy, &n) == 3) {
angle = angle / 180 * M_PI;
m_transformMatrix *= agg::trans_affine_translation(-xxx, -yyy);
m_transformMatrix *= agg::trans_affine_rotation(angle);
m_transformMatrix *= agg::trans_affine_translation(xxx, yyy);
} else if (sscanf(pointerOnData, "rotate (%f) %n", &angle, &n) == 1) {
angle = angle / 180 * M_PI;
SVG_VERBOSE("rotate : " << angle << "rad, " << (angle/M_PI*180) << "°");
m_transformMatrix *= agg::trans_affine_rotation(angle);
} else if (sscanf(pointerOnData, "skewX (%f) %n", &angle, &n) == 1) {
angle = angle / 180 * M_PI;
SVG_VERBOSE("skewX : " << angle << "rad, " << (angle/M_PI*180) << "\Uffffffff");
m_transformMatrix *= agg::trans_affine_skewing(angle, 0.0);
} else if (sscanf(pointerOnData, "skewY (%f) %n", &angle, &n) == 1) {
angle = angle / 180 * M_PI;
SVG_VERBOSE("skewY : " << angle << "rad, " << (angle/M_PI*180) << "\Uffffffff");
m_transformMatrix *= agg::trans_affine_skewing(0.0, angle);
} else {
break;
}
pointerOnData += n;
}
}
/**
* @brief Parse x, y, width, height attribute of the xml node
* @param[in] node XML node
* @param[out] pos parsed position
* @param[out] size parsed dimention
* @return ---
*/
void svg::Base::ParsePosition(const TiXmlNode *node, Vector2D<float> &pos, Vector2D<float> &size)
{
pos.x = 0;
pos.y = 0;
size.x = 0;
size.y = 0;
const char * content = node->ToElement()->Attribute("x");
if (NULL != content) {
pos.x = ParseLength(content);
}
content = node->ToElement()->Attribute("y");
if (NULL != content) {
pos.y = ParseLength(content);
}
content = node->ToElement()->Attribute("width");
if (NULL != content) {
size.x = ParseLength(content);
}
content = node->ToElement()->Attribute("height");
if (NULL != content) {
size.y = ParseLength(content);
}
}
/**
* @brief Parse a lenght of the xml element
* @param[in] dataInput Data C String with the printed lenght
* @return standart number of pixels
*/
float svg::Base::ParseLength(const char *dataInput)
{
int32_t numLength = strspn(dataInput, "0123456789+-.");
const char *unit = dataInput + numLength;
//SVG_INFO(" ==> \"" << dataInput << "\"");
float n = atof(dataInput);
//SVG_INFO(" ==> ?? = " << n );
float font_size = 20.0;
// note : ";" is for the parsing of the style elements ...
if (unit[0] == '\0' || unit[0] == ';' ) {
return n;
} else if (unit[0] == '%') { // xxx %
return n / 100.0 * m_paint.viewPort.x;
} else if (unit[0] == 'e' && unit[1] == 'm') { // xxx em
return n * font_size;
} else if (unit[0] == 'e' && unit[1] == 'x') { // xxx ex
return n / 2.0 * font_size;
} else if (unit[0] == 'p' && unit[1] == 'x') { // xxx px
return n;
} else if (unit[0] == 'p' && unit[1] == 't') { // xxx pt
return n * 1.25;
} else if (unit[0] == 'p' && unit[1] == 'c') { // xxx pc
return n * 15.0;
} else if (unit[0] == 'm' && unit[1] == 'm') { // xxx mm
return n * 3.543307;
} else if (unit[0] == 'c' && unit[1] == 'm') { // xxx cm
return n * 35.43307;
} else if (unit[0] == 'i' && unit[1] == 'n') { // xxx in
return n * 90;
}
return 0;
}
// return the next char position ... (after ';' or NULL)
const char * extractPartOfStyle(const char * input, char * outputType, char * outputData, int32_t maxLen)
{
if (*input == '\0') {
return NULL;
}
int32_t jjj = 0;
const char * outputPointer = NULL;
outputType[maxLen-1] = '\0';
outputType[0] = '\0';
outputData[maxLen-1] = '\0';
outputData[0] = '\0';
char * output = outputType;
for( int32_t iii=0; iii<maxLen-1 && input[iii]!='\0'; iii++) {
outputPointer = &input[iii];
if (input[iii] != ';') {
if (input[iii] == ' ') {
// nothing to do ... we do not copy espaces ...
} else if (input[iii] == ':') {
// change the output ...
output = outputData;
jjj = 0;
} else {
output[jjj] = input[iii];
output[jjj+1] = '\0';
jjj++;
}
} else {
break;
}
}
outputPointer++;
return outputPointer;
}
/**
* @brief Parse a Painting attribute of a specific node
* @param[in] node : basic node of the XML that might be parsed
* @return ---
*/
void svg::Base::ParsePaintAttr(const TiXmlNode *node)
{
bool fillNone = false;
bool strokeNone = false;
const char * content = node->ToElement()->Attribute("fill");
if (NULL != content) {
m_paint.fill = ParseColor(content);
if (m_paint.fill.alpha == 0) {
fillNone = true;
}
}
content = node->ToElement()->Attribute("stroke");
if (NULL != content) {
m_paint.stroke = ParseColor(content);
if (m_paint.stroke.alpha == 0) {
strokeNone = true;
}
}
content = node->ToElement()->Attribute("stroke-width");
if (NULL != content) {
m_paint.strokeWidth = ParseLength(content);
}
content = node->ToElement()->Attribute("opacity");
if (NULL != content) {
float opacity = ParseLength(content);
opacity = etk_max(0.0, etk_min(1.0, opacity));
m_paint.fill.alpha = opacity*0xFF;
m_paint.stroke.alpha = opacity*0xFF;
}
content = node->ToElement()->Attribute("fill-opacity");
if (NULL != content) {
float opacity = ParseLength(content);
opacity = etk_max(0.0, etk_min(1.0, opacity));
m_paint.fill.alpha = opacity*0xFF;
}
content = node->ToElement()->Attribute("stroke-opacity");
if (NULL != content) {
float opacity = ParseLength(content);
opacity = etk_max(0.0, etk_min(1.0, opacity));
m_paint.stroke.alpha = opacity*0xFF;
}
content = node->ToElement()->Attribute("fill-rule");
if (NULL != content) {
if (0 == strcmp(content, "nonzero") ) {
m_paint.flagEvenOdd = false;
} else if (0 == strcmp(content, "evenodd") ) {
m_paint.flagEvenOdd = true;
} else {
SVG_ERROR("not know fill-rule value : \"" << content << "\", not in [nonzero,evenodd]");
}
}
content = node->ToElement()->Attribute("stroke-linecap");
if (NULL != content) {
if (0 == strcmp(content, "butt") ) {
m_paint.lineCap = svg::LINECAP_BUTT;
} else if (0 == strcmp(content, "round") ) {
m_paint.lineCap = svg::LINECAP_ROUND;
} else if (0 == strcmp(content, "square") ) {
m_paint.lineCap = svg::LINECAP_SQUARE;
} else {
m_paint.lineCap = svg::LINECAP_BUTT;
SVG_ERROR("not know stroke-linecap value : \"" << content << "\", not in [butt,round,square]");
}
}
content = node->ToElement()->Attribute("stroke-linejoin");
if (NULL != content) {
if (0 == strcmp(content, "miter") ) {
m_paint.lineJoin = svg::LINEJOIN_MITER;
} else if (0 == strcmp(content, "round") ) {
m_paint.lineJoin = svg::LINEJOIN_ROUND;
} else if (0 == strcmp(content, "bevel") ) {
m_paint.lineJoin = svg::LINEJOIN_BEVEL;
} else {
m_paint.lineJoin = svg::LINEJOIN_MITER;
SVG_ERROR("not know stroke-linejoin value : \"" << content << "\", not in [miter,round,bevel]");
}
}
content = node->ToElement()->Attribute("style");
if (NULL != content) {
char outputType[1024] = "";
char outputValue[1024] = "";
for( const char *sss=extractPartOfStyle(content, outputType, outputValue, 1024);
NULL != sss;
sss=extractPartOfStyle(sss, outputType, outputValue, 1024) ) {
SVG_VERBOSE(" style parse : \"" << outputType << "\" with value : \"" << outputValue << "\"");
if (0 == strcmp(outputType, "fill") ) {
m_paint.fill = ParseColor(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" ==> " << m_paint.fill);
if (m_paint.fill.alpha == 0) {
fillNone = true;
}
} else if (0 == strcmp(outputType, "stroke") ) {
m_paint.stroke = ParseColor(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" ==> " << m_paint.stroke);
if (m_paint.stroke.alpha == 0) {
strokeNone = true;
}
} else if (0 == strcmp(outputType, "stroke-width") ) {
m_paint.strokeWidth = ParseLength(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" ==> " << m_paint.strokeWidth);
} else if (0 == strcmp(outputType, "opacity") ) {
float opacity = ParseLength(outputValue);
opacity = etk_max(0.0, etk_min(1.0, opacity));
m_paint.fill.alpha = opacity*0xFF;
m_paint.stroke.alpha = opacity*0xFF;
SVG_VERBOSE(" input : \"" << outputValue << "\" ==> " << m_paint.fill);
} else if (0 == strcmp(outputType, "fill-opacity") ) {
float opacity = ParseLength(outputValue);
opacity = etk_max(0.0, etk_min(1.0, opacity));
m_paint.fill.alpha = opacity*0xFF;
SVG_VERBOSE(" input : \"" << outputValue << "\" ==> " << m_paint.fill);
} else if (0 == strcmp(outputType, "stroke-opacity") ) {
float opacity = ParseLength(outputValue);
opacity = etk_max(0.0, etk_min(1.0, opacity));
m_paint.stroke.alpha = opacity*0xFF;
SVG_VERBOSE(" input : \"" << outputValue << "\" ==> " << m_paint.stroke);
} else if (0 == strcmp(outputType, "fill-rule") ) {
if (0 == strcmp(outputValue, "nonzero") ) {
m_paint.flagEvenOdd = false;
} else if (0 == strcmp(outputValue, "evenodd") ) {
m_paint.flagEvenOdd = true;
} else {
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [nonzero,evenodd]");
}
} else if (0 == strcmp(outputType, "stroke-linecap") ) {
if (0 == strcmp(outputValue, "butt") ) {
m_paint.lineCap = svg::LINECAP_BUTT;
} else if (0 == strcmp(outputValue, "round") ) {
m_paint.lineCap = svg::LINECAP_ROUND;
} else if (0 == strcmp(outputValue, "square") ) {
m_paint.lineCap = svg::LINECAP_SQUARE;
} else {
m_paint.lineCap = svg::LINECAP_BUTT;
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [butt,round,square]");
}
} else if (0 == strcmp(outputType, "stroke-linejoin") ) {
if (0 == strcmp(outputValue, "miter") ) {
m_paint.lineJoin = svg::LINEJOIN_MITER;
} else if (0 == strcmp(outputValue, "round") ) {
m_paint.lineJoin = svg::LINEJOIN_ROUND;
} else if (0 == strcmp(outputValue, "bevel") ) {
m_paint.lineJoin = svg::LINEJOIN_BEVEL;
} else {
m_paint.lineJoin = svg::LINEJOIN_MITER;
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [miter,round,bevel]");
}
} else if (0 == strcmp(outputType, "marker-start") ) {
// TODO : ...
} else {
SVG_ERROR("not know painting element in style balise : \"" << outputType << "\" with value : \"" << outputValue << "\"");
}
}
}
// check if somewere none is set to the filling:
if (true == fillNone) {
m_paint.fill.alpha = 0;
}
if (true == strokeNone) {
m_paint.stroke.alpha = 0;
}
}
bool strnCmpNoCase(const char * input1, const char * input2, int32_t maxLen)
{
int32_t iii=0;
while ('\0' != *input1 && '\0' != *input2 && iii < maxLen) {
char in1 = *input1;
char in2 = *input2;
if (in1 != in2) {
if (in1 <= 'Z' && in1 >= 'A') {
in1 = in1 - 'A' + 'a';
}
if (in2 <= 'Z' && in2 >= 'A') {
in2 = in2 - 'A' + 'a';
}
if (in1 != in2) {
return false;
}
}
iii++;
input1++;
input2++;
}
return true;
}
/**
* @brief Parse a color specification from the svg file
* @param[in] inputData Data C String with the xml definition
* @return the parsed color
*/
color_ts svg::Base::ParseColor(const char *inputData)
{
color_ts localColor = etk::color::color_White;;
size_t len = strlen(inputData);
if( 4 < len
&& inputData[0] == 'u'
&& inputData[1] == 'r'
&& inputData[2] == 'l'
&& inputData[3] == '(') {
if (inputData[4] == '#') {
// TODO : parse gradient ...
}
SVG_ERROR(" pb in parsing the color : \"" << inputData << "\" ==> url(XXX) is not supported now ...");
} else {
localColor = etk::color::Parse(inputData);
}
SVG_VERBOSE("Parse color : \"" << inputData << "\" ==> " << localColor);
return localColor;
}
/**
* @brief Parse all the element needed in the basic node
* @param[in] node standart XML node
* @return true if no problem arrived
*/
bool svg::Base::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
SVG_ERROR("NOT IMPLEMENTED");
sizeMax.x = 0;
sizeMax.y = 0;
return false;
}
const char * svg::Base::SpacingDist(int32_t spacing)
{
static const char *tmpValue = " ";
if (spacing>20) {
spacing = 20;
}
return tmpValue + 20*4 - spacing*4;
}
/*
void svg::Base::AggCheckChange(agg::path_storage& path, etk::VectorType<agg::rgba8> &colors, etk::VectorType<uint32_t> &pathIdx, PaintState &curentPaintProp)
{
if (curentPaintProp != m_paint) {
SVG_INFO("add path color = " << m_paint.fill);
// New color. Every new color creates new path in the path object.
colors.PushBack(agg::rgba8(m_paint.fill.red, m_paint.fill.green, m_paint.fill.blue, m_paint.fill.alpha));
uint32_t tmpPathNew = path.start_new_path();
pathIdx.PushBack(tmpPathNew);
curentPaintProp = m_paint;
}
}
*/

70
parserSVG/Base.h Normal file
View File

@ -0,0 +1,70 @@
/**
*******************************************************************************
* @file parserSVG/Base.h
* @brief basic Element parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_BASE_H__
#define __SVG_BASE_H__
#include <etk/Types.h>
#include <etk/VectorType.h>
#include <tinyXML/tinyxml.h>
#include <parserSVG/Renderer.h>
#include <agg-2.4/agg_basics.h>
#include <agg-2.4/agg_rendering_buffer.h>
#include <agg-2.4/agg_rasterizer_scanline_aa.h>
#include <agg-2.4/agg_scanline_p.h>
#include <agg-2.4/agg_renderer_scanline.h>
#include <agg-2.4/agg_path_storage.h>
#include <agg-2.4/agg_conv_transform.h>
#include <agg-2.4/agg_bounding_rect.h>
#include <agg-2.4/agg_color_rgba.h>
#include <agg-2.4/agg_pixfmt_rgba.h>
namespace svg
{
class Base
{
protected:
PaintState m_paint;
agg::trans_affine m_transformMatrix; //!< specific render of the curent element
const char * SpacingDist(int32_t spacing);
public:
Base(void) {};
Base(PaintState parentPaintState);
virtual ~Base(void) { };
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
//specific drawing for AAG librairy ...
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans) { };
virtual void Display(int32_t spacing) { };
void ParseTransform(TiXmlNode *node);
void ParsePosition(const TiXmlNode *node, Vector2D<float> &pos, Vector2D<float> &size);
float ParseLength(const char *dataInput);
void ParsePaintAttr(const TiXmlNode *node);
color_ts ParseColor(const char *inputData);
};
};
#endif

116
parserSVG/Circle.cpp Normal file
View File

@ -0,0 +1,116 @@
/**
*******************************************************************************
* @file parserSVG/Circle.cpp
* @brief basic circle parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Circle.h>
#include <agg-2.4/agg_conv_stroke.h>
#include <agg-2.4/agg_ellipse.h>
svg::Circle::Circle(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Circle::~Circle(void)
{
}
bool svg::Circle::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
m_radius = 0.0;
m_position.x = 0.0;
m_position.y = 0.0;
ParseTransform(node);
ParsePaintAttr(node);
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
const char * content = node->ToElement()->Attribute("cx");
if (NULL != content) {
m_position.x = ParseLength(content);
}
content = node->ToElement()->Attribute("cy");
if (NULL != content) {
m_position.y = ParseLength(content);
}
content = node->ToElement()->Attribute("r");
if (NULL != content) {
m_radius = ParseLength(content);
} else {
SVG_ERROR("(l "<<node->Row()<<") Circle \"r\" is not present");
return false;
}
if (0 > m_radius) {
m_radius = 0;
SVG_ERROR("(l "<<node->Row()<<") Circle \"r\" is negative");
return false;
}
sizeMax.x = m_position.x + m_radius;
sizeMax.y = m_position.y + m_radius;
return true;
}
void svg::Circle::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Circle " << m_position << " radius=" << m_radius);
}
void svg::Circle::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.red, m_paint.fill.green, m_paint.fill.blue, m_paint.fill.alpha));
// Creating an ellipse
agg::ellipse myCircle(m_position.x, m_position.y, m_radius, m_radius, 0);
// Calculate transformation matrix ...
agg::trans_affine mtx = m_transformMatrix;
mtx *= basicTrans;
// set the filling mode :
myRenderer.m_rasterizer.filling_rule((m_paint.flagEvenOdd)?agg::fill_even_odd:agg::fill_non_zero);
if (m_paint.fill.alpha != 0x00) {
agg::conv_transform<agg::ellipse, agg::trans_affine> trans(myCircle, mtx);
myRenderer.m_rasterizer.add_path(trans);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
if (m_paint.strokeWidth > 0 && m_paint.stroke.alpha!=0x00 ) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::ellipse> myCircleStroke(myCircle);
myCircleStroke.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::ellipse>, agg::trans_affine> transStroke(myCircleStroke, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}

47
parserSVG/Circle.h Normal file
View File

@ -0,0 +1,47 @@
/**
*******************************************************************************
* @file parserSVG/Circle.h
* @brief basic circle parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_CIRCLE_H__
#define __SVG_CIRCLE_H__
#include <parserSVG/Base.h>
namespace svg
{
class Circle : public svg::Base
{
private:
Vector2D<float> m_position; //!< Position of the Circle
float m_radius; //!< Radius of the Circle
public:
Circle(PaintState parentPaintState);
~Circle(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

27
parserSVG/Debug.cpp Normal file
View File

@ -0,0 +1,27 @@
/**
*******************************************************************************
* @file parserSVG/Debug.h
* @brief parserSVG : log wrapper (Sources)
* @author Edouard DUPIN
* @date 18/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
const char * parserSVGLibName = "parserSVG";

75
parserSVG/Debug.h Normal file
View File

@ -0,0 +1,75 @@
/**
*******************************************************************************
* @file tinySVG/Debug.h
* @brief SVG : log wrapper (header)
* @author Edouard DUPIN
* @date 18/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __PARSER_SVG_DEBUG_H__
#define __PARSER_SVG_DEBUG_H__
#include <etk/Types.h>
#include <etk/Debug.h>
extern const char * parserSVGLibName;
#define SVG_CRITICAL(data) ETK_CRITICAL(parserSVGLibName, data)
// General
#if SVG_DEBUG_LEVEL > 0
# define SVG_WARNING(data) ETK_WARNING(parserSVGLibName, data)
# define SVG_ERROR(data) ETK_ERROR(parserSVGLibName, data)
#else
# define SVG_WARNING(data) do {}while(0)
# define SVG_ERROR(data) do {}while(0)
#endif
#if SVG_DEBUG_LEVEL > 1
# define SVG_INFO(data) ETK_INFO(parserSVGLibName, data)
#else
# define SVG_INFO(data) do {}while(0)
#endif
#if SVG_DEBUG_LEVEL > 2
# define SVG_DEBUG(data) ETK_DEBUG(parserSVGLibName, data)
#else
# define SVG_DEBUG(data) do {}while(0)
#endif
#if SVG_DEBUG_LEVEL > 3
# define SVG_VERBOSE(data) ETK_VERBOSE(parserSVGLibName, data)
#else
# define SVG_VERBOSE(data) do {}while(0)
#endif
#define SVG_TODO(data) SVG_WARNING("TODO : " << data)
#define SVG_ASSERT(cond, data) ETK_ASSERT(parserSVGLibName, cond, data)
#if SVG_DEBUG_LEVEL > 1
# define SVG_CHECK_INOUT(cond) ETK_CHECK_INOUT_ASSERT(parserSVGLibName, cond)
#elif SVG_DEBUG_LEVEL > 0
# define SVG_CHECK_INOUT(cond) ETK_CHECK_INOUT_WARNING(parserSVGLibName, cond)
#else
# define SVG_CHECK_INOUT(cond) do { } while (0)
#endif
#endif

120
parserSVG/Ellipse.cpp Normal file
View File

@ -0,0 +1,120 @@
/**
*******************************************************************************
* @file parserSVG/Ellipse.cpp
* @brief basic ellipse parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Ellipse.h>
#include <agg-2.4/agg_conv_stroke.h>
#include <agg-2.4/agg_ellipse.h>
svg::Ellipse::Ellipse(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Ellipse::~Ellipse(void)
{
}
bool svg::Ellipse::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
ParseTransform(node);
ParsePaintAttr(node);
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
m_c.x = 0.0;
m_c.y = 0.0;
m_r.x = 0.0;
m_r.y = 0.0;
const char * content = node->ToElement()->Attribute("cx");
if (NULL != content) {
m_c.x = ParseLength(content);
}
content = node->ToElement()->Attribute("cy");
if (NULL != content) {
m_c.y = ParseLength(content);
}
content = node->ToElement()->Attribute("rx");
if (NULL != content) {
m_r.x = ParseLength(content);
} else {
SVG_ERROR("(l "<<node->Row()<<") Ellipse \"rx\" is not present");
return false;
}
content = node->ToElement()->Attribute("ry");
if (NULL != content) {
m_r.y = ParseLength(content);
} else {
SVG_ERROR("(l "<<node->Row()<<") Ellipse \"ry\" is not present");
return false;
}
sizeMax.x = m_c.x + m_r.x;
sizeMax.y = m_c.y + m_r.y;
return true;
}
void svg::Ellipse::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Ellipse c=" << m_c << " r=" << m_r);
}
void svg::Ellipse::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.red, m_paint.fill.green, m_paint.fill.blue, m_paint.fill.alpha));
// Creating an ellipse
agg::ellipse myEllipse(m_c.x, m_c.y, m_r.x, m_r.y, 0);
// Calculate transformation matrix ...
agg::trans_affine mtx = m_transformMatrix;
mtx *= basicTrans;
// set the filling mode :
myRenderer.m_rasterizer.filling_rule((m_paint.flagEvenOdd)?agg::fill_even_odd:agg::fill_non_zero);
if (m_paint.fill.alpha != 0x00) {
agg::conv_transform<agg::ellipse, agg::trans_affine> trans(myEllipse, mtx);
myRenderer.m_rasterizer.add_path(trans);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
if (m_paint.strokeWidth > 0 && m_paint.stroke.alpha!=0x00 ) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::ellipse> myEllipseStroke(myEllipse);
myEllipseStroke.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::ellipse>, agg::trans_affine> transStroke(myEllipseStroke, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}

47
parserSVG/Ellipse.h Normal file
View File

@ -0,0 +1,47 @@
/**
*******************************************************************************
* @file parserSVG/Ellipse.h
* @brief basic ellipse parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_ELLIPSE_H__
#define __SVG_ELLIPSE_H__
#include <parserSVG/Base.h>
namespace svg
{
class Ellipse : public svg::Base
{
private:
Vector2D<float> m_c; //!< Center property of the ellipse
Vector2D<float> m_r; //!< Radius property of the ellipse
public:
Ellipse(PaintState parentPaintState);
~Ellipse(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

135
parserSVG/Group.cpp Normal file
View File

@ -0,0 +1,135 @@
/**
*******************************************************************************
* @file parserSVG/Group.cpp
* @brief Basic Group parsing (Sources)
* @author Edouard DUPIN
* @date 21/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Group.h>
#include <etk/UString.h>
#include <parserSVG/Base.h>
#include <parserSVG/Circle.h>
#include <parserSVG/Ellipse.h>
#include <parserSVG/Line.h>
#include <parserSVG/Path.h>
#include <parserSVG/Polygon.h>
#include <parserSVG/Polyline.h>
#include <parserSVG/Rectangle.h>
#include <parserSVG/Text.h>
#include <parserSVG/Group.h>
svg::Group::Group(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Group::~Group(void)
{
}
bool svg::Group::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
// parse ...
Vector2D<float> pos;
Vector2D<float> size;
ParseTransform(node);
ParsePosition(node, pos, size);
ParsePaintAttr(node);
SVG_VERBOSE("parsed G1. trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
SVG_VERBOSE("parsed G2. trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
sizeMax.x = 0;
sizeMax.y = 0;
Vector2D<float> tmpPos;
// parse all sub node :
for(TiXmlNode * child = node->FirstChild(); NULL != child; child = child->NextSibling() ) {
svg::Base *elementParser = NULL;
if (child->Type()==TiXmlNode::TINYXML_COMMENT) {
// nothing to do, just proceed to next step
} else {
etk::UString localValue = child->Value();
if (localValue == "g") {
elementParser = new svg::Group(m_paint);
} else if (localValue == "a") {
// TODO ...
} else if (localValue == "path") {
elementParser = new svg::Path(m_paint);
} else if (localValue == "rect") {
elementParser = new svg::Rectangle(m_paint);
} else if (localValue == "circle") {
elementParser = new svg::Circle(m_paint);
} else if (localValue == "ellipse") {
elementParser = new svg::Ellipse(m_paint);
} else if (localValue == "line") {
elementParser = new svg::Line(m_paint);
} else if (localValue == "polyline") {
elementParser = new svg::Polyline(m_paint);
} else if (localValue == "polygon") {
elementParser = new svg::Polygon(m_paint);
} else if (localValue == "text") {
elementParser = new svg::Text(m_paint);
} else {
SVG_ERROR("(l "<<child->Row()<<") node not suported : \""<<localValue<<"\" must be [g,a,path,rect,circle,ellipse,line,polyline,polygon,text]");
}
if (NULL == elementParser) {
SVG_ERROR("(l "<<child->Row()<<") error on node: \""<<localValue<<"\" allocation error or not supported ...");
} else {
if (false == elementParser->Parse(child, m_transformMatrix, tmpPos)) {
SVG_ERROR("(l "<<child->Row()<<") error on node: \""<<localValue<<"\" Sub Parsing ERROR");
delete(elementParser);
elementParser = NULL;
} else {
sizeMax.x = etk_max(sizeMax.x, tmpPos.x);
sizeMax.y = etk_max(sizeMax.y, tmpPos.y);
// add element in the system
m_subElementList.PushBack(elementParser);
}
}
}
}
return true;
}
void svg::Group::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Group (START) fill=" << m_paint.fill << " stroke=" << m_paint.stroke << " stroke-width=" << m_paint.strokeWidth );
for (int32_t iii=0; iii<m_subElementList.Size(); iii++) {
if (NULL != m_subElementList[iii]) {
m_subElementList[iii]->Display(spacing+1);
}
}
SVG_DEBUG(SpacingDist(spacing) << "Group (STOP)");
}
void svg::Group::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
for (int32_t iii=0; iii<m_subElementList.Size(); iii++) {
if (NULL != m_subElementList[iii]) {
m_subElementList[iii]->AggDraw(myRenderer, basicTrans);
}
}
}

47
parserSVG/Group.h Normal file
View File

@ -0,0 +1,47 @@
/**
*******************************************************************************
* @file parserSVG/Group.h
* @brief basic group parsing (Header)
* @author Edouard DUPIN
* @date 21/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_GROUP_H__
#define __SVG_GROUP_H__
#include <parserSVG/Base.h>
#include <etk/VectorType.h>
namespace svg
{
class Group : public svg::Base
{
private:
etk::VectorType<svg::Base *> m_subElementList; //!< group sub elements ...
public:
Group(PaintState parentPaintState);
~Group(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

127
parserSVG/Line.cpp Normal file
View File

@ -0,0 +1,127 @@
/**
*******************************************************************************
* @file parserSVG/Line.cpp
* @brief basic line parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Line.h>
#include <agg-2.4/agg_conv_stroke.h>
#include <agg-2.4/agg_path_storage.h>
svg::Line::Line(PaintState parentPaintState) : svg::Base(parentPaintState)
{
m_startPos.x = 0.0;
m_startPos.y = 0.0;
m_stopPos.x = 0.0;
m_stopPos.y = 0.0;
}
svg::Line::~Line(void)
{
}
bool svg::Line::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
// line must have a minimum size...
m_paint.strokeWidth = 1;
ParseTransform(node);
ParsePaintAttr(node);
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
const char * content = node->ToElement()->Attribute("x1");
if (NULL != content) {
m_startPos.x = ParseLength(content);
}
content = node->ToElement()->Attribute("y1");
if (NULL != content) {
m_startPos.y = ParseLength(content);
}
content = node->ToElement()->Attribute("x2");
if (NULL != content) {
m_stopPos.x = ParseLength(content);
}
content = node->ToElement()->Attribute("y2");
if (NULL != content) {
m_stopPos.y = ParseLength(content);
}
sizeMax.x = etk_max(m_startPos.x, m_stopPos.x);
sizeMax.y = etk_max(m_startPos.y, m_stopPos.y);
return true;
}
void svg::Line::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Line " << m_startPos << " to " << m_stopPos);
}
void svg::Line::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
agg::path_storage path;
path.start_new_path();
path.move_to(m_startPos.x, m_startPos.y);
path.line_to(m_stopPos.x, m_stopPos.y);
/*
// configure the end of the line :
switch (m_paint.lineCap) {
case svg::LINECAP_SQUARE:
path.line_cap(agg::square_cap);
break;
case svg::LINECAP_ROUND:
path.line_cap(agg::round_cap);
break;
default: // svg::LINECAP_BUTT
path.line_cap(agg::butt_cap);
break;
}
switch (m_paint.lineJoin) {
case svg::LINEJOIN_BEVEL:
path.line_join(agg::bevel_join);
break;
case svg::LINEJOIN_ROUND:
path.line_join(agg::round_join);
break;
default: // svg::LINEJOIN_MITER
path.line_join(agg::miter_join);
break;
}
*/
agg::trans_affine mtx = m_transformMatrix;
mtx *= basicTrans;
if (m_paint.strokeWidth > 0) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::path_storage> myPolygonStroke(path);
myPolygonStroke.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::path_storage>, agg::trans_affine> transStroke(myPolygonStroke, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}

47
parserSVG/Line.h Normal file
View File

@ -0,0 +1,47 @@
/**
*******************************************************************************
* @file parserSVG/Line.h
* @brief basic line parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_LINE_H__
#define __SVG_LINE_H__
#include <parserSVG/Base.h>
namespace svg
{
class Line : public svg::Base
{
private:
Vector2D<float> m_startPos; //!< Start line position
Vector2D<float> m_stopPos; //!< Stop line position
public:
Line(PaintState parentPaintState);
~Line(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

527
parserSVG/Path.cpp Normal file
View File

@ -0,0 +1,527 @@
/**
*******************************************************************************
* @file parserSVG/Path.cpp
* @brief basic path parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Path.h>
#include <agg-2.4/agg_conv_stroke.h>
#include <agg-2.4/agg_conv_dash.h>
#include <agg-2.4/agg_conv_curve.h>
#include <agg-2.4/agg_conv_contour.h>
#include <agg-2.4/agg_conv_smooth_poly1.h>
svg::Path::Path(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Path::~Path(void)
{
}
// return the next char position ... (after 'X' or NULL)
const char * extractCmd(const char * input, char& cmd, etk::VectorType<float>& outputList)
{
if (*input == '\0') {
return NULL;
}
outputList.Clear();
cmd = '\0';
const char * outputPointer = NULL;
if (!( (input[0] <= 'Z' && input[0] >= 'A') || (input[0] <= 'z' && input[0] >= 'a') ) ) {
SVG_ERROR("Error in the SVG Path : \"" << input << "\"");
return NULL;
}
cmd = input[0];
SVG_VERBOSE("Find command : " << cmd);
if (input[1] == '\0') {
return &input[1];
}
int32_t iii=1;
// extract every float separated by a ' ' or a ','
float element;
char spacer[10];
int32_t nbElementRead;
while( sscanf(&input[iii], "%1[, ]%f%n", spacer, &element, &nbElementRead) == 2
|| sscanf(&input[iii], "%f%n", &element, &nbElementRead) == 1) {
SVG_VERBOSE("Find element : " << element);
outputList.PushBack(element);
iii += nbElementRead;
}
outputPointer = &input[iii];
while(*outputPointer!= '\0' && *outputPointer == ' ') {
outputPointer++;
}
//outputPointer++;
return outputPointer;
}
bool svg::Path::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
ParseTransform(node);
ParsePaintAttr(node);
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
const char *elementXML = node->ToElement()->Attribute("d");
if (NULL == elementXML) {
SVG_ERROR("(l "<<node->Row()<<") path: missing 'p' attribute");
return false;
}
SVG_VERBOSE("Parse Path : \"" << elementXML << "\"");
char command;
etk::VectorType<float> listDot;
for( const char *sss=extractCmd(elementXML, command, listDot);
NULL != sss;
sss=extractCmd(sss, command, listDot) ) {
pathBasic_ts pathElement;
memset(&pathElement, 0, 1*sizeof(pathBasic_ts));
switch(command) {
case 'M': // Move To (absolute)
case 'L': // Line To (absolute)
case 'V': // Vertical Line To (absolute)
case 'H': // Horizantal Line To (absolute)
case 'Q': // Quadratic Bezier curve (absolute)
case 'T': // smooth quadratic Bezier curve to (absolute)
case 'C': // curve to (absolute)
case 'S': // smooth curve to (absolute)
case 'A': // elliptical Arc (absolute)
case 'Z': // closepath (absolute)
pathElement.relative = false;
break;
default : // else (relative)
pathElement.relative = true;
break;
}
switch(command) {
case 'M': // Move To (absolute)
case 'm': // Move To (relative)
// 2 Elements ...
if(listDot.Size()%2 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_MOVETO;
if (listDot.Size() >= 2) {
pathElement.element[0] = listDot[0];
pathElement.element[1] = listDot[1];
m_listElement.PushBack(pathElement);
}
pathElement.cmd = svg::PATH_ENUM_LINETO;
for(int32_t iii=2; iii<listDot.Size(); iii+=2) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
m_listElement.PushBack(pathElement);
}
break;
case 'L': // Line To (absolute)
case 'l': // Line To (relative)
// 2 Elements ...
if(listDot.Size()%2 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_LINETO;
for(int32_t iii=0; iii<listDot.Size(); iii+=2) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
m_listElement.PushBack(pathElement);
}
break;
case 'V': // Vertical Line To (absolute)
case 'v': // Vertical Line To (relative)
// 1 Element ...
if(listDot.Size() == 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_LINETO_V;
for(int32_t iii=0; iii<listDot.Size(); iii+=1) {
pathElement.element[0] = listDot[iii];
m_listElement.PushBack(pathElement);
}
break;
case 'H': // Horizantal Line To (absolute)
case 'h': // Horizantal Line To (relative)
// 1 Element ...
if(listDot.Size() == 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_LINETO_H;
for(int32_t iii=0; iii<listDot.Size(); iii+=1) {
pathElement.element[0] = listDot[iii];
m_listElement.PushBack(pathElement);
}
break;
case 'Q': // Quadratic Bezier curve (absolute)
case 'q': // Quadratic Bezier curve (relative)
// 4 Elements ...
if(listDot.Size()%4 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_BEZIER_CURVETO;
for(int32_t iii=0; iii<listDot.Size(); iii+=4) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
pathElement.element[2] = listDot[iii+2];
pathElement.element[3] = listDot[iii+3];
m_listElement.PushBack(pathElement);
}
break;
case 'T': // smooth quadratic Bezier curve to (absolute)
case 't': // smooth quadratic Bezier curve to (relative)
// 2 Elements ...
if(listDot.Size()%2 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_BEZIER_SMOTH_CURVETO;
for(int32_t iii=0; iii<listDot.Size(); iii+=2) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
m_listElement.PushBack(pathElement);
}
break;
case 'C': // curve to (absolute)
case 'c': // curve to (relative)
// 6 Elements ...
if(listDot.Size()%6 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_CURVETO;
for(int32_t iii=0; iii<listDot.Size(); iii+=6) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
pathElement.element[2] = listDot[iii+2];
pathElement.element[3] = listDot[iii+3];
pathElement.element[4] = listDot[iii+4];
pathElement.element[5] = listDot[iii+5];
m_listElement.PushBack(pathElement);
}
break;
case 'S': // smooth curve to (absolute)
case 's': // smooth curve to (relative)
// 4 Elements ...
if(listDot.Size()%4 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_SMOTH_CURVETO;
for(int32_t iii=0; iii<listDot.Size(); iii+=4) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
pathElement.element[2] = listDot[iii+2];
pathElement.element[3] = listDot[iii+3];
m_listElement.PushBack(pathElement);
}
break;
case 'A': // elliptical Arc (absolute)
case 'a': // elliptical Arc (relative)
// 7 Elements ...
if(listDot.Size()%7 != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_ELLIPTIC;
for(int32_t iii=0; iii<listDot.Size(); iii+=7) {
pathElement.element[0] = listDot[iii];
pathElement.element[1] = listDot[iii+1];
pathElement.element[2] = listDot[iii+2];
pathElement.element[3] = listDot[iii+3];
pathElement.element[4] = listDot[iii+4];
pathElement.element[5] = listDot[iii+5];
pathElement.element[6] = listDot[iii+6];
m_listElement.PushBack(pathElement);
}
break;
case 'Z': // closepath (absolute)
case 'z': // closepath (relative)
// 0 Element ...
if(listDot.Size() != 0) {
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.Size() );
break;
}
pathElement.cmd = svg::PATH_ENUM_STOP;
m_listElement.PushBack(pathElement);
break;
default:
SVG_ERROR ("Unknow error : \"" << command << "\"");
}
}
return true;
}
void svg::Path::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Path");
for(int32_t iii=0; iii<m_listElement.Size(); iii++) {
switch (m_listElement[iii].cmd) {
case PATH_ENUM_STOP:
SVG_DEBUG(SpacingDist(spacing+4) << "STOP");
break;
case PATH_ENUM_MOVETO:
SVG_DEBUG(SpacingDist(spacing+4) << "MOVETO (" << m_listElement[iii].element[0] << "," << m_listElement[iii].element[1] << ")" );
break;
case PATH_ENUM_LINETO:
SVG_DEBUG(SpacingDist(spacing+4) << "LINETO (" << m_listElement[iii].element[0] << "," << m_listElement[iii].element[1] << ")" );
break;
case PATH_ENUM_LINETO_H:
SVG_DEBUG(SpacingDist(spacing+4) << "LINETO_H (" << m_listElement[iii].element[0] << ")" );
break;
case PATH_ENUM_LINETO_V:
SVG_DEBUG(SpacingDist(spacing+4) << "LINETO_V (" << m_listElement[iii].element[0] << ")" );
break;
case PATH_ENUM_CURVETO:
SVG_DEBUG(SpacingDist(spacing+4) << "CURVETO (" << m_listElement[iii].element[0] <<
"," << m_listElement[iii].element[1] <<
"," << m_listElement[iii].element[2] <<
"," << m_listElement[iii].element[3] <<
"," << m_listElement[iii].element[4] <<
"," << m_listElement[iii].element[5] << ")" );
break;
case PATH_ENUM_SMOTH_CURVETO:
SVG_DEBUG(SpacingDist(spacing+4) << "SMOTH_CURVETO (" << m_listElement[iii].element[0] <<
"," << m_listElement[iii].element[1] <<
"," << m_listElement[iii].element[2] <<
"," << m_listElement[iii].element[3] << ")" );
break;
case PATH_ENUM_BEZIER_CURVETO:
SVG_DEBUG(SpacingDist(spacing+4) << "BEZIER_CURVETO (" << m_listElement[iii].element[0] <<
"," << m_listElement[iii].element[1] <<
"," << m_listElement[iii].element[2] <<
"," << m_listElement[iii].element[3] << ")" );
break;
case PATH_ENUM_BEZIER_SMOTH_CURVETO:
SVG_DEBUG(SpacingDist(spacing+4) << "BEZIER_SMOTH_CURVETO (" << m_listElement[iii].element[0] << "," << m_listElement[iii].element[1] << ")" );
break;
case PATH_ENUM_ELLIPTIC:
SVG_DEBUG(SpacingDist(spacing+4) << "ELLIPTIC (TODO...)" );
// show explanation at : http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
break;
default:
SVG_DEBUG(SpacingDist(spacing+4) << "????" );
break;
}
}
}
void svg::Path::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.red, m_paint.fill.green, m_paint.fill.blue, m_paint.fill.alpha));
agg::path_storage path;
path.start_new_path();
for(int32_t iii=0; iii<m_listElement.Size(); iii++) {
switch (m_listElement[iii].cmd) {
case PATH_ENUM_STOP:
AbstractCloseSubpath(path);
break;
case PATH_ENUM_MOVETO:
AbstractMoveTo(path, m_listElement[iii].relative,
m_listElement[iii].element[0],
m_listElement[iii].element[1] );
break;
case PATH_ENUM_LINETO:
AbstractLineTo(path, m_listElement[iii].relative,
m_listElement[iii].element[0],
m_listElement[iii].element[1] );
break;
case PATH_ENUM_LINETO_H:
AbstractHLineTo(path, m_listElement[iii].relative,
m_listElement[iii].element[0] );
break;
case PATH_ENUM_LINETO_V:
AbstractVLineTo(path, m_listElement[iii].relative,
m_listElement[iii].element[0] );
break;
case PATH_ENUM_CURVETO:
AbstractCurve4(path, m_listElement[iii].relative,
m_listElement[iii].element[0],
m_listElement[iii].element[1],
m_listElement[iii].element[2],
m_listElement[iii].element[3],
m_listElement[iii].element[4],
m_listElement[iii].element[5] );
//SVG_INFO(" draw : PATH_ENUM_CURVETO");
break;
case PATH_ENUM_SMOTH_CURVETO:
AbstractCurve4(path, m_listElement[iii].relative,
m_listElement[iii].element[0],
m_listElement[iii].element[1],
m_listElement[iii].element[2],
m_listElement[iii].element[3] );
//SVG_INFO(" draw : PATH_ENUM_SMOTH_CURVETO");
break;
case PATH_ENUM_BEZIER_CURVETO:
AbstractCurve3(path, m_listElement[iii].relative,
m_listElement[iii].element[0],
m_listElement[iii].element[1],
m_listElement[iii].element[2],
m_listElement[iii].element[3] );
//SVG_INFO(" draw : PATH_ENUM_BEZIER_CURVETO");
break;
case PATH_ENUM_BEZIER_SMOTH_CURVETO:
AbstractCurve3(path, m_listElement[iii].relative,
m_listElement[iii].element[0],
m_listElement[iii].element[1] );
//SVG_INFO(" draw : PATH_ENUM_BEZIER_SMOTH_CURVETO");
break;
case PATH_ENUM_ELLIPTIC:
SVG_TODO("Elliptic arc is not implemented NOW ...");
break;
default:
SVG_ERROR("Unknow PATH commant (internal error)");
break;
}
}
agg::trans_affine mtx = m_transformMatrix;
mtx *= basicTrans;
agg::conv_curve<agg::path_storage> curve(path);
if (m_paint.fill.alpha != 0x00) {
agg::conv_transform<agg::conv_curve<agg::path_storage>, agg::trans_affine> trans(curve, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule((m_paint.flagEvenOdd)?agg::fill_even_odd:agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(trans);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
if (m_paint.strokeWidth > 0 && m_paint.stroke.alpha!=0x00 ) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::conv_curve<agg::path_storage> > myPolygonStroke(curve);
myPolygonStroke.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::conv_curve<agg::path_storage> >, agg::trans_affine> transStroke(myPolygonStroke, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}
void svg::Path::AbstractMoveTo(agg::path_storage& path, bool rel, double x, double y)
{
if(true == rel) {
path.rel_to_abs(&x, &y);
}
path.move_to(x, y);
}
void svg::Path::AbstractLineTo(agg::path_storage& path, bool rel, double x, double y)
{
if(true == rel) {
path.rel_to_abs(&x, &y);
}
path.line_to(x, y);
}
void svg::Path::AbstractHLineTo(agg::path_storage& path, bool rel, double x)
{
double x2 = 0.0;
double y2 = 0.0;
if(0!=path.total_vertices()) {
path.vertex(path.total_vertices() - 1, &x2, &y2);
if(true == rel) {
x += x2;
}
path.line_to(x, y2);
}
}
void svg::Path::AbstractVLineTo(agg::path_storage& path, bool rel, double y)
{
double x2 = 0.0;
double y2 = 0.0;
if(path.total_vertices()) {
path.vertex(path.total_vertices() - 1, &x2, &y2);
if(true == rel) {
y += y2;
}
path.line_to(x2, y);
}
}
void svg::Path::AbstractCurve3(agg::path_storage& path, bool rel, double x1, double y1, double x, double y)
{
if(true == rel) {
path.rel_to_abs(&x1, &y1);
path.rel_to_abs(&x, &y);
}
path.curve3(x1, y1, x, y);
}
void svg::Path::AbstractCurve3(agg::path_storage& path, bool rel, double x, double y)
{
if(true == rel) {
path.curve3_rel(x, y);
} else {
path.curve3(x, y);
}
}
void svg::Path::AbstractCurve4(agg::path_storage& path, bool rel, double x1, double y1, double x2, double y2, double x, double y)
{
if(true == rel) {
path.rel_to_abs(&x1, &y1);
path.rel_to_abs(&x2, &y2);
path.rel_to_abs(&x, &y);
}
path.curve4(x1, y1, x2, y2, x, y);
}
void svg::Path::AbstractCurve4(agg::path_storage& path, bool rel, double x2, double y2, double x, double y)
{
if(true == rel) {
path.curve4_rel(x2, y2, x, y);
} else {
path.curve4(x2, y2, x, y);
}
}
void svg::Path::AbstractCloseSubpath(agg::path_storage& path)
{
path.end_poly(agg::path_flags_close);
}

76
parserSVG/Path.h Normal file
View File

@ -0,0 +1,76 @@
/**
*******************************************************************************
* @file parserSVG/Path.h
* @brief basic path parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_PATH_H__
#define __SVG_PATH_H__
#include <parserSVG/Base.h>
#include <agg-2.4/agg_path_storage.h>
namespace svg
{
typedef enum {
PATH_ENUM_STOP,
PATH_ENUM_MOVETO,
PATH_ENUM_LINETO,
PATH_ENUM_LINETO_H,
PATH_ENUM_LINETO_V,
PATH_ENUM_CURVETO,
PATH_ENUM_SMOTH_CURVETO,
PATH_ENUM_BEZIER_CURVETO,
PATH_ENUM_BEZIER_SMOTH_CURVETO,
PATH_ENUM_ELLIPTIC,
} pathEnum_te;
typedef struct {
pathEnum_te cmd;
bool relative;
float element[7];
}pathBasic_ts;
class Path : public svg::Base
{
private:
etk::VectorType<pathBasic_ts> m_listElement;
public:
Path(PaintState parentPaintState);
~Path(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
private:
void AbstractMoveTo(agg::path_storage& path, bool rel, double x, double y);
void AbstractLineTo(agg::path_storage& path, bool rel, double x, double y);
void AbstractHLineTo(agg::path_storage& path, bool rel, double x);
void AbstractVLineTo(agg::path_storage& path, bool rel, double y);
void AbstractCurve3(agg::path_storage& path, bool rel, double x1, double y1, double x, double y);
void AbstractCurve3(agg::path_storage& path, bool rel, double x, double y);
void AbstractCurve4(agg::path_storage& path, bool rel, double x1, double y1, double x2, double y2, double x, double y);
void AbstractCurve4(agg::path_storage& path, bool rel, double x2, double y2, double x, double y);
void AbstractCloseSubpath(agg::path_storage& path);
};
};
#endif

144
parserSVG/Polygon.cpp Normal file
View File

@ -0,0 +1,144 @@
/**
*******************************************************************************
* @file parserSVG/Polygon.cpp
* @brief basic poligon parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Polygon.h>
#include <agg-2.4/agg_conv_stroke.h>
#include <agg-2.4/agg_path_storage.h>
svg::Polygon::Polygon(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Polygon::~Polygon(void)
{
}
bool svg::Polygon::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
ParseTransform(node);
ParsePaintAttr(node);
SVG_VERBOSE("parsed P1. trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
SVG_VERBOSE("parsed P2. trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
const char *sss = node->ToElement()->Attribute("points");
if (NULL == sss) {
SVG_ERROR("(l "<<node->Row()<<") polygon: missing points attribute");
return false;
}
sizeMax.x = 0;
sizeMax.y = 0;
SVG_VERBOSE("Parse polygon : \"" << sss << "\"");
while ('\0' != sss[0]) {
Vector2D<float> pos;
int32_t n;
if (sscanf(sss, "%f,%f%n", &pos.x, &pos.y, &n) == 2) {
m_listPoint.PushBack(pos);
sss += n;
sizeMax.x = etk_max(sizeMax.x, pos.x);
sizeMax.y = etk_max(sizeMax.y, pos.y);
if(sss[0] == ' ' || sss[0] == ',') {
sss++;
}
} else {
break;
}
}
return true;
}
void svg::Polygon::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Polygon nbPoint=" << m_listPoint.Size());
}
void svg::Polygon::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.red, m_paint.fill.green, m_paint.fill.blue, m_paint.fill.alpha));
agg::path_storage path;
path.start_new_path();
path.move_to(m_listPoint[0].x, m_listPoint[0].y);
for( int32_t iii=1; iii< m_listPoint.Size(); iii++) {
path.line_to(m_listPoint[iii].x, m_listPoint[iii].y);
}
path.close_polygon();
/*
// configure the end of the line :
switch (m_paint.lineCap) {
case svg::LINECAP_SQUARE:
path.line_cap(agg::square_cap);
break;
case svg::LINECAP_ROUND:
path.line_cap(agg::round_cap);
break;
default: // svg::LINECAP_BUTT
path.line_cap(agg::butt_cap);
break;
}
switch (m_paint.lineJoin) {
case svg::LINEJOIN_BEVEL:
path.line_join(agg::bevel_join);
break;
case svg::LINEJOIN_ROUND:
path.line_join(agg::round_join);
break;
default: // svg::LINEJOIN_MITER
path.line_join(agg::miter_join);
break;
}
*/
agg::trans_affine mtx = m_transformMatrix;
mtx *= basicTrans;
if (m_paint.fill.alpha != 0x00) {
agg::conv_transform<agg::path_storage, agg::trans_affine> trans(path, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule((m_paint.flagEvenOdd)?agg::fill_even_odd:agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(trans);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
if (m_paint.strokeWidth > 0 && m_paint.stroke.alpha!=0x00 ) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::path_storage> myPolygonStroke(path);
myPolygonStroke.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::path_storage>, agg::trans_affine> transStroke(myPolygonStroke, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}

52
parserSVG/Polygon.h Normal file
View File

@ -0,0 +1,52 @@
/**
*******************************************************************************
* @file parserSVG/Polygon.h
* @brief basic poligon parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_POLYGON_H__
#define __SVG_POLYGON_H__
#include <parserSVG/Base.h>
#include <etk/VectorType.h>
namespace svg
{
typedef enum {
POLYGONE_MODE__NON_ZERO,
POLYGONE_MODE__EVEN_ODD,
} PolygonMode_te;
class Polygon : public svg::Base
{
private:
etk::VectorType<Vector2D<float> > m_listPoint; //!< list of all point of the polygone
PolygonMode_te m_diplayMode; //!< polygone specific display mode
public:
Polygon(PaintState parentPaintState);
~Polygon(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

129
parserSVG/Polyline.cpp Normal file
View File

@ -0,0 +1,129 @@
/**
*******************************************************************************
* @file parserSVG/Polyline.cpp
* @brief basic Poliline parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Polyline.h>
#include <agg-2.4/agg_conv_stroke.h>
#include <agg-2.4/agg_path_storage.h>
svg::Polyline::Polyline(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Polyline::~Polyline(void)
{
}
bool svg::Polyline::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
// line must have a minimum size...
m_paint.strokeWidth = 1;
ParseTransform(node);
ParsePaintAttr(node);
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
const char *sss = node->ToElement()->Attribute("points");
if (NULL == sss) {
SVG_ERROR("(l "<<node->Row()<<") polyline: missing points attribute");
return false;
}
sizeMax.x = 0;
sizeMax.y = 0;
SVG_VERBOSE("Parse polyline : \"" << sss << "\"");
while ('\0' != sss[0]) {
Vector2D<float> pos;
int32_t n;
if (sscanf(sss, "%f,%f %n", &pos.x, &pos.y, &n) == 2) {
m_listPoint.PushBack(pos);
sizeMax.x = etk_max(sizeMax.x, pos.x);
sizeMax.y = etk_max(sizeMax.y, pos.y);
sss += n;
} else {
break;
}
}
return true;
}
void svg::Polyline::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Polyline nbPoint=" << m_listPoint.Size());
}
void svg::Polyline::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
agg::path_storage path;
path.start_new_path();
path.move_to(m_listPoint[0].x, m_listPoint[0].y);
for( int32_t iii=1; iii< m_listPoint.Size(); iii++) {
path.line_to(m_listPoint[iii].x, m_listPoint[iii].y);
}
/*
// configure the end of the line :
switch (m_paint.lineCap) {
case svg::LINECAP_SQUARE:
path.line_cap(agg::square_cap);
break;
case svg::LINECAP_ROUND:
path.line_cap(agg::round_cap);
break;
default: // svg::LINECAP_BUTT
path.line_cap(agg::butt_cap);
break;
}
switch (m_paint.lineJoin) {
case svg::LINEJOIN_BEVEL:
path.line_join(agg::bevel_join);
break;
case svg::LINEJOIN_ROUND:
path.line_join(agg::round_join);
break;
default: // svg::LINEJOIN_MITER
path.line_join(agg::miter_join);
break;
}
*/
agg::trans_affine mtx = m_transformMatrix;
mtx *= basicTrans;
if (m_paint.strokeWidth > 0) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::path_storage> myPolygonStroke(path);
myPolygonStroke.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::path_storage>, agg::trans_affine> transStroke(myPolygonStroke, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}

47
parserSVG/Polyline.h Normal file
View File

@ -0,0 +1,47 @@
/**
*******************************************************************************
* @file parserSVG/Polyline.h
* @brief basic Poliline parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_POLYLINE_H__
#define __SVG_POLYLINE_H__
#include <parserSVG/Base.h>
#include <etk/VectorType.h>
namespace svg
{
class Polyline : public svg::Base
{
private:
etk::VectorType<Vector2D<float> > m_listPoint; //!< list of all point of the polyline
public:
Polyline(PaintState parentPaintState);
~Polyline(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

113
parserSVG/Rectangle.cpp Normal file
View File

@ -0,0 +1,113 @@
/**
*******************************************************************************
* @file parserSVG/Rectangle.cpp
* @brief basic rectangle parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Rectangle.h>
#include <agg-2.4/agg_rounded_rect.h>
#include <agg-2.4/agg_conv_stroke.h>
svg::Rectangle::Rectangle(PaintState parentPaintState) : svg::Base(parentPaintState)
{
m_position.x = 0.0;
m_position.y = 0.0;
m_size.x = 0.0;
m_size.y = 0.0;
m_roundedCorner.x = 0.0;
m_roundedCorner.y = 0.0;
}
svg::Rectangle::~Rectangle(void)
{
}
bool svg::Rectangle::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
m_position.x = 0.0;
m_position.y = 0.0;
m_size.x = 0.0;
m_size.y = 0.0;
m_roundedCorner.x = 0.0;
m_roundedCorner.y = 0.0;
ParseTransform(node);
ParsePaintAttr(node);
// add the property of the parrent modifications ...
m_transformMatrix *= parentTrans;
ParsePosition(node, m_position, m_size);
const char * content = node->ToElement()->Attribute("rx");
if (NULL != content) {
m_roundedCorner.x = ParseLength(content);
}
content = node->ToElement()->Attribute("ry");
if (NULL != content) {
m_roundedCorner.y = ParseLength(content);
}
sizeMax.x = m_position.x + m_size.x + m_paint.strokeWidth;
sizeMax.y = m_position.y + m_size.y + m_paint.strokeWidth;
return true;
}
void svg::Rectangle::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Rectangle : pos=" << m_position << " size=" << m_size << " corner=" << m_roundedCorner);
}
void svg::Rectangle::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.red, m_paint.fill.green, m_paint.fill.blue, m_paint.fill.alpha));
// Creating a rounded rectangle
agg::rounded_rect rect_r(m_position.x, m_position.y, m_position.x+m_size.x, m_position.y+m_size.y, m_roundedCorner.x);
rect_r.radius(m_roundedCorner.x, m_roundedCorner.y);
rect_r.normalize_radius();
agg::trans_affine mtx = m_transformMatrix;
// herited modifications ...
mtx *= basicTrans;
if (m_paint.fill.alpha != 0x00) {
agg::conv_transform<agg::rounded_rect, agg::trans_affine> trans(rect_r, mtx);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule((m_paint.flagEvenOdd)?agg::fill_even_odd:agg::fill_non_zero);
myRenderer.m_rasterizer.add_path(trans);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
if (m_paint.strokeWidth > 0 && m_paint.stroke.alpha!=0x00 ) {
myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.red, m_paint.stroke.green, m_paint.stroke.blue, m_paint.stroke.alpha));
// Drawing as an outline
agg::conv_stroke<agg::rounded_rect> rect_p(rect_r);
// set the filling mode :
myRenderer.m_rasterizer.filling_rule(agg::fill_non_zero);
rect_p.width(m_paint.strokeWidth);
agg::conv_transform<agg::conv_stroke<agg::rounded_rect>, agg::trans_affine> transStroke(rect_p, mtx);
myRenderer.m_rasterizer.add_path(transStroke);
agg::render_scanlines(myRenderer.m_rasterizer, myRenderer.m_scanLine, *myRenderer.m_renderArea);
}
}

48
parserSVG/Rectangle.h Normal file
View File

@ -0,0 +1,48 @@
/**
*******************************************************************************
* @file parserSVG/Rectangle.h
* @brief basic rectangle parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_RECTANGLE_H__
#define __SVG_RECTANGLE_H__
#include <parserSVG/Base.h>
namespace svg
{
class Rectangle : public svg::Base
{
private:
Vector2D<float> m_position; //!< position of the rectangle
Vector2D<float> m_size; //!< size of the rectangle
Vector2D<float> m_roundedCorner; //!< property of the rounded corner
public:
Rectangle(PaintState parentPaintState);
~Rectangle(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
};
};
#endif

110
parserSVG/Renderer.cpp Normal file
View File

@ -0,0 +1,110 @@
/**
*******************************************************************************
* @file parserSVG/Renderer.cpp
* @brief Basic SVG renderer for the AGG librairy (Sources)
* @author Edouard DUPIN
* @date 23/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Renderer.h>
// 4 is for the RGBA ...
#define DATA_ALLOCATION_ELEMENT (4)
svg::Renderer::Renderer(uint32_t width, uint32_t height)
{
m_allocatedSize = 0;
m_size.x = width;
m_size.y = height;
int32_t dataSize = ((int32_t)width * (int32_t)height * DATA_ALLOCATION_ELEMENT);
m_allocatedSize = dataSize;
// allocate Data
SVG_DEBUG("Allocate buffer : " << dataSize);
ETK_MALLOC(m_buffer, dataSize, uint8_t);
if (NULL == m_buffer) {
SVG_ERROR("Allocation of the output buffer for SVG drawing error");
m_allocatedSize = 0;
return;
}
memset(m_buffer, 0x00, dataSize * sizeof(uint8_t) );
m_renderingBuffer = new agg::rendering_buffer(m_buffer, m_size.x, m_size.y, m_size.x * DATA_ALLOCATION_ELEMENT);
if (NULL == m_renderingBuffer) {
SVG_ERROR("Allocation of the m_renderingBuffer for SVG drawing error");
return;
}
m_pixFrame = new agg::pixfmt_rgba32(*m_renderingBuffer);
if (NULL == m_pixFrame) {
SVG_ERROR("Allocation of the m_pixFrame for SVG drawing error");
return;
}
m_renderBase = new rendererBase_t(*m_pixFrame);
if (NULL == m_renderBase) {
SVG_ERROR("Allocation of the m_renderBase for SVG drawing error");
return;
}
m_renderArea = new rendererSolid_t(*m_renderBase);
if (NULL == m_renderArea) {
SVG_ERROR("Allocation of the m_renderArea for SVG drawing error");
return;
}
//m_basicMatrix *= agg::trans_affine_translation(-g_base_dx2, -g_base_dy2);
//m_basicMatrix *= agg::trans_affine_scaling(g_scale*coefmult, g_scale*coefmult);
//m_basicMatrix *= agg::trans_affine_rotation(g_angle);// + agg::pi);
//m_basicMatrix *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0);
//m_basicMatrix *= agg::trans_affine_translation(m_size.x*0.7, m_size.y/2);
}
svg::Renderer::~Renderer(void)
{
if (NULL != m_buffer) {
ETK_FREE(m_buffer);
m_buffer = NULL;
}
}
// Writing the buffer to a .PPM file, assuming it has
// RGB-structure, one byte per color component
//--------------------------------------------------
void svg::Renderer::WritePpm(etk::UString fileName)
{
if (NULL == m_buffer) {
return;
}
FILE* fd = fopen(fileName.Utf8Data(), "wb");
if(NULL != fd) {
int32_t sizeX = m_size.x;
int32_t sizeY = m_size.y;
SVG_DEBUG("Generate ppm : " << m_size);
fprintf(fd, "P6 %d %d 255 ", sizeX, sizeY);
for (int32_t iii=0 ; iii<sizeX*sizeY; iii++) {
fwrite(m_buffer+iii*DATA_ALLOCATION_ELEMENT, 1, 3, fd);
}
fclose(fd);
}
}

89
parserSVG/Renderer.h Normal file
View File

@ -0,0 +1,89 @@
/**
*******************************************************************************
* @file parserSVG/Renderer.h
* @brief Basic SVG renderer for the AGG librairy (Header)
* @author Edouard DUPIN
* @date 23/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_RENDERER_H__
#define __SVG_RENDERER_H__
#include <etk/UString.h>
#include <agg-2.4/agg_basics.h>
#include <agg-2.4/agg_rendering_buffer.h>
#include <agg-2.4/agg_rasterizer_scanline_aa.h>
#include <agg-2.4/agg_scanline_p.h>
#include <agg-2.4/agg_renderer_scanline.h>
#include <agg-2.4/agg_path_storage.h>
#include <agg-2.4/agg_conv_transform.h>
#include <agg-2.4/agg_bounding_rect.h>
#include <agg-2.4/agg_color_rgba.h>
#include <agg-2.4/agg_pixfmt_rgba.h>
namespace svg
{
typedef enum {
LINECAP_BUTT,
LINECAP_ROUND,
LINECAP_SQUARE,
} lineCap_te;
typedef enum {
LINEJOIN_MITER,
LINEJOIN_ROUND,
LINEJOIN_BEVEL,
} lineJoin_te;
class PaintState {
public:
color_ts fill;
color_ts stroke;
float strokeWidth;
bool flagEvenOdd;
lineCap_te lineCap;
lineJoin_te lineJoin;
Vector2D<float> viewPort;
};
// basic definition type for the renderer
typedef agg::renderer_base<agg::pixfmt_rgba32> rendererBase_t;
typedef agg::renderer_scanline_aa_solid<rendererBase_t> rendererSolid_t;
class Renderer {
private:
uint8_t * m_buffer;
uint32_t m_allocatedSize;
public:
Renderer(uint32_t width, uint32_t height);
~Renderer(void);
void WritePpm(etk::UString fileName);
Vector2D<float> m_size;
agg::rendering_buffer * m_renderingBuffer;
agg::pixfmt_rgba32 * m_pixFrame;
rendererBase_t * m_renderBase;
rendererSolid_t * m_renderArea;
agg::rasterizer_scanline_aa<> m_rasterizer; //!< AGG renderer system
agg::scanline_p8 m_scanLine; //!<
uint8_t* GetDataPointer(void) { return m_buffer; };
uint32_t GetDataSize(void) { return m_allocatedSize; };
};
};
#endif

25
parserSVG/Stroking.cpp Normal file
View File

@ -0,0 +1,25 @@
/**
*******************************************************************************
* @file parserSVG/Stroking.cpp
* @brief basic stroking parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/

36
parserSVG/Stroking.h Normal file
View File

@ -0,0 +1,36 @@
/**
*******************************************************************************
* @file parserSVG/Stroking.h
* @brief basic stroking parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_STROKING_H__
#define __SVG_STROKING_H__
#include <parserSVG/Base.h>
namespace svg
{
};
#endif

51
parserSVG/Text.cpp Normal file
View File

@ -0,0 +1,51 @@
/**
*******************************************************************************
* @file parserSVG/Text.cpp
* @brief Basic Text parsing (Sources)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/Text.h>
svg::Text::Text(PaintState parentPaintState) : svg::Base(parentPaintState)
{
}
svg::Text::~Text(void)
{
}
bool svg::Text::Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax)
{
sizeMax.x = 0;
sizeMax.y = 0;
SVG_ERROR("NOT IMPLEMENTED");
return false;
}
void svg::Text::Display(int32_t spacing)
{
SVG_DEBUG(SpacingDist(spacing) << "Text");
}

45
parserSVG/Text.h Normal file
View File

@ -0,0 +1,45 @@
/**
*******************************************************************************
* @file parserSVG/Text.h
* @brief Basic Text parsing (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_TEXT_H__
#define __SVG_TEXT_H__
#include <parserSVG/Base.h>
namespace svg
{
class Text : public svg::Base
{
private:
public:
Text(PaintState parentPaintState);
~Text(void);
virtual bool Parse(TiXmlNode * node, agg::trans_affine& parentTrans, Vector2D<float>& sizeMax);
virtual void Display(int32_t spacing);
};
};
#endif

322
parserSVG/parserSVG.cpp Normal file
View File

@ -0,0 +1,322 @@
/**
*******************************************************************************
* @file parserSVG/parserSVG.cpp
* @brief parserSVG : basic header of the SVG parser (Sources)
* @author Edouard DUPIN
* @date 18/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <parserSVG/Debug.h>
#include <parserSVG/parserSVG.h>
#include <tinyXML/tinyxml.h>
#include <parserSVG/Base.h>
#include <parserSVG/Circle.h>
#include <parserSVG/Ellipse.h>
#include <parserSVG/Line.h>
#include <parserSVG/Path.h>
#include <parserSVG/Polygon.h>
#include <parserSVG/Polyline.h>
#include <parserSVG/Rectangle.h>
#include <parserSVG/Text.h>
#include <parserSVG/Group.h>
#include <agg-2.4/agg_basics.h>
#include <agg-2.4/agg_rendering_buffer.h>
#include <agg-2.4/agg_rasterizer_scanline_aa.h>
#include <agg-2.4/agg_scanline_p.h>
#include <agg-2.4/agg_renderer_scanline.h>
#include <agg-2.4/agg_path_storage.h>
#include <agg-2.4/agg_conv_transform.h>
#include <agg-2.4/agg_bounding_rect.h>
#include <agg-2.4/agg_color_rgba.h>
#include <agg-2.4/agg_pixfmt_rgba.h>
svg::Parser::Parser(etk::File fileName) : m_renderedElement(NULL)
{
m_fileName = fileName;
m_version = "0.0";
m_loadOK = true;
m_paint.fill.red = 0xFF;
m_paint.fill.green = 0;
m_paint.fill.blue = 0;
m_paint.fill.alpha = 0xFF;
m_paint.stroke.red = 0xFF;
m_paint.stroke.green = 0xFF;
m_paint.stroke.blue = 0xFF;
m_paint.stroke.alpha = 0;
m_paint.strokeWidth = 1.0;
m_paint.viewPort.x = 255;
m_paint.viewPort.y = 255;
m_paint.flagEvenOdd = false;
m_paint.lineJoin = svg::LINEJOIN_MITER;
m_paint.lineCap = svg::LINECAP_BUTT;
m_size.x = 0.0;
m_size.y = 0.0;
// Start loading the XML :
SVG_DEBUG("open file (SVG) \"" << m_fileName << "\"");
// allocate the document in the stack
TiXmlDocument XmlDocument;
if (false == m_fileName.Exist()) {
SVG_ERROR("File Does not exist : " << m_fileName);
m_loadOK = false;
return;
}
int32_t fileSize = m_fileName.Size();
if (0==fileSize) {
SVG_ERROR("This file is empty : " << m_fileName);
m_loadOK = false;
return;
}
if (false == m_fileName.fOpenRead()) {
SVG_ERROR("Can not open the file : " << m_fileName);
m_loadOK = false;
return;
}
// allocate data
char * fileBuffer = new char[fileSize+5];
if (NULL == fileBuffer) {
SVG_ERROR("Error Memory allocation size=" << fileSize);
m_loadOK = false;
return;
}
memset(fileBuffer, 0, (fileSize+5)*sizeof(char));
// load data from the file :
m_fileName.fRead(fileBuffer, 1, fileSize);
// close the file:
m_fileName.fClose();
// load the XML from the memory
XmlDocument.Parse((const char*)fileBuffer, 0, TIXML_ENCODING_UTF8);
TiXmlElement* root = XmlDocument.FirstChildElement( "svg" );
if (NULL == root ) {
SVG_ERROR("(l ?) main node not find: \"svg\" in \"" << m_fileName << "\"");
m_loadOK = false;
} else {
// get the svg version :
const char *version = root->ToElement()->Attribute("version");
if (NULL != version) {
m_version = version;
}
// parse ...
Vector2D<float> pos;
ParseTransform(root);
ParsePosition(root, pos, m_size);
ParsePaintAttr(root);
SVG_VERBOSE("parsed .ROOT trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
Vector2D<float> maxSize;
maxSize.x = 0.0;
maxSize.y = 0.0;
Vector2D<float> size;
// parse all sub node :
for(TiXmlNode * child = root->FirstChild(); NULL != child; child = child->NextSibling() ) {
svg::Base *elementParser = NULL;
if (child->Type()==TiXmlNode::TINYXML_COMMENT) {
// nothing to do, just proceed to next step
} else {
etk::UString localValue = child->Value();
bool normalNoElement = false;
if (localValue == "g") {
elementParser = new svg::Group(m_paint);
} else if (localValue == "a") {
SVG_INFO("Note : 'a' balise is parsed like a g balise ...");
elementParser = new svg::Group(m_paint);
} else if (localValue == "title") {
m_title = "TODO : set the title here ...";
normalNoElement = true;
} else if (localValue == "path") {
elementParser = new svg::Path(m_paint);
} else if (localValue == "rect") {
elementParser = new svg::Rectangle(m_paint);
} else if (localValue == "circle") {
elementParser = new svg::Circle(m_paint);
} else if (localValue == "ellipse") {
elementParser = new svg::Ellipse(m_paint);
} else if (localValue == "line") {
elementParser = new svg::Line(m_paint);
} else if (localValue == "polyline") {
elementParser = new svg::Polyline(m_paint);
} else if (localValue == "polygon") {
elementParser = new svg::Polygon(m_paint);
} else if (localValue == "text") {
elementParser = new svg::Text(m_paint);
} else if (localValue == "metadata") {
// nothing to do : generaly inkscape data
normalNoElement = true;
} else {
SVG_ERROR("(l "<<child->Row()<<") node not suported : \""<<localValue<<"\" must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
}
if (false == normalNoElement) {
if (NULL == elementParser) {
SVG_ERROR("(l "<<child->Row()<<") error on node: \""<<localValue<<"\" allocation error or not supported ...");
} else {
if (false == elementParser->Parse(child, m_transformMatrix, size)) {
SVG_ERROR("(l "<<child->Row()<<") error on node: \""<<localValue<<"\" Sub Parsing ERROR");
delete(elementParser);
elementParser = NULL;
} else {
if (maxSize.x<size.x) {
maxSize.x=size.x;
}
if (maxSize.y<size.y) {
maxSize.y=size.y;
}
// add element in the system
m_subElementList.PushBack(elementParser);
}
}
}
}
}
if (m_size.x==0 || m_size.y==0) {
m_size.x=(int32_t)maxSize.x;
m_size.y=(int32_t)maxSize.y;
} else {
m_size.x=(int32_t)m_size.x;
m_size.y=(int32_t)m_size.y;
}
}
if (NULL != fileBuffer) {
delete[] fileBuffer;
}
//DisplayDebug();
}
svg::Parser::~Parser(void)
{
if(NULL != m_renderedElement) {
delete(m_renderedElement);
m_renderedElement = NULL;
}
}
void svg::Parser::DisplayDebug(void)
{
SVG_DEBUG("Main SVG node : size=" << m_size);
for (int32_t iii=0; iii<m_subElementList.Size(); iii++) {
if (NULL != m_subElementList[iii]) {
m_subElementList[iii]->Display(1);
}
}
}
void svg::Parser::AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans)
{
for (int32_t iii=0; iii<m_subElementList.Size(); iii++) {
if (NULL != m_subElementList[iii]) {
m_subElementList[iii]->AggDraw(myRenderer, basicTrans);
}
}
}
void svg::Parser::GenerateTestFile(void)
{
int32_t SizeX = m_size.x;
if (SizeX == 0) {
SizeX = 50;
}
int32_t SizeY = m_size.y;
if (SizeY == 0) {
SizeY = 50;
}
if(NULL != m_renderedElement) {
delete(m_renderedElement);
m_renderedElement = NULL;
}
m_renderedElement = new svg::Renderer(SizeX, SizeY);
// create the first element matrix modification ...
agg::trans_affine basicTrans;
//basicTrans *= agg::trans_affine_translation(-g_base_dx, -g_base_dy);
//basicTrans *= agg::trans_affine_scaling(2, 2);
//basicTrans *= agg::trans_affine_rotation(g_angle);// + agg::pi);
//basicTrans *= agg::trans_affine_skewing(2.0, 5.0);
//basicTrans *= agg::trans_affine_translation(width*0.3, height/2);
//basicTrans *= agg::trans_affine_translation(width/3, height/3);
AggDraw(*m_renderedElement, basicTrans);
etk::UString tmpFileOut = "yyy_out_";
tmpFileOut += m_fileName.GetShortFilename();
tmpFileOut += ".ppm";
m_renderedElement->WritePpm(tmpFileOut);
}
void svg::Parser::GenerateAnImage(int32_t sizeX, int32_t sizeY)
{
int32_t SizeX = sizeX;
if (SizeX == 0) {
SizeX = 50;
}
int32_t SizeY = sizeY;
if (SizeY == 0) {
SizeY = 50;
}
if(NULL != m_renderedElement) {
delete(m_renderedElement);
m_renderedElement = NULL;
}
m_renderedElement = new svg::Renderer(SizeX, SizeY);
// create the first element matrix modification ...
agg::trans_affine basicTrans;
//basicTrans *= agg::trans_affine_translation(-g_base_dx, -g_base_dy);
basicTrans *= agg::trans_affine_scaling(SizeX/m_size.x, SizeY/m_size.y);
//basicTrans *= agg::trans_affine_rotation(g_angle);// + agg::pi);
//basicTrans *= agg::trans_affine_skewing(2.0, 5.0);
//basicTrans *= agg::trans_affine_translation(width*0.3, height/2);
//basicTrans *= agg::trans_affine_translation(width/3, height/3);
AggDraw(*m_renderedElement, basicTrans);
/*
etk::UString tmpFileOut = "zzz_out_test.ppm";
m_renderedElement->WritePpm(tmpFileOut);
*/
}
uint8_t* svg::Parser::GetPointerOnData(void)
{
if(NULL == m_renderedElement) {
return NULL;
}
return m_renderedElement->GetDataPointer();
}
uint32_t svg::Parser::GetSizeOnData(void)
{
if(NULL == m_renderedElement) {
return 0;
}
return m_renderedElement->GetDataSize();
}

60
parserSVG/parserSVG.h Normal file
View File

@ -0,0 +1,60 @@
/**
*******************************************************************************
* @file parserSVG/parserSVG.h
* @brief parserSVG : basic header of the SVG parser (Header)
* @author Edouard DUPIN
* @date 20/03/2012
* @par Project
* parserSVG
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __SVG_PARSER_H__
#define __SVG_PARSER_H__
#include <etk/File.h>
#include <etk/VectorType.h>
#include <parserSVG/Base.h>
namespace svg
{
class Parser : public svg::Base
{
private:
etk::File m_fileName;
bool m_loadOK;
etk::UString m_version;
etk::UString m_title;
etk::VectorType<svg::Base *> m_subElementList;
Vector2D<float> m_size;
svg::Renderer* m_renderedElement;
public:
Parser(etk::File fileName);
~Parser(void);
bool IsLoadOk(void) { return m_loadOK; };
void DisplayDebug(void);
void GenerateTestFile(void);
void GenerateAnImage(int32_t sizeX, int32_t sizeY);
virtual void AggDraw(svg::Renderer& myRenderer, agg::trans_affine& basicTrans);
uint8_t* GetPointerOnData(void);
uint32_t GetSizeOnData(void);
Vector2D<float> GetDefinedSize(void) { return m_size;};
};
};
#endif