[DEV] start think of the gradient rendering ==> very complicated ...

This commit is contained in:
Edouard DUPIN 2015-12-08 21:42:30 +01:00
parent effc33ef14
commit 7e67a54e32
22 changed files with 292 additions and 298 deletions

View File

@ -17,8 +17,8 @@ const float esvg::kappa90(0.5522847493f);
#define __class__ "PaintState" #define __class__ "PaintState"
esvg::PaintState::PaintState() : esvg::PaintState::PaintState() :
fill(etk::color::black), fill(std::pair<etk::Color<float,4>, std::string>(etk::color::black, "")),
stroke(etk::color::none), stroke(std::pair<etk::Color<float,4>, std::string>(etk::color::none, "")),
strokeWidth(1.0f), strokeWidth(1.0f),
flagEvenOdd(false), flagEvenOdd(false),
lineCap(esvg::cap_butt), lineCap(esvg::cap_butt),
@ -30,8 +30,8 @@ esvg::PaintState::PaintState() :
} }
void esvg::PaintState::clear() { void esvg::PaintState::clear() {
fill = etk::color::black; fill = std::pair<etk::Color<float,4>, std::string>(etk::color::black, "");
stroke = etk::color::none; stroke = std::pair<etk::Color<float,4>, std::string>(etk::color::none, "");
strokeWidth = 1.0; strokeWidth = 1.0;
viewPort.setValue(255,255); viewPort.setValue(255,255);
flagEvenOdd = false; flagEvenOdd = false;
@ -151,8 +151,7 @@ std::pair<float, enum esvg::distance> esvg::Base::parseLength2(const std::string
} }
SVG_VERBOSE(" lenght : '" << n << "' => unit=" << unit); SVG_VERBOSE(" lenght : '" << n << "' => unit=" << unit);
// note : ";" is for the parsing of the style elements ... // note : ";" is for the parsing of the style elements ...
if( unit.size() == 0 if(unit.size() == 0) {
|| unit[0] == ';' ) {
return std::make_pair(n, esvg::distance_pixel); return std::make_pair(n, esvg::distance_pixel);
} else if (unit[0] == '%') { // xxx % } else if (unit[0] == '%') { // xxx %
return std::make_pair(n, esvg::distance_pourcent); return std::make_pair(n, esvg::distance_pourcent);
@ -212,43 +211,14 @@ float esvg::Base::parseLength(const std::string& _dataInput) {
return 0.0f; return 0.0f;
} }
// return the next char position ... (after ';' or NULL)
int32_t esvg::extractPartOfStyle(const std::string& _data, std::string& _outputType, std::string& _outputData, int32_t _pos) {
_outputType = "";
_outputData = "";
if (_pos == -1) {
return -2;
}
bool processFirst=true;
//SVG_DEBUG("parse : '" << _data.Extract(_pos) << "'");
for( int32_t iii=_pos; iii<_data.size(); iii++) {
//SVG_DEBUG(" ? '" << _data[iii] << "'");
if (_data[iii] == ';') {
// end of the element
return iii+1;
}
if (_data[iii] == ' ') {
// nothing to do ... we do not copy espaces ...
} else if (_data[iii] == ':') {
processFirst = false;
} else {
if (processFirst) {
_outputType += _data[iii];
} else {
_outputData += _data[iii];
}
}
}
SVG_VERBOSE(" extract : '" << _outputType << "':'" << _outputData << "'");
return -1;
}
void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _element) { void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _element) {
if (_element == nullptr) { if (_element == nullptr) {
return; return;
} }
/*
bool fillNone = false; bool fillNone = false;
bool strokeNone = false; bool strokeNone = false;
*/
std::string content; std::string content;
// ---------------- get unique ID ---------------- // ---------------- get unique ID ----------------
m_id = _element->getAttribute("id"); m_id = _element->getAttribute("id");
@ -256,9 +226,11 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
content = _element->getAttribute("stroke"); content = _element->getAttribute("stroke");
if (content.size()!=0) { if (content.size()!=0) {
m_paint.stroke = parseColor(content); m_paint.stroke = parseColor(content);
if (m_paint.stroke.a() == 0) { /*
if (m_paint.stroke.first.a() == 0) {
strokeNone = true; strokeNone = true;
} }
*/
} }
content = _element->getAttribute("stroke-width"); content = _element->getAttribute("stroke-width");
if (content.size()!=0) { if (content.size()!=0) {
@ -268,7 +240,7 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
if (content.size()!=0) { if (content.size()!=0) {
float opacity = parseLength(content); float opacity = parseLength(content);
opacity = std::avg(0.0f, opacity, 1.0f); opacity = std::avg(0.0f, opacity, 1.0f);
m_paint.stroke.setA(opacity); m_paint.stroke.first.setA(opacity);
} }
content = _element->getAttribute("stroke-dasharray"); content = _element->getAttribute("stroke-dasharray");
@ -314,15 +286,17 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
content = _element->getAttribute("fill"); content = _element->getAttribute("fill");
if (content.size()!=0) { if (content.size()!=0) {
m_paint.fill = parseColor(content); m_paint.fill = parseColor(content);
/*
if (m_paint.fill.a() == 0) { if (m_paint.fill.a() == 0) {
fillNone = true; fillNone = true;
} }
*/
} }
content = _element->getAttribute("fill-opacity"); content = _element->getAttribute("fill-opacity");
if (content.size()!=0) { if (content.size()!=0) {
float opacity = parseLength(content); float opacity = parseLength(content);
opacity = std::avg(0.0f, opacity, 1.0f); opacity = std::avg(0.0f, opacity, 1.0f);
m_paint.fill.setA(opacity); m_paint.fill.first.setA(opacity);
} }
content = _element->getAttribute("fill-rule"); content = _element->getAttribute("fill-rule");
if (content.size()!=0) { if (content.size()!=0) {
@ -340,102 +314,20 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
m_paint.opacity = parseLength(content); m_paint.opacity = parseLength(content);
m_paint.opacity = std::avg(0.0f, m_paint.opacity, 1.0f); m_paint.opacity = std::avg(0.0f, m_paint.opacity, 1.0f);
} }
// ---------------- STYLE ---------------- // Note : No parsing of 'style' it is already converted in attribute before...
content = _element->getAttribute("style");
if (content.size()!=0) {
std::string outputType;
std::string outputValue;
for( int32_t sss=extractPartOfStyle(content, outputType, outputValue, 0);
-2 != sss;
sss=extractPartOfStyle(content, outputType, outputValue, sss) ) {
SVG_VERBOSE(" style parse : \"" << outputType << "\" with value : \"" << outputValue << "\"");
if (outputType == "fill") {
m_paint.fill = parseColor(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.fill);
if (m_paint.fill.a() == 0) {
fillNone = true;
}
} else if (outputType == "stroke") {
m_paint.stroke = parseColor(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.stroke);
if (m_paint.stroke.a() == 0) {
strokeNone = true;
}
} else if (outputType == "stroke-width" ) {
m_paint.strokeWidth = parseLength(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.strokeWidth);
} else if (outputType == "opacity" ) {
m_paint.opacity = parseLength(content);
m_paint.opacity = std::avg(0.0f, m_paint.opacity, 1.0f);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.opacity);
} else if (outputType == "fill-opacity") {
float opacity = parseLength(outputValue);
opacity = std::avg(0.0f, opacity, 1.0f);
m_paint.fill.setA(opacity);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.fill);
} else if (outputType == "stroke-opacity") {
float opacity = parseLength(outputValue);
opacity = std::avg(0.0f, opacity, 1.0f);
m_paint.stroke.setA(opacity);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.stroke);
} else if (outputType == "fill-rule" ) {
if (outputValue == "nonzero" ) {
m_paint.flagEvenOdd = false;
} else if (outputValue == "evenodd") {
m_paint.flagEvenOdd = true;
} else {
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [nonzero,evenodd]");
}
} else if (outputType == "stroke-linecap") {
if (outputValue == "butt") {
m_paint.lineCap = esvg::cap_butt;
} else if (outputValue == "round") {
m_paint.lineCap = esvg::cap_round;
} else if (outputValue == "square") {
m_paint.lineCap = esvg::cap_square;
} else {
m_paint.lineCap = esvg::cap_butt;
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [butt,round,square]");
}
} else if (outputType == "stroke-linejoin") {
if (outputValue == "miter") {
m_paint.lineJoin = esvg::join_miter;
} else if (outputValue == "round") {
m_paint.lineJoin = esvg::join_round;
} else if (outputValue == "bevel") {
m_paint.lineJoin = esvg::join_bevel;
} else {
m_paint.lineJoin = esvg::join_miter;
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [miter,round,bevel]");
}
} else if (outputType == "stroke-dasharray") {
if (outputValue == "none") {
// OK, Nothing to do ...
} else {
SVG_TODO(" 'stroke-dasharray' not implemented ...");
}
} else if (outputType == "stroke-miterlimit") {
float tmp = parseLength(outputValue);
m_paint.miterLimit = std::max(0.0f, tmp);
} else if (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: // check if somewere none is set to the filling:
/*
if (fillNone == true) { if (fillNone == true) {
m_paint.fill.setA(0.0f); m_paint.fill.setA(0.0f);
} }
if (strokeNone == true) { if (strokeNone == true) {
m_paint.stroke.setA(0.0f); m_paint.stroke.setA(0.0f);
} }
*/
} }
etk::Color<uint8_t,4> esvg::Base::parseColor(const std::string& _inputData) { std::pair<etk::Color<float,4>, std::string> esvg::Base::parseColor(const std::string& _inputData) {
etk::Color<uint8_t,4> localColor = etk::color::white; std::pair<etk::Color<float,4>, std::string> localColor(etk::color::white, "");
if( _inputData.size() > 4 if( _inputData.size() > 4
&& _inputData[0] == 'u' && _inputData[0] == 'u'
@ -443,13 +335,14 @@ etk::Color<uint8_t,4> esvg::Base::parseColor(const std::string& _inputData) {
&& _inputData[2] == 'l' && _inputData[2] == 'l'
&& _inputData[3] == '(') { && _inputData[3] == '(') {
if (_inputData[4] == '#') { if (_inputData[4] == '#') {
// TODO : parse gradient ... localColor = std::pair<etk::Color<float,4>, std::string>(etk::color::none, &(_inputData[5]));
}
SVG_ERROR(" pb in parsing the color : \"" << _inputData << "\" == > url(XXX) is not supported now ...");
} else { } else {
localColor = etk::Color<uint8_t,4>(_inputData); SVG_ERROR(" pb in parsing the color : \"" << _inputData << "\" == > url(XXX) is not supported now ...");
} }
SVG_VERBOSE("Parse color : \"" << _inputData << "\" == > " << localColor); } else {
localColor = std::pair<etk::Color<float,4>, std::string>(_inputData, "");
}
SVG_VERBOSE("Parse color : \"" << _inputData << "\" == > " << localColor.first << " " << localColor.second);
return localColor; return localColor;
} }

View File

@ -40,8 +40,8 @@ namespace esvg {
PaintState(); PaintState();
void clear(); void clear();
public: public:
etk::Color<float,4> fill; std::pair<etk::Color<float,4>, std::string> fill;
etk::Color<float,4> stroke; std::pair<etk::Color<float,4>, std::string> stroke;
float strokeWidth; float strokeWidth;
bool flagEvenOdd; //!< Fill rules bool flagEvenOdd; //!< Fill rules
enum esvg::cap lineCap; enum esvg::cap lineCap;
@ -51,8 +51,6 @@ namespace esvg {
float opacity; float opacity;
}; };
int32_t extractPartOfStyle(const std::string& _data, std::string& _outputType, std::string& _outputData, int32_t _pos);
class Base { class Base {
protected: protected:
PaintState m_paint; PaintState m_paint;
@ -95,9 +93,9 @@ namespace esvg {
/** /**
* @brief parse a color specification from the svg file * @brief parse a color specification from the svg file
* @param[in] _inputData Data C String with the xml definition * @param[in] _inputData Data C String with the xml definition
* @return the parsed color * @return The parsed color (color used and the link if needed)
*/ */
etk::Color<uint8_t,4> parseColor(const std::string& _inputData); std::pair<etk::Color<float,4>, std::string> parseColor(const std::string& _inputData);
protected: protected:
std::string m_id; //!< unique ID of the element. std::string m_id; //!< unique ID of the element.
public: public:

View File

@ -102,8 +102,13 @@ void esvg::Circle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
if (m_paint.fill.a() != 0x00) { if (colorFill != nullptr) {
listSegmentFill.createSegmentList(listPoints); listSegmentFill.createSegmentList(listPoints);
listSegmentFill.applyMatrix(mtx); listSegmentFill.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -112,8 +117,7 @@ void esvg::Circle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
listSegmentFill); listSegmentFill);
} }
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -127,9 +131,9 @@ void esvg::Circle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -75,8 +75,8 @@ void esvg::Dimension::set(std::string _config) {
SVG_VERBOSE(" config dimention : \"" << _config << "\" == > " << *this ); SVG_VERBOSE(" config dimention : \"" << _config << "\" == > " << *this );
} }
static enum distance parseType(std::string& _config) { static enum esvg::distance parseType(std::string& _config) {
enum distance type = esvg::distance_pixel; enum esvg::distance type = esvg::distance_pixel;
if (etk::end_with(_config, "%", false) == true) { if (etk::end_with(_config, "%", false) == true) {
type = esvg::distance_pourcent; type = esvg::distance_pourcent;
_config.erase(_config.size()-1, 1); _config.erase(_config.size()-1, 1);
@ -120,7 +120,7 @@ void esvg::Dimension::set(std::string _configX, std::string _configY) {
float valueY = etk::string_to_float(_configY); float valueY = etk::string_to_float(_configY);
// TODO : Check difference ... // TODO : Check difference ...
set(vec2(valueX, valueY), typeX); set(vec2(valueX, valueY), typeX);
SVG_VERBOSE(" config dimention : \"" << _config << "\" == > " << *this ); SVG_VERBOSE(" config dimention : '" << _configX << "' '" << _configY << "' == > " << *this );
} }

View File

@ -97,7 +97,7 @@ namespace esvg {
*/ */
void set(const vec2& _size, enum distance _type); void set(const vec2& _size, enum distance _type);
private: public:
/** /**
* @brief set the current dimention in requested type * @brief set the current dimention in requested type
* @param[in] _config dimension configuration. * @param[in] _config dimension configuration.

View File

@ -107,8 +107,13 @@ void esvg::Ellipse::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
if (m_paint.fill.a() != 0x00) { if (colorFill != nullptr) {
listSegmentFill.createSegmentList(listPoints); listSegmentFill.createSegmentList(listPoints);
listSegmentFill.applyMatrix(mtx); listSegmentFill.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -117,8 +122,7 @@ void esvg::Ellipse::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
listSegmentFill); listSegmentFill);
} }
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -132,9 +136,9 @@ void esvg::Ellipse::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -99,7 +99,9 @@ bool esvg::Group::parseXML(const std::shared_ptr<exml::Element>& _element, mat2&
} }
void esvg::Group::display(int32_t _spacing) { void esvg::Group::display(int32_t _spacing) {
SVG_DEBUG(spacingDist(_spacing) << "Group (START) fill=" << m_paint.fill << " stroke=" << m_paint.stroke << " stroke-width=" << m_paint.strokeWidth ); SVG_DEBUG(spacingDist(_spacing) << "Group (START) fill=" << m_paint.fill.first << "/" << m_paint.fill.second
<< " stroke=" << m_paint.stroke.first << "/" << m_paint.stroke.second
<< " stroke-width=" << m_paint.strokeWidth );
for (size_t iii=0; iii<m_subElementList.size(); ++iii) { for (size_t iii=0; iii<m_subElementList.size(); ++iii) {
if (m_subElementList[iii] != nullptr) { if (m_subElementList[iii] != nullptr) {
m_subElementList[iii]->display(_spacing+1); m_subElementList[iii]->display(_spacing+1);

View File

@ -81,11 +81,15 @@ void esvg::Line::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _l
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
// No background ... // No background ...
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -99,9 +103,9 @@ void esvg::Line::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _l
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -15,14 +15,15 @@
#define __class__ "LinearGradient" #define __class__ "LinearGradient"
esvg::LinearGradient::LinearGradient(PaintState _parentPaintState) : esvg::Base(_parentPaintState) { esvg::LinearGradient::LinearGradient(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
m_pos1.setValue(0,0); m_pos1.set(vec2(0,0), esvg::distance_pixel);
m_pos2.setValue(0,0); m_pos2.set(vec2(0,0), esvg::distance_pixel);
} }
esvg::LinearGradient::~LinearGradient() { esvg::LinearGradient::~LinearGradient() {
} }
bool esvg::LinearGradient::parseXML(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) { bool esvg::LinearGradient::parseXML(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
// line must have a minimum size... // line must have a minimum size...
//m_paint.strokeWidth = 1; //m_paint.strokeWidth = 1;
@ -39,22 +40,12 @@ bool esvg::LinearGradient::parseXML(const std::shared_ptr<exml::Element>& _eleme
// add the property of the parrent modifications ... // add the property of the parrent modifications ...
m_transformMatrix *= _parentTrans; m_transformMatrix *= _parentTrans;
std::string content = _element->getAttribute("x1"); std::string contentX = _element->getAttribute("x1");
if (content.size()!=0) { std::string contentY = _element->getAttribute("y1");
m_pos1.setX(parseLength(content)); m_pos1.set(contentX, contentY);
} contentX = _element->getAttribute("x2");
content = _element->getAttribute("y1"); contentY = _element->getAttribute("y2");
if (content.size()!=0) { m_pos2.set(contentX, contentY);
m_pos1.setY(parseLength(content));
}
content = _element->getAttribute("x2");
if (content.size()!=0) {
m_pos2.setX(parseLength(content));
}
content = _element->getAttribute("y2");
if (content.size()!=0) {
m_pos2.setY(parseLength(content));
}
// parse all sub node : // parse all sub node :
for(int32_t iii=0; iii<_element->size() ; iii++) { for(int32_t iii=0; iii<_element->size() ; iii++) {
@ -64,35 +55,28 @@ bool esvg::LinearGradient::parseXML(const std::shared_ptr<exml::Element>& _eleme
continue; continue;
} }
if (child->getValue() == "stop") { if (child->getValue() == "stop") {
float offset = 0; float offset = 100;
etk::Color<float,4> stopColor = etk::color::none; etk::Color<float,4> stopColor = etk::color::none;
// ---------------- offset ---------------- std::string content = child->getAttribute("offset");
content = child->getAttribute("offset");
if (content.size()!=0) { if (content.size()!=0) {
offset = parseLength(content); std::pair<float, enum esvg::distance> tmp = parseLength2(content);
offset = std::avg(0.0f, offset, 100.0f); if (tmp.second != esvg::distance_pourcent) {
SVG_ERROR("offset : " << content << " res=" << tmp.first << "," << tmp.second << " Not support other than pourcent %");
} else {
offset = tmp.first;
} }
// ---------------- STYLE ---------------- }
content = _element->getAttribute("style"); content = child->getAttribute("stop-color");
if (content.size()!=0) { if (content.size()!=0) {
std::string outputType; stopColor = parseColor(content).first;
std::string outputValue; SVG_VERBOSE(" color : \"" << content << "\" == > " << stopColor);
for( int32_t sss=extractPartOfStyle(content, outputType, outputValue, 0); }
-2 != sss; content = child->getAttribute("stop-opacity");
sss=extractPartOfStyle(content, outputType, outputValue, sss) ) { if (content.size()!=0) {
SVG_VERBOSE(" style parse : \"" << outputType << "\" with value : \"" << outputValue << "\""); float opacity = parseLength(content);
if (outputType == "stop-color") {
stopColor = parseColor(outputValue);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << stopColor);
} else if (outputType == "stop-opacity") {
float opacity = parseLength(outputValue);
opacity = std::avg(0.0f, opacity, 1.0f); opacity = std::avg(0.0f, opacity, 1.0f);
stopColor.setA(opacity); stopColor.setA(opacity);
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << stopColor); SVG_VERBOSE(" opacity : \"" << content << "\" == > " << stopColor);
} else {
SVG_ERROR("not know painting element in style balise : \"" << outputType << "\" with value : \"" << outputValue << "\"");
}
}
} }
m_data.push_back(std::pair<float, etk::Color<float,4>>(offset, stopColor)); m_data.push_back(std::pair<float, etk::Color<float,4>>(offset, stopColor));
} else { } else {

View File

@ -14,8 +14,8 @@
namespace esvg { namespace esvg {
class LinearGradient : public esvg::Base { class LinearGradient : public esvg::Base {
private: private:
vec2 m_pos1; //!< gradient position x1 y1 esvg::Dimension m_pos1; //!< gradient position x1 y1
vec2 m_pos2; //!< gradient position x2 y2 esvg::Dimension m_pos2; //!< gradient position x2 y2
std::vector<std::pair<float, etk::Color<float,4>>> m_data; std::vector<std::pair<float, etk::Color<float,4>>> m_data;
public: public:
LinearGradient(PaintState _parentPaintState); LinearGradient(PaintState _parentPaintState);

View File

@ -271,16 +271,20 @@ void esvg::Path::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _l
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
if (m_paint.fill.a() != 0x00) { if (colorFill != nullptr) {
listSegmentFill.createSegmentList(listPoints); listSegmentFill.createSegmentList(listPoints);
listSegmentFill.applyMatrix(mtx); listSegmentFill.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
tmpFill.generate(_myRenderer.getSize(), _myRenderer.getNumberSubScanLine(), listSegmentFill); tmpFill.generate(_myRenderer.getSize(), _myRenderer.getNumberSubScanLine(), listSegmentFill);
} }
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -292,9 +296,9 @@ void esvg::Path::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _l
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -88,8 +88,13 @@ void esvg::Polygon::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
if (m_paint.fill.a() != 0x00) { if (colorFill != nullptr) {
listSegmentFill.createSegmentList(listPoints); listSegmentFill.createSegmentList(listPoints);
listSegmentFill.applyMatrix(mtx); listSegmentFill.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -98,8 +103,7 @@ void esvg::Polygon::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
listSegmentFill); listSegmentFill);
} }
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -113,9 +117,9 @@ void esvg::Polygon::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -85,8 +85,13 @@ void esvg::Polyline::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
if (m_paint.fill.a() != 0x00) { if (colorFill != nullptr) {
listSegmentFill.createSegmentList(listPoints); listSegmentFill.createSegmentList(listPoints);
listSegmentFill.applyMatrix(mtx); listSegmentFill.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -95,8 +100,7 @@ void esvg::Polyline::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_
listSegmentFill); listSegmentFill);
} }
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -110,9 +114,9 @@ void esvg::Polyline::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -59,7 +59,8 @@ void esvg::Rectangle::display(int32_t _spacing) {
} }
void esvg::Rectangle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) { void esvg::Rectangle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Rectangle : fill=" << m_paint.fill << " stroke=" << m_paint.stroke); SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Rectangle: fill=" << m_paint.fill.first << "/" << m_paint.fill.second
<< " stroke=" << m_paint.stroke.first << "/" << m_paint.stroke.second);
esvg::render::Path listElement; esvg::render::Path listElement;
listElement.clear(); listElement.clear();
if ( m_roundedCorner.x() == 0.0f if ( m_roundedCorner.x() == 0.0f
@ -102,8 +103,13 @@ void esvg::Rectangle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32
esvg::render::SegmentList listSegmentStroke; esvg::render::SegmentList listSegmentStroke;
esvg::render::Weight tmpFill; esvg::render::Weight tmpFill;
esvg::render::Weight tmpStroke; esvg::render::Weight tmpStroke;
std::shared_ptr<esvg::render::DynamicColor> colorFill = esvg::render::createColor(m_paint.fill, mtx, m_paint.viewPort);
std::shared_ptr<esvg::render::DynamicColor> colorStroke;
if (m_paint.strokeWidth > 0.0f) {
colorStroke = esvg::render::createColor(m_paint.stroke, mtx, m_paint.viewPort);
}
// Check if we need to display background // Check if we need to display background
if (m_paint.fill.a() != 0x00) { if (colorFill != nullptr) {
listSegmentFill.createSegmentList(listPoints); listSegmentFill.createSegmentList(listPoints);
listSegmentFill.applyMatrix(mtx); listSegmentFill.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -112,8 +118,7 @@ void esvg::Rectangle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32
listSegmentFill); listSegmentFill);
} }
// check if we need to display stroke: // check if we need to display stroke:
if ( m_paint.strokeWidth > 0 if (colorStroke != nullptr) {
&& m_paint.stroke.a() != 0x00) {
listSegmentStroke.createSegmentListStroke(listPoints, listSegmentStroke.createSegmentListStroke(listPoints,
m_paint.strokeWidth, m_paint.strokeWidth,
m_paint.lineCap, m_paint.lineCap,
@ -127,9 +132,9 @@ void esvg::Rectangle::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32
} }
// add on images: // add on images:
_myRenderer.print(tmpFill, _myRenderer.print(tmpFill,
m_paint.fill, colorFill,
tmpStroke, tmpStroke,
m_paint.stroke, colorStroke,
m_paint.opacity); m_paint.opacity);
#ifdef DEBUG #ifdef DEBUG
_myRenderer.addDebugSegment(listSegmentFill); _myRenderer.addDebugSegment(listSegmentFill);

View File

@ -13,14 +13,15 @@
#undef __class__ #undef __class__
#define __class__ "Renderer" #define __class__ "Renderer"
esvg::Renderer::Renderer(const ivec2& _size, bool _visualDebug) : esvg::Renderer::Renderer(const ivec2& _size, esvg::Document* _document, bool _visualDebug) :
#ifdef DEBUG #ifdef DEBUG
m_visualDebug(_visualDebug), m_visualDebug(_visualDebug),
m_factor(1), m_factor(1),
#endif #endif
m_interpolationRecurtionMax(10), m_interpolationRecurtionMax(10),
m_interpolationThreshold(0.25f), m_interpolationThreshold(0.25f),
m_nbSubScanLine(8) { m_nbSubScanLine(8),
m_document(_document) {
#ifdef DEBUG #ifdef DEBUG
if (m_visualDebug == true) { if (m_visualDebug == true) {
m_factor = 20; m_factor = 20;
@ -57,9 +58,9 @@ etk::Color<float,4> esvg::Renderer::mergeColor(etk::Color<float,4> _base, etk::C
} }
void esvg::Renderer::print(const esvg::render::Weight& _weightFill, void esvg::Renderer::print(const esvg::render::Weight& _weightFill,
const etk::Color<float,4>& _colorFill, const std::shared_ptr<esvg::render::DynamicColor>& _colorFill,
const esvg::render::Weight& _weightStroke, const esvg::render::Weight& _weightStroke,
const etk::Color<float,4>& _colorStroke, const std::shared_ptr<esvg::render::DynamicColor>& _colorStroke,
float _opacity) { float _opacity) {
int32_t sizeX = m_size.x(); int32_t sizeX = m_size.x();
int32_t sizeY = m_size.y(); int32_t sizeY = m_size.y();
@ -67,48 +68,7 @@ void esvg::Renderer::print(const esvg::render::Weight& _weightFill,
sizeX *= m_factor; sizeX *= m_factor;
sizeY *= m_factor; sizeY *= m_factor;
#endif #endif
if (_colorFill.a() == 0x00) {
if (_colorStroke.a() != 0x00) {
// only stroke
for (int32_t yyy=0; yyy<sizeY; ++yyy) {
for (int32_t xxx=0; xxx<sizeX; ++xxx) {
#if DEBUG
ivec2 pos(xxx/m_factor, yyy/m_factor);
#else
ivec2 pos(xxx, yyy);
#endif
float valueStroke = _weightStroke.get(pos);
if (valueStroke != 0.0f) {
// set a ratio of the merging value
etk::Color<float,4> tmpColor = _colorStroke * valueStroke;
tmpColor.setA(tmpColor.a() * _opacity);
// integrate the value at the previous color
m_buffer[sizeX*yyy + xxx] = mergeColor(m_buffer[sizeX*yyy + xxx], tmpColor);
}
}
}
}
} else {
if (_colorStroke.a() == 0x00) {
// only Fill
for (int32_t yyy=0; yyy<sizeY; ++yyy) {
for (int32_t xxx=0; xxx<sizeX; ++xxx) {
#if DEBUG
ivec2 pos(xxx/m_factor, yyy/m_factor);
#else
ivec2 pos(xxx, yyy);
#endif
float valueFill = _weightFill.get(pos);
if (valueFill != 0.0f) {
// set a ratio of the merging value
etk::Color<float,4> tmpColor = _colorFill * valueFill;
tmpColor.setA(tmpColor.a() * _opacity);
// integrate the value at the previous color
m_buffer[sizeX*yyy + xxx] = mergeColor(m_buffer[sizeX*yyy + xxx], tmpColor);
}
}
}
} else {
// all together // all together
for (int32_t yyy=0; yyy<sizeY; ++yyy) { for (int32_t yyy=0; yyy<sizeY; ++yyy) {
for (int32_t xxx=0; xxx<sizeX; ++xxx) { for (int32_t xxx=0; xxx<sizeX; ++xxx) {
@ -120,9 +80,9 @@ void esvg::Renderer::print(const esvg::render::Weight& _weightFill,
float valueFill = _weightFill.get(pos); float valueFill = _weightFill.get(pos);
float valueStroke = _weightStroke.get(pos); float valueStroke = _weightStroke.get(pos);
// calculate merge of stroke and fill value: // calculate merge of stroke and fill value:
etk::Color<float,4> intermediateColorFill = _colorFill; etk::Color<float,4> intermediateColorFill = _colorFill->getColor(pos);
intermediateColorFill.setA(intermediateColorFill.a()*valueFill); intermediateColorFill.setA(intermediateColorFill.a()*valueFill);
etk::Color<float,4> intermediateColorStroke = _colorStroke; etk::Color<float,4> intermediateColorStroke = _colorStroke->getColor(pos);
intermediateColorStroke.setA(intermediateColorStroke.a()*valueStroke); intermediateColorStroke.setA(intermediateColorStroke.a()*valueStroke);
etk::Color<float,4> intermediateColor = mergeColor(intermediateColorFill, intermediateColorStroke); etk::Color<float,4> intermediateColor = mergeColor(intermediateColorFill, intermediateColorStroke);
intermediateColor.setA(intermediateColor.a() * _opacity); intermediateColor.setA(intermediateColor.a() * _opacity);
@ -130,8 +90,6 @@ void esvg::Renderer::print(const esvg::render::Weight& _weightFill,
} }
} }
} }
}
}
#ifdef DEBUG #ifdef DEBUG
void esvg::Renderer::addDebugSegment(const esvg::render::SegmentList& _listSegment) { void esvg::Renderer::addDebugSegment(const esvg::render::SegmentList& _listSegment) {

View File

@ -13,8 +13,10 @@
#include <etk/math/Vector2D.h> #include <etk/math/Vector2D.h>
#include <etk/Color.h> #include <etk/Color.h>
#include <esvg/render/Weight.h> #include <esvg/render/Weight.h>
#include <esvg/render/DynamicColor.h>
namespace esvg { namespace esvg {
class Document;
class Renderer { class Renderer {
#ifdef DEBUG #ifdef DEBUG
private: private:
@ -22,7 +24,7 @@ namespace esvg {
int32_t m_factor; int32_t m_factor;
#endif #endif
public: public:
Renderer(const ivec2& _size, bool _visualDebug=false); Renderer(const ivec2& _size, esvg::Document* _document, bool _visualDebug=false);
~Renderer(); ~Renderer();
protected: protected:
ivec2 m_size; ivec2 m_size;
@ -55,13 +57,19 @@ namespace esvg {
etk::Color<float,4> mergeColor(etk::Color<float,4> _base, etk::Color<float,4> _integration); etk::Color<float,4> mergeColor(etk::Color<float,4> _base, etk::Color<float,4> _integration);
public: public:
void print(const esvg::render::Weight& _weightFill, void print(const esvg::render::Weight& _weightFill,
const etk::Color<float,4>& _colorFill, const std::shared_ptr<esvg::render::DynamicColor>& _colorFill,
const esvg::render::Weight& _weightStroke, const esvg::render::Weight& _weightStroke,
const etk::Color<float,4>& _colorStroke, const std::shared_ptr<esvg::render::DynamicColor>& _colorStroke,
float _opacity); float _opacity);
#ifdef DEBUG #ifdef DEBUG
void addDebugSegment(const esvg::render::SegmentList& _listSegment); void addDebugSegment(const esvg::render::SegmentList& _listSegment);
#endif #endif
protected:
esvg::Document* m_document;
public:
esvg::Document* getMainDocument() {
return m_document;
}
}; };
}; };

View File

@ -74,7 +74,7 @@ void esvg::Document::generateAnImage(const ivec2& _size, const std::string& _fil
} }
SVG_DEBUG("Generate size " << sizeRender); SVG_DEBUG("Generate size " << sizeRender);
std::shared_ptr<esvg::Renderer> renderedElement = std::make_shared<esvg::Renderer>(sizeRender, _visualDebug); std::shared_ptr<esvg::Renderer> renderedElement = std::make_shared<esvg::Renderer>(sizeRender, this, _visualDebug);
// create the first element matrix modification ... // create the first element matrix modification ...
mat2 basicTrans; mat2 basicTrans;
basicTrans *= etk::mat2Scale(vec2(sizeRender.x()/m_size.x(), sizeRender.y()/m_size.y())); basicTrans *= etk::mat2Scale(vec2(sizeRender.x()/m_size.x(), sizeRender.y()/m_size.y()));
@ -99,7 +99,7 @@ std::vector<etk::Color<float,4>> esvg::Document::renderImageFloatRGBA(ivec2& _si
_size.setY(m_size.y()); _size.setY(m_size.y());
} }
SVG_DEBUG("Generate size " << _size); SVG_DEBUG("Generate size " << _size);
std::shared_ptr<esvg::Renderer> renderedElement = std::make_shared<esvg::Renderer>(_size); std::shared_ptr<esvg::Renderer> renderedElement = std::make_shared<esvg::Renderer>(_size, this);
// create the first element matrix modification ... // create the first element matrix modification ...
mat2 basicTrans; mat2 basicTrans;
basicTrans *= etk::mat2Scale(vec2(_size.x()/m_size.x(), _size.y()/m_size.y())); basicTrans *= etk::mat2Scale(vec2(_size.x()/m_size.x(), _size.y()/m_size.y()));
@ -170,6 +170,7 @@ bool esvg::Document::parse(const std::string& _data) {
m_loadOK = false; m_loadOK = false;
return m_loadOK; return m_loadOK;
} }
cleanStyleProperty(root);
m_loadOK = parseXMLData(root); m_loadOK = parseXMLData(root);
return m_loadOK; return m_loadOK;
} }
@ -198,6 +199,7 @@ bool esvg::Document::load(const std::string& _file) {
m_loadOK = false; m_loadOK = false;
return m_loadOK; return m_loadOK;
} }
cleanStyleProperty(root);
m_loadOK = parseXMLData(root); m_loadOK = parseXMLData(root);
return m_loadOK; return m_loadOK;
} }
@ -206,7 +208,36 @@ bool esvg::Document::store(const std::string& _file) {
return false; return false;
} }
bool esvg::Document::cleanStyleProperty(const std::shared_ptr<exml::Element>& _root) {
// for each nodes:
for(int32_t iii=0; iii< _root->size(); iii++) {
std::shared_ptr<exml::Element> child = _root->getElement(iii);
if (child == nullptr) {
continue;
}
// get attribute style:
if (child->existAttribute("style") == true) {
std::string content = child->getAttribute("style");
if (content.size() != 0) {
std::vector<std::string> listStyle = etk::split(content, ';');
for (auto &it : listStyle) {
std::vector<std::string> value = etk::split(it, ':');
if (value.size() != 2) {
SVG_ERROR("parsing style with a wrong patern : " << it << " missing ':'");
continue;
}
// TODO : Check if the attibute already exist ...
child->setAttribute(value[0], value[1]);
}
}
// remove attribute style:
child->removeAttribute("style");
}
// sub-parsing ...
cleanStyleProperty(child);
}
return true;
}
bool esvg::Document::parseXMLData(const std::shared_ptr<exml::Element>& _root, bool _isReference) { bool esvg::Document::parseXMLData(const std::shared_ptr<exml::Element>& _root, bool _isReference) {
// get the svg version : // get the svg version :

View File

@ -59,6 +59,10 @@ namespace esvg {
*/ */
bool store(const std::string& _file); bool store(const std::string& _file);
protected: protected:
/**
* @brief change all style in a xml atribute
*/
virtual bool cleanStyleProperty(const std::shared_ptr<exml::Element>& _root);
virtual bool parseXMLData(const std::shared_ptr<exml::Element>& _root, bool _isReference = false); virtual bool parseXMLData(const std::shared_ptr<exml::Element>& _root, bool _isReference = false);
public: public:
bool isLoadOk() { bool isLoadOk() {

View File

@ -0,0 +1,33 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <esvg/debug.h>
#include <esvg/render/DynamicColor.h>
esvg::render::DynamicColorLinear::DynamicColorLinear(const std::string& _link, const mat2& _mtx, const vec2 _objectSize, const vec2 _objectPos)
{
}
etk::Color<float,4> esvg::render::DynamicColorLinear::getColor(const ivec2& _pos) {
return etk::color::purple;
}
std::shared_ptr<esvg::render::DynamicColor> esvg::render::createColor(std::pair<etk::Color<float,4>, std::string> _color, const mat2& _mtx, const vec2 _size) {
// Check if need to create a color:
if ( _color.first.a() == 0x00
&& _color.second == "") {
return nullptr;
}
if (_color.second != "") {
return std::make_shared<esvg::render::DynamicColorLinear>(_color.second, _mtx, _size);
}
return std::make_shared<esvg::render::DynamicColorUni>(_color.first);
}

View File

@ -0,0 +1,52 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#ifndef __ESVG_RENDER_DYNAMIC_COLOR_H__
#define __ESVG_RENDER_DYNAMIC_COLOR_H__
#include <etk/types.h>
#include <etk/Color.h>
#include <etk/math/Vector2D.h>
#include <etk/math/Matrix2.h>
namespace esvg {
namespace render {
class DynamicColor {
public:
DynamicColor() {
// nothing to do ...
}
virtual ~DynamicColor() {};
virtual etk::Color<float,4> getColor(const ivec2& _pos) = 0;
};
class DynamicColorUni : public esvg::render::DynamicColor {
public:
etk::Color<float,4> m_color;
public:
DynamicColorUni(const etk::Color<float,4>& _color) :
m_color(_color) {
}
etk::Color<float,4> getColor(const ivec2& _pos) {
return m_color;
}
};
class DynamicColorLinear : public esvg::render::DynamicColor {
public:
etk::Color<float,4> m_color;
public:
DynamicColorLinear(const std::string& _link, const mat2& _mtx, const vec2 _objectSize, const vec2 _objectPos);
etk::Color<float,4> getColor(const ivec2& _pos);
};
std::shared_ptr<DynamicColor> createColor(std::pair<etk::Color<float,4>, std::string> _color, const mat2& _mtx, const vec2 _size);
}
}
#endif

View File

@ -62,6 +62,7 @@ def create(target, module_name):
'esvg/render/Segment.cpp', 'esvg/render/Segment.cpp',
'esvg/render/SegmentList.cpp', 'esvg/render/SegmentList.cpp',
'esvg/render/Weight.cpp', 'esvg/render/Weight.cpp',
'esvg/render/DynamicColor.cpp',
'esvg/LinearGradient.cpp', 'esvg/LinearGradient.cpp',
'esvg/RadialGradient.cpp' 'esvg/RadialGradient.cpp'
]) ])
@ -102,6 +103,7 @@ def create(target, module_name):
'esvg/render/Segment.h', 'esvg/render/Segment.h',
'esvg/render/SegmentList.h', 'esvg/render/SegmentList.h',
'esvg/render/Weight.h', 'esvg/render/Weight.h',
'esvg/render/DynamicColor.h',
'esvg/LinearGradient.h', 'esvg/LinearGradient.h',
'esvg/RadialGradient.h' 'esvg/RadialGradient.h'
]) ])

View File

@ -27,7 +27,7 @@ TEST(TestGradientLinear, horizontal) {
esvg::Document doc; esvg::Document doc;
doc.parse(data); doc.parse(data);
etk::FSNodeWriteAllData("TestGradientLinear_horizontal.svg", data); etk::FSNodeWriteAllData("TestGradientLinear_horizontal.svg", data);
//doc.generateAnImage(ivec2(100, 100), "TestGradientLinear_horizontal.bmp", g_visualDebug); doc.generateAnImage(ivec2(100, 100), "TestGradientLinear_horizontal.bmp", g_visualDebug);
} }