[DEV] first study of rendering directly
This commit is contained in:
parent
14eea2f916
commit
402b29ca36
@ -41,36 +41,36 @@ void esvg::Base::parseTransform(const std::shared_ptr<exml::Element>& _element)
|
||||
const char * pointerOnData = inputString.c_str();
|
||||
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);
|
||||
m_transformMatrix = mat2(matrix);
|
||||
} else if (sscanf(pointerOnData, "translate (%f %f) %n", &xxx, &yyy, &n) == 2) {
|
||||
m_transformMatrix *= agg::trans_affine_translation(xxx, yyy);
|
||||
m_transformMatrix *= etk::mat2Translate(vec2(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);
|
||||
m_transformMatrix *= etk::mat2Translate(vec2(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);
|
||||
m_transformMatrix *= etk::mat2Scale(vec2(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);
|
||||
m_transformMatrix *= etk::mat2Scale(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);
|
||||
m_transformMatrix *= etk::mat2Translate(vec2(-xxx, -yyy));
|
||||
m_transformMatrix *= etk::mat2Rotate(angle);
|
||||
m_transformMatrix *= etk::mat2Translate(vec2(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);
|
||||
m_transformMatrix *= etk::mat2Rotate(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) << "°");
|
||||
m_transformMatrix *= agg::trans_affine_skewing(angle, 0.0);
|
||||
m_transformMatrix *= etk::mat2Skew(vec2(angle, 0.0f));
|
||||
} else if (sscanf(pointerOnData, "skewY (%f) %n", &angle, &n) == 1) {
|
||||
angle = angle / 180 * M_PI;
|
||||
SVG_VERBOSE("skewY : " << angle << "rad, " << (angle/M_PI*180) << "°");
|
||||
m_transformMatrix *= agg::trans_affine_skewing(0.0, angle);
|
||||
m_transformMatrix *= etk::mat2Skew(vec2(0.0f, angle));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -85,7 +85,7 @@ void esvg::Base::parseTransform(const std::shared_ptr<exml::Element>& _element)
|
||||
* @param[out] _pos parsed position
|
||||
* @param[out] _size parsed dimention
|
||||
*/
|
||||
void esvg::Base::parsePosition(const std::shared_ptr<const exml::Element>& _element, etk::Vector2D<float> &_pos, etk::Vector2D<float> &_size) {
|
||||
void esvg::Base::parsePosition(const std::shared_ptr<const exml::Element>& _element, vec2 &_pos, vec2 &_size) {
|
||||
_pos.setValue(0,0);
|
||||
_size.setValue(0,0);
|
||||
|
||||
@ -203,14 +203,14 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
std::string content = _element->getAttribute("fill");
|
||||
if (content.size()!=0) {
|
||||
m_paint.fill = parseColor(content);
|
||||
if (m_paint.fill.a == 0) {
|
||||
if (m_paint.fill.a() == 0) {
|
||||
fillNone = true;
|
||||
}
|
||||
}
|
||||
content = _element->getAttribute("stroke");
|
||||
if (content.size()!=0) {
|
||||
m_paint.stroke = parseColor(content);
|
||||
if (m_paint.stroke.a == 0) {
|
||||
if (m_paint.stroke.a() == 0) {
|
||||
strokeNone = true;
|
||||
}
|
||||
}
|
||||
@ -221,21 +221,21 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
content = _element->getAttribute("opacity");
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = std::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.fill.a = opacity*0xFF;
|
||||
m_paint.stroke.a = opacity*0xFF;
|
||||
opacity = std::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.fill.setA(opacity*0xFF);
|
||||
m_paint.stroke.setA(opacity*0xFF);
|
||||
}
|
||||
content = _element->getAttribute("fill-opacity");
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = std::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.fill.a = opacity*0xFF;
|
||||
m_paint.fill.setA(opacity*0xFF);
|
||||
}
|
||||
content = _element->getAttribute("stroke-opacity");
|
||||
if (content.size()!=0) {
|
||||
float opacity = parseLength(content);
|
||||
opacity = std::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.stroke.a = opacity*0xFF;
|
||||
m_paint.stroke.setA(opacity*0xFF);
|
||||
}
|
||||
content = _element->getAttribute("fill-rule");
|
||||
if (content.size()!=0) {
|
||||
@ -250,26 +250,26 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
content = _element->getAttribute("stroke-linecap");
|
||||
if (content.size()!=0) {
|
||||
if (content == "butt" ) {
|
||||
m_paint.lineCap = esvg::lineCapButt;
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
} else if (content == "round" ) {
|
||||
m_paint.lineCap = esvg::lineCapRound;
|
||||
m_paint.lineCap = esvg::cap_round;
|
||||
} else if (content == "square" ) {
|
||||
m_paint.lineCap = esvg::lineCapSquare;
|
||||
m_paint.lineCap = esvg::cap_square;
|
||||
} else {
|
||||
m_paint.lineCap = esvg::lineCapButt;
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
SVG_ERROR("not know stroke-linecap value : \"" << content << "\", not in [butt,round,square]");
|
||||
}
|
||||
}
|
||||
content = _element->getAttribute("stroke-linejoin");
|
||||
if (content.size()!=0) {
|
||||
if (content == "miter" ) {
|
||||
m_paint.lineJoin = esvg::lineJoinMiter;
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
} else if (content == "round" ) {
|
||||
m_paint.lineJoin = esvg::lineJoinRound;
|
||||
m_paint.lineJoin = esvg::join_round;
|
||||
} else if (content == "bevel" ) {
|
||||
m_paint.lineJoin = esvg::lineJoinBevel;
|
||||
m_paint.lineJoin = esvg::join_bevel;
|
||||
} else {
|
||||
m_paint.lineJoin = esvg::lineJoinMiter;
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
SVG_ERROR("not know stroke-linejoin value : \"" << content << "\", not in [miter,round,bevel]");
|
||||
}
|
||||
}
|
||||
@ -285,13 +285,13 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
if (outputType == "fill") {
|
||||
m_paint.fill = parseColor(outputValue);
|
||||
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.fill);
|
||||
if (m_paint.fill.a == 0) {
|
||||
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) {
|
||||
if (m_paint.stroke.a() == 0) {
|
||||
strokeNone = true;
|
||||
}
|
||||
} else if (outputType == "stroke-width" ) {
|
||||
@ -300,18 +300,18 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
} else if (outputType == "opacity" ) {
|
||||
float opacity = parseLength(outputValue);
|
||||
opacity = std::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.fill.a = opacity*0xFF;
|
||||
m_paint.stroke.a = opacity*0xFF;
|
||||
m_paint.fill.setA(opacity*0xFF);
|
||||
m_paint.stroke.setA(opacity*0xFF);
|
||||
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.fill);
|
||||
} else if (outputType == "fill-opacity") {
|
||||
float opacity = parseLength(outputValue);
|
||||
opacity = std::avg(0.0f, opacity, 1.0f);
|
||||
m_paint.fill.a = opacity*0xFF;
|
||||
m_paint.fill.setA(opacity*0xFF);
|
||||
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.a = opacity*0xFF;
|
||||
m_paint.stroke.setA(opacity*0xFF);
|
||||
SVG_VERBOSE(" input : \"" << outputValue << "\" == > " << m_paint.stroke);
|
||||
} else if (outputType == "fill-rule" ) {
|
||||
if (outputValue == "nonzero" ) {
|
||||
@ -323,24 +323,24 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
}
|
||||
} else if (outputType == "stroke-linecap") {
|
||||
if (outputValue == "butt") {
|
||||
m_paint.lineCap = esvg::lineCapButt;
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
} else if (outputValue == "round") {
|
||||
m_paint.lineCap = esvg::lineCapRound;
|
||||
m_paint.lineCap = esvg::cap_round;
|
||||
} else if (outputValue == "square") {
|
||||
m_paint.lineCap = esvg::lineCapSquare;
|
||||
m_paint.lineCap = esvg::cap_square;
|
||||
} else {
|
||||
m_paint.lineCap = esvg::lineCapButt;
|
||||
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::lineJoinMiter;
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
} else if (outputValue == "round") {
|
||||
m_paint.lineJoin = esvg::lineJoinRound;
|
||||
m_paint.lineJoin = esvg::join_round;
|
||||
} else if (outputValue == "bevel") {
|
||||
m_paint.lineJoin = esvg::lineJoinBevel;
|
||||
m_paint.lineJoin = esvg::join_bevel;
|
||||
} else {
|
||||
m_paint.lineJoin = esvg::lineJoinMiter;
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
SVG_ERROR("not know " << outputType << " value : \"" << outputValue << "\", not in [miter,round,bevel]");
|
||||
}
|
||||
} else if (outputType == "marker-start") {
|
||||
@ -352,10 +352,10 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
}
|
||||
// check if somewere none is set to the filling:
|
||||
if (true == fillNone) {
|
||||
m_paint.fill.a = 0;
|
||||
m_paint.fill.setA(0);
|
||||
}
|
||||
if (true == strokeNone) {
|
||||
m_paint.stroke.a = 0;
|
||||
m_paint.stroke.setA(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,8 +364,8 @@ void esvg::Base::parsePaintAttr(const std::shared_ptr<const exml::Element>& _ele
|
||||
* @param[in] _inputData Data C String with the xml definition
|
||||
* @return the parsed color
|
||||
*/
|
||||
draw::Color esvg::Base::parseColor(const std::string& _inputData) {
|
||||
draw::Color localColor = draw::color::white;
|
||||
etk::Color<uint8_t,4> esvg::Base::parseColor(const std::string& _inputData) {
|
||||
etk::Color<uint8_t,4> localColor = etk::color::white;
|
||||
|
||||
if( _inputData.size() > 4
|
||||
&& _inputData[0] == 'u'
|
||||
@ -377,7 +377,7 @@ draw::Color esvg::Base::parseColor(const std::string& _inputData) {
|
||||
}
|
||||
SVG_ERROR(" pb in parsing the color : \"" << _inputData << "\" == > url(XXX) is not supported now ...");
|
||||
} else {
|
||||
localColor = _inputData.c_str();
|
||||
localColor = etk::Color<uint8_t,4>(_inputData);
|
||||
}
|
||||
SVG_VERBOSE("Parse color : \"" << _inputData << "\" == > " << localColor);
|
||||
return localColor;
|
||||
@ -389,7 +389,7 @@ draw::Color esvg::Base::parseColor(const std::string& _inputData) {
|
||||
* @param[in] _element standart XML node
|
||||
* @return true if no problem arrived
|
||||
*/
|
||||
bool esvg::Base::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Base::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
SVG_ERROR("NOT IMPLEMENTED");
|
||||
_sizeMax.setValue(0,0);
|
||||
return false;
|
||||
@ -404,3 +404,6 @@ const char * esvg::Base::spacingDist(int32_t _spacing) {
|
||||
return tmpValue + 20*4 - _spacing*4;
|
||||
}
|
||||
|
||||
void esvg::Base::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_WARNING(spacingDist(_level) << "DRAW esvg::Base ... ==> No drawing availlable");
|
||||
}
|
65
esvg/Base.h
65
esvg/Base.h
@ -12,42 +12,73 @@
|
||||
#include <etk/types.h>
|
||||
#include <vector>
|
||||
#include <etk/math/Vector2D.h>
|
||||
#include <draw/Color.h>
|
||||
#include <etk/math/Matrix2.h>
|
||||
#include <etk/Color.h>
|
||||
|
||||
#include <exml/exml.h>
|
||||
#include <esvg/Renderer.h>
|
||||
|
||||
#include <agg/agg_basics.h>
|
||||
#include <agg/agg_rendering_buffer.h>
|
||||
#include <agg/agg_rasterizer_scanline_aa.h>
|
||||
#include <agg/agg_scanline_p.h>
|
||||
#include <agg/agg_renderer_scanline.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
#include <agg/agg_conv_transform.h>
|
||||
#include <agg/agg_bounding_rect.h>
|
||||
#include <agg/agg_color_rgba.h>
|
||||
#include <agg/agg_pixfmt_rgba.h>
|
||||
|
||||
namespace esvg {
|
||||
/**
|
||||
* @brief Painting mode of the Object:
|
||||
*/
|
||||
enum paint {
|
||||
paint_none, //!< No painting.
|
||||
paint_color, //!< Painting a color.
|
||||
paint_gradientLinear, //!< Painting a linear gradient.
|
||||
paint_gradientRadial //!< Painting a radial gradient.
|
||||
};
|
||||
/**
|
||||
* @brief Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle.
|
||||
*/
|
||||
enum spread {
|
||||
spread_pad, //!< 'pad' spread.
|
||||
spread_reflect, //!< 'reflect' spread.
|
||||
spread_repead, //!< 'repead' spread.
|
||||
};
|
||||
|
||||
enum cap {
|
||||
cap_butt,
|
||||
cap_round,
|
||||
cap_square
|
||||
};
|
||||
|
||||
enum join {
|
||||
join_miter,
|
||||
join_round,
|
||||
join_bevel
|
||||
};
|
||||
|
||||
class PaintState {
|
||||
public:
|
||||
etk::Color<uint8_t,4> fill;
|
||||
etk::Color<uint8_t,4> stroke;
|
||||
float strokeWidth;
|
||||
bool flagEvenOdd; //!< Fill rules
|
||||
enum esvg::cap lineCap;
|
||||
enum esvg::join lineJoin;
|
||||
vec2 viewPort;
|
||||
};
|
||||
|
||||
class Base {
|
||||
protected:
|
||||
PaintState m_paint;
|
||||
agg::trans_affine m_transformMatrix; //!< specific render of the curent element
|
||||
mat2 m_transformMatrix; //!< specific render of the curent element
|
||||
const char * spacingDist(int32_t _spacing);
|
||||
public:
|
||||
Base() {};
|
||||
Base(PaintState _parentPaintState);
|
||||
virtual ~Base() { };
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
//specific drawing for AAG librairy ...
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) { };
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level=1);
|
||||
|
||||
virtual void display(int32_t _spacing) { };
|
||||
void parseTransform(const std::shared_ptr<exml::Element>& _element);
|
||||
void parsePosition(const std::shared_ptr<const exml::Element>& _element, etk::Vector2D<float> &_pos, etk::Vector2D<float> &_size);
|
||||
void parsePosition(const std::shared_ptr<const exml::Element>& _element, vec2 &_pos, vec2 &_size);
|
||||
float parseLength(const std::string& _dataInput);
|
||||
void parsePaintAttr(const std::shared_ptr<const exml::Element>& _element);
|
||||
draw::Color parseColor(const std::string& _inputData);
|
||||
etk::Color<uint8_t,4> parseColor(const std::string& _inputData);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Circle.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_ellipse.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Circle"
|
||||
@ -22,7 +20,7 @@ esvg::Circle::~Circle() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Circle::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Circle::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
m_radius = 0.0;
|
||||
m_position.setValue(0,0);
|
||||
if (_element == nullptr) {
|
||||
@ -58,27 +56,27 @@ bool esvg::Circle::parse(const std::shared_ptr<exml::Element>& _element, agg::tr
|
||||
return true;
|
||||
}
|
||||
|
||||
void esvg::Circle::display(int32_t _spacing)
|
||||
{
|
||||
void esvg::Circle::display(int32_t _spacing) {
|
||||
SVG_DEBUG(spacingDist(_spacing) << "Circle " << m_position << " radius=" << m_radius);
|
||||
}
|
||||
|
||||
|
||||
void esvg::Circle::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans)
|
||||
{
|
||||
void esvg::Circle::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Circle");
|
||||
/*
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.r, m_paint.fill.g, m_paint.fill.b, m_paint.fill.a));
|
||||
// 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;
|
||||
mat2 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.a != 0x00) {
|
||||
agg::conv_transform<agg::ellipse, agg::trans_affine> trans(myCircle, mtx);
|
||||
agg::conv_transform<agg::ellipse, mat2> trans(myCircle, mtx);
|
||||
_myRenderer.m_rasterizer.add_path(trans);
|
||||
agg::render_scanlines(_myRenderer.m_rasterizer, _myRenderer.m_scanLine, *_myRenderer.m_renderArea);
|
||||
}
|
||||
@ -88,12 +86,12 @@ void esvg::Circle::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basi
|
||||
// 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);
|
||||
agg::conv_transform<agg::conv_stroke<agg::ellipse>, mat2> 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);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
@ -14,14 +14,14 @@
|
||||
namespace esvg {
|
||||
class Circle : public esvg::Base {
|
||||
private:
|
||||
etk::Vector2D<float> m_position; //!< Position of the Circle
|
||||
vec2 m_position; //!< Position of the Circle
|
||||
float m_radius; //!< Radius of the Circle
|
||||
public:
|
||||
Circle(PaintState _parentPaintState);
|
||||
~Circle();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Ellipse.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_ellipse.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Ellipse"
|
||||
@ -22,7 +20,7 @@ esvg::Ellipse::~Ellipse() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Ellipse::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Ellipse::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -67,20 +65,22 @@ void esvg::Ellipse::display(int32_t _spacing) {
|
||||
}
|
||||
|
||||
|
||||
void esvg::Ellipse::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) {
|
||||
void esvg::Ellipse::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Ellipse");
|
||||
/*
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.r, m_paint.fill.g, m_paint.fill.b, m_paint.fill.a));
|
||||
// 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;
|
||||
mat2 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.a != 0x00) {
|
||||
agg::conv_transform<agg::ellipse, agg::trans_affine> trans(myEllipse, mtx);
|
||||
agg::conv_transform<agg::ellipse, mat2> trans(myEllipse, mtx);
|
||||
_myRenderer.m_rasterizer.add_path(trans);
|
||||
agg::render_scanlines(_myRenderer.m_rasterizer, _myRenderer.m_scanLine, *_myRenderer.m_renderArea);
|
||||
}
|
||||
@ -89,12 +89,13 @@ void esvg::Ellipse::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _bas
|
||||
// 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);
|
||||
agg::conv_transform<agg::conv_stroke<agg::ellipse>, mat2> 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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,14 +14,14 @@
|
||||
namespace esvg {
|
||||
class Ellipse : public esvg::Base {
|
||||
private:
|
||||
etk::Vector2D<float> m_c; //!< Center property of the ellipse
|
||||
etk::Vector2D<float> m_r; //!< Radius property of the ellipse
|
||||
vec2 m_c; //!< Center property of the ellipse
|
||||
vec2 m_r; //!< Radius property of the ellipse
|
||||
public:
|
||||
Ellipse(PaintState _parentPaintState);
|
||||
~Ellipse();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -31,22 +31,22 @@ esvg::Group::~Group() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Group::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Group::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element == nullptr) {
|
||||
return false;
|
||||
}
|
||||
// parse ...
|
||||
etk::Vector2D<float> pos(0,0);
|
||||
etk::Vector2D<float> size(0,0);
|
||||
vec2 pos(0,0);
|
||||
vec2 size(0,0);
|
||||
parseTransform(_element);
|
||||
parsePosition(_element, pos, size);
|
||||
parsePaintAttr(_element);
|
||||
SVG_VERBOSE("parsed G1. trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
|
||||
SVG_VERBOSE("parsed G1. trans : " << m_transformMatrix);
|
||||
|
||||
// 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 << ")");
|
||||
SVG_VERBOSE("parsed G2. trans : " << m_transformMatrix);
|
||||
|
||||
_sizeMax.setValue(0,0);
|
||||
vec2 tmpPos(0,0);
|
||||
@ -109,11 +109,11 @@ void esvg::Group::display(int32_t _spacing) {
|
||||
SVG_DEBUG(spacingDist(_spacing) << "Group (STOP)");
|
||||
}
|
||||
|
||||
void esvg::Group::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans)
|
||||
{
|
||||
void esvg::Group::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::group");
|
||||
for (int32_t iii=0; iii<m_subElementList.size(); iii++) {
|
||||
if (NULL != m_subElementList[iii]) {
|
||||
m_subElementList[iii]->aggDraw(_myRenderer, _basicTrans);
|
||||
m_subElementList[iii]->aggDraw(_myRenderer, _basicTrans, _level+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ namespace esvg {
|
||||
public:
|
||||
Group(PaintState _parentPaintState);
|
||||
~Group();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Line.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Line"
|
||||
@ -23,7 +21,7 @@ esvg::Line::~Line() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Line::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Line::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
// line must have a minimum size...
|
||||
m_paint.strokeWidth = 1;
|
||||
if (_element == nullptr) {
|
||||
@ -60,8 +58,10 @@ void esvg::Line::display(int32_t _spacing) {
|
||||
SVG_DEBUG(spacingDist(_spacing) << "Line " << m_startPos << " to " << m_stopPos);
|
||||
}
|
||||
|
||||
void esvg::Line::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) {
|
||||
agg::path_storage path;
|
||||
void esvg::Line::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Line");
|
||||
# if 0
|
||||
esvg::RenderPath path;
|
||||
path.start_new_path();
|
||||
path.move_to(m_startPos.x(), m_startPos.y());
|
||||
path.line_to(m_stopPos.x(), m_stopPos.y());
|
||||
@ -90,20 +90,21 @@ void esvg::Line::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicT
|
||||
break;
|
||||
}
|
||||
*/
|
||||
agg::trans_affine mtx = m_transformMatrix;
|
||||
mat2 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
if (m_paint.strokeWidth > 0) {
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.r, m_paint.stroke.g, m_paint.stroke.b, m_paint.stroke.a));
|
||||
// drawing as an outline
|
||||
agg::conv_stroke<agg::path_storage> myPolygonStroke(path);
|
||||
agg::conv_stroke<esvg::RenderPath> myPolygonStroke(path);
|
||||
myPolygonStroke.width(m_paint.strokeWidth);
|
||||
agg::conv_transform<agg::conv_stroke<agg::path_storage>, agg::trans_affine> transStroke(myPolygonStroke, mtx);
|
||||
agg::conv_transform<agg::conv_stroke<esvg::RenderPath>, mat2> 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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,14 +14,14 @@
|
||||
namespace esvg {
|
||||
class Line : public esvg::Base {
|
||||
private:
|
||||
etk::Vector2D<float> m_startPos; //!< Start line position
|
||||
etk::Vector2D<float> m_stopPos; //!< Stop line position
|
||||
vec2 m_startPos; //!< Start line position
|
||||
vec2 m_stopPos; //!< Stop line position
|
||||
public:
|
||||
Line(PaintState _parentPaintState);
|
||||
~Line();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
784
esvg/Path.cpp
784
esvg/Path.cpp
@ -8,11 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Path.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_conv_dash.h>
|
||||
#include <agg/agg_conv_curve.h>
|
||||
#include <agg/agg_conv_contour.h>
|
||||
#include <agg/agg_conv_smooth_poly1.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Path"
|
||||
@ -65,7 +60,7 @@ const char * extractCmd(const char* _input, char& _cmd, std::vector<float>& _out
|
||||
return outputPointer;
|
||||
}
|
||||
|
||||
bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -117,13 +112,13 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathMoveTo;
|
||||
pathElement.m_cmd = esvg::path_moveTo;
|
||||
if (listDot.size() >= 2) {
|
||||
pathElement.m_element[0] = listDot[0];
|
||||
pathElement.m_element[1] = listDot[1];
|
||||
m_listElement.push_back(pathElement);
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathLineTo;
|
||||
pathElement.m_cmd = esvg::path_lineTo;
|
||||
for(int32_t iii=2; iii<listDot.size(); iii+=2) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -138,7 +133,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathLineTo;
|
||||
pathElement.m_cmd = esvg::path_lineTo;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=2) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -153,7 +148,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathLineToV;
|
||||
pathElement.m_cmd = esvg::path_lineToV;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=1) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
m_listElement.push_back(pathElement);
|
||||
@ -167,7 +162,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathLineToH;
|
||||
pathElement.m_cmd = esvg::path_lineToH;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=1) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
m_listElement.push_back(pathElement);
|
||||
@ -181,7 +176,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathBesizeCurveTo;
|
||||
pathElement.m_cmd = esvg::path_bezierCurveTo;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=4) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -198,7 +193,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathBesizeSmothCurveTo;
|
||||
pathElement.m_cmd = esvg::path_bezierSmothCurveTo;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=2) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -213,7 +208,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathCurveTo;
|
||||
pathElement.m_cmd = path_curveTo;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=6) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -232,7 +227,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathSmothCurveTo;
|
||||
pathElement.m_cmd = esvg::path_smothCurveTo;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=4) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -249,7 +244,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathElliptic;
|
||||
pathElement.m_cmd = esvg::path_elliptic;
|
||||
for(int32_t iii=0; iii<listDot.size(); iii+=7) {
|
||||
pathElement.m_element[0] = listDot[iii];
|
||||
pathElement.m_element[1] = listDot[iii+1];
|
||||
@ -268,7 +263,7 @@ bool esvg::Path::parse(const std::shared_ptr<exml::Element>& _element, agg::tran
|
||||
SVG_WARNING("the PATH command "<< command << " has not the good number of element = " << listDot.size() );
|
||||
break;
|
||||
}
|
||||
pathElement.m_cmd = esvg::pathStop;
|
||||
pathElement.m_cmd = esvg::path_stop;
|
||||
m_listElement.push_back(pathElement);
|
||||
break;
|
||||
default:
|
||||
@ -283,22 +278,22 @@ void esvg::Path::display(int32_t _spacing) {
|
||||
SVG_DEBUG(spacingDist(_spacing) << "Path");
|
||||
for(int32_t iii=0; iii<m_listElement.size(); iii++) {
|
||||
switch (m_listElement[iii].m_cmd) {
|
||||
case esvg::pathStop:
|
||||
case esvg::path_stop:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "STOP");
|
||||
break;
|
||||
case esvg::pathMoveTo:
|
||||
case esvg::path_moveTo:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "MOVETO (" << m_listElement[iii].m_element[0] << "," << m_listElement[iii].m_element[1] << ")" );
|
||||
break;
|
||||
case esvg::pathLineTo:
|
||||
case esvg::path_lineTo:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "LINETO (" << m_listElement[iii].m_element[0] << "," << m_listElement[iii].m_element[1] << ")" );
|
||||
break;
|
||||
case esvg::pathLineToH:
|
||||
case esvg::path_lineToH:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "LINETO_H (" << m_listElement[iii].m_element[0] << ")" );
|
||||
break;
|
||||
case esvg::pathLineToV:
|
||||
case esvg::path_lineToV:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "LINETO_V (" << m_listElement[iii].m_element[0] << ")" );
|
||||
break;
|
||||
case esvg::pathCurveTo:
|
||||
case esvg::path_curveTo:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "CURVETO (" << m_listElement[iii].m_element[0] <<
|
||||
"," << m_listElement[iii].m_element[1] <<
|
||||
"," << m_listElement[iii].m_element[2] <<
|
||||
@ -306,23 +301,29 @@ void esvg::Path::display(int32_t _spacing) {
|
||||
"," << m_listElement[iii].m_element[4] <<
|
||||
"," << m_listElement[iii].m_element[5] << ")" );
|
||||
break;
|
||||
case esvg::pathSmothCurveTo:
|
||||
case esvg::path_smothCurveTo:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "SMOTH_CURVETO (" << m_listElement[iii].m_element[0] <<
|
||||
"," << m_listElement[iii].m_element[1] <<
|
||||
"," << m_listElement[iii].m_element[2] <<
|
||||
"," << m_listElement[iii].m_element[3] << ")" );
|
||||
break;
|
||||
case esvg::pathBesizeCurveTo:
|
||||
case esvg::path_bezierCurveTo:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "BEZIER_CURVETO (" << m_listElement[iii].m_element[0] <<
|
||||
"," << m_listElement[iii].m_element[1] <<
|
||||
"," << m_listElement[iii].m_element[2] <<
|
||||
"," << m_listElement[iii].m_element[3] << ")" );
|
||||
break;
|
||||
case esvg::pathBesizeSmothCurveTo:
|
||||
case esvg::path_bezierSmothCurveTo:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "BEZIER_SMOTH_CURVETO (" << m_listElement[iii].m_element[0] << "," << m_listElement[iii].m_element[1] << ")" );
|
||||
break;
|
||||
case esvg::pathElliptic:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "ELLIPTIC (TODO...)" );
|
||||
case esvg::path_elliptic:
|
||||
SVG_DEBUG(spacingDist(_spacing+4) << "ELLIPTIC (" << m_listElement[iii].m_element[0] <<
|
||||
"," << m_listElement[iii].m_element[1] <<
|
||||
"," << m_listElement[iii].m_element[2] <<
|
||||
"," << m_listElement[iii].m_element[3] <<
|
||||
"," << m_listElement[iii].m_element[4] <<
|
||||
"," << m_listElement[iii].m_element[5] <<
|
||||
"," << m_listElement[iii].m_element[6] << ")" );
|
||||
// show explanation at : http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
|
||||
break;
|
||||
default:
|
||||
@ -332,70 +333,560 @@ void esvg::Path::display(int32_t _spacing) {
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::Path::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) {
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.r, m_paint.fill.g, m_paint.fill.b, m_paint.fill.a));
|
||||
|
||||
agg::path_storage path;
|
||||
path.start_new_path();
|
||||
|
||||
|
||||
class Segment {
|
||||
public:
|
||||
Segment(const vec2& _p0, const vec2& _p1) {
|
||||
// segment register all time the lower at P0n then we need to register the sens of the path
|
||||
if (_p0.y() < _p1.y()) {
|
||||
p0 = _p0;
|
||||
p1 = _p1;
|
||||
direction = 1.0f; // direction like clock
|
||||
} else {
|
||||
p0 = _p1;
|
||||
p1 = _p0;
|
||||
direction = -1.0f; // direction like anti-clock
|
||||
}
|
||||
}
|
||||
vec2 p0;
|
||||
vec2 p1;
|
||||
float direction;
|
||||
};
|
||||
|
||||
|
||||
class Scanline {
|
||||
private:
|
||||
std::vector<float> m_data;
|
||||
public:
|
||||
// constructor :
|
||||
Scanline(size_t _size=32) {
|
||||
float tmp(0);
|
||||
m_data.resize(_size, tmp);
|
||||
}
|
||||
// destructor
|
||||
~Scanline() { };
|
||||
// -----------------------------------------------
|
||||
// -- basic tools :
|
||||
// -----------------------------------------------
|
||||
public:
|
||||
size_t size() const {
|
||||
return m_data.size();
|
||||
};
|
||||
void clear(float _fill) {
|
||||
for (auto &it : m_data) {
|
||||
it = _fill;
|
||||
}
|
||||
}
|
||||
float get(int32_t _pos) const {
|
||||
if( _pos>=0
|
||||
&& _pos<m_data.size()) {
|
||||
return m_data[_pos];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void set(int32_t _pos, float _newColor) {
|
||||
if( _pos>=0
|
||||
&& _pos<m_data.size()) {
|
||||
m_data[_pos] = _newColor;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Weighter {
|
||||
private:
|
||||
ivec2 m_size;
|
||||
std::vector<float> m_data;
|
||||
public:
|
||||
// constructor :
|
||||
Weighter(const ivec2& _size=ivec2(32,32)):
|
||||
m_size(_size) {
|
||||
float tmp(0);
|
||||
m_data.resize(m_size.x()*m_size.y(), tmp);
|
||||
if ((uint32_t)m_size.x()*m_size.y() > m_data.size()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// destructor
|
||||
~Weighter() { };
|
||||
// -----------------------------------------------
|
||||
// -- basic tools :
|
||||
// -----------------------------------------------
|
||||
public:
|
||||
const ivec2& getSize() const {
|
||||
return m_size;
|
||||
};
|
||||
int32_t getWidth() const {
|
||||
return m_size.x();
|
||||
};
|
||||
int32_t getHeight() const {
|
||||
return m_size.y();
|
||||
};
|
||||
void clear(float _fill) {
|
||||
for (int32_t iii=0; iii<m_size.x()*m_size.y(); iii++) {
|
||||
m_data[iii] = _fill;
|
||||
}
|
||||
}
|
||||
float get(const ivec2& _pos) const {
|
||||
if ( _pos.x()>0 && _pos.x()<m_size.x()
|
||||
&& _pos.y()>0 && _pos.y()<m_size.y()) {
|
||||
return m_data[_pos.x()+_pos.y()*m_size.x()];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void set(const ivec2& _pos, float _newColor) {
|
||||
if ( _pos.x()>=0 && _pos.x()<m_size.x()
|
||||
&& _pos.y()>=0 && _pos.y()<m_size.y()) {
|
||||
m_data[_pos.x()+_pos.y()*m_size.x()] = _newColor;
|
||||
}
|
||||
}
|
||||
void set(int32_t _posY, const Scanline& _data) {
|
||||
if ( _posY>=0
|
||||
&& _posY<m_size.y()) {
|
||||
for (size_t xxx=0; xxx<m_size.x(); ++xxx) {
|
||||
m_data[xxx+_posY*m_size.x()] = _data.get(xxx);
|
||||
}
|
||||
}
|
||||
}
|
||||
void append(int32_t _posY, const Scanline& _data) {
|
||||
if ( _posY>=0
|
||||
&& _posY<m_size.y()) {
|
||||
for (size_t xxx=0; xxx<m_size.x(); ++xxx) {
|
||||
m_data[xxx+_posY*m_size.x()] += _data.get(xxx);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool sortSegmentFunction(const Segment& _e1, const Segment& _e2) {
|
||||
return _e1.p0.y() < _e2.p0.y();
|
||||
}
|
||||
|
||||
bool sortXPosFunction(const std::pair<float,float>& _e1, const std::pair<float,float>& _e2) {
|
||||
return _e1.first < _e2.first;
|
||||
}
|
||||
|
||||
class PointRender {
|
||||
public:
|
||||
enum typePoint {
|
||||
typePoint_single, //!< Point type is single, this mean that it start and stop of a path
|
||||
typePoint_start, //!< Point type is starting of a path
|
||||
typePoint_stop, //!< Point type is stoping of a path
|
||||
typePoint_join, //!< Point type in an user point provided inside a path
|
||||
typePoint_interpolation, //!< This point is dynamicly calculated to create an interpolation
|
||||
};
|
||||
public:
|
||||
vec2 m_pos; //!< position of the point
|
||||
enum typePoint m_type;
|
||||
vec2 m_miterAxe;
|
||||
vec2 m_delta;
|
||||
float m_len;
|
||||
PointRender(const vec2& _pos, enum typePoint _type = PointRender::typePoint_join) :
|
||||
m_pos(_pos),
|
||||
m_type(_type) {
|
||||
// nothing to do ...
|
||||
}
|
||||
void normalize(const vec2& _nextPoint) {
|
||||
m_delta = _nextPoint - m_pos;
|
||||
m_len = m_delta.length();
|
||||
}
|
||||
};
|
||||
|
||||
class Transformation {
|
||||
public:
|
||||
std::vector<PointRender> m_listPoints;
|
||||
std::vector<Segment> m_listSegment;
|
||||
float m_threshold;
|
||||
int32_t m_recursionMax;
|
||||
int32_t m_subSamplingCount;
|
||||
public:
|
||||
Transformation() :
|
||||
m_threshold(0.25f),
|
||||
m_recursionMax(10),
|
||||
m_subSamplingCount(8) {
|
||||
|
||||
}
|
||||
|
||||
void addSegment(const PointRender& _pos0, const PointRender& _pos1) {
|
||||
// Skip horizontal Segments
|
||||
if (_pos0.m_pos.y() == _pos1.m_pos.y()) {
|
||||
// remove /0 operation
|
||||
return;
|
||||
}
|
||||
m_listSegment.push_back(Segment(_pos0.m_pos, _pos1.m_pos));
|
||||
}
|
||||
|
||||
void flattenCubicBez(vec2 _pos1,
|
||||
vec2 _pos2,
|
||||
vec2 _pos3,
|
||||
vec2 _pos4,
|
||||
int32_t _level,
|
||||
enum PointRender::typePoint _type) {
|
||||
if (_level > m_recursionMax) {
|
||||
return;
|
||||
}
|
||||
vec2 pos12 = (_pos1+_pos2)*0.5f;
|
||||
vec2 pos23 = (_pos2+_pos3)*0.5f;
|
||||
vec2 pos34 = (_pos3+_pos4)*0.5f;
|
||||
|
||||
vec2 delta = _pos4 - _pos1;
|
||||
float distance2 = std::abs(((_pos2.x() - _pos4.x()) * delta.y() - (_pos2.y() - _pos4.y()) * delta.x() ));
|
||||
float distance3 = std::abs(((_pos3.x() - _pos4.x()) * delta.y() - (_pos3.y() - _pos4.y()) * delta.x() ));
|
||||
|
||||
if ((distance2 + distance3)*(distance2 + distance3) < m_threshold * delta.length2()) {
|
||||
m_listPoints.push_back(PointRender(_pos4, _type) );
|
||||
return;
|
||||
}
|
||||
vec2 pos123 = (pos12+pos23)*0.5f;
|
||||
vec2 pos234 = (pos23+pos34)*0.5f;
|
||||
vec2 pos1234 = (pos123+pos234)*0.5f;
|
||||
|
||||
flattenCubicBez(_pos1, pos12, pos123, pos1234, _level+1, PointRender::typePoint_interpolation);
|
||||
flattenCubicBez(pos1234, pos234, pos34, _pos4, _level+1, _type);
|
||||
}
|
||||
|
||||
void flattenShape(const esvg::RenderPath& _path, const mat2& _matrix) {
|
||||
// Flatten path
|
||||
m_listPoints.push_back(PointRender(_path.m_points[0], PointRender::typePoint_join));
|
||||
for (int32_t iii=0;
|
||||
iii<_path.m_points.size()-1;
|
||||
iii+=3) {
|
||||
flattenCubicBez(_path.m_points[iii+0], _path.m_points[iii+1], _path.m_points[iii+2], _path.m_points[iii+3], 0, PointRender::typePoint_interpolation);
|
||||
}
|
||||
// Close path (all time in a background element)
|
||||
m_listPoints.push_back(PointRender(_path.m_points[0], PointRender::typePoint_join));
|
||||
// Build Segments
|
||||
for (int32_t iii=0, jjj=m_listPoints.size()-1;
|
||||
iii < m_listPoints.size();
|
||||
jjj = iii++) {
|
||||
addSegment(m_listPoints[jjj], m_listPoints[iii]);
|
||||
}
|
||||
}
|
||||
|
||||
void flattenShapeStroke(const esvg::RenderPath& _path, const mat2& _matrix) {
|
||||
// Flatten path
|
||||
m_listPoints.push_back(PointRender(_path.m_points[0], PointRender::typePoint_start));
|
||||
for (int32_t iii=0;
|
||||
iii<_path.m_points.size()-1;
|
||||
iii+=3) {
|
||||
flattenCubicBez(_path.m_points[iii+0], _path.m_points[iii+1], _path.m_points[iii+2], _path.m_points[iii+3], 0, PointRender::typePoint_join);
|
||||
}
|
||||
// When we stroke , We need to have a minimum of 2 points:
|
||||
if (_path.m_points.size() < 2) {
|
||||
// no stroke ...
|
||||
return;
|
||||
}
|
||||
// generate for every point all the orthogonal elements
|
||||
// normal edge * end path
|
||||
// * | * * * * * * * * * * * * * *
|
||||
// * |<--*----this | *
|
||||
// * | * this -->| *
|
||||
// * * * | *
|
||||
// * . | . * . . . . . . . . * *
|
||||
// * . | . * | *
|
||||
// * A . | . B * | *
|
||||
// . * . | *
|
||||
// . * * . * * * * * * * * * * * * *
|
||||
// * *
|
||||
// * *
|
||||
// TODO : Start and stop of the path ...
|
||||
for (int32_t idPevious=-1, idCurrent=0, idNext=1;
|
||||
idCurrent < m_listPoints.size();
|
||||
idPevious++, idCurrent++, idNext++) {
|
||||
if ( m_listPoints[idCurrent].m_type == PointRender::typePoint_join
|
||||
|| m_listPoints[idCurrent].m_type == PointRender::typePoint_interpolation) {
|
||||
if (idPevious < 0 ) {
|
||||
SVG_ERROR("an error occure a previous ID is < 0.... ");
|
||||
continue;
|
||||
}
|
||||
if (idNext >= m_listPoints.size()) {
|
||||
SVG_ERROR("an error occure a next ID is >= nbPoint len .... ");
|
||||
continue;
|
||||
}
|
||||
vec2 vecA = m_listPoints[idCurrent].m_pos - m_listPoints[idPevious].m_pos;
|
||||
vecA.safeNormalize();
|
||||
vec2 vecB = m_listPoints[idNext].m_pos - m_listPoints[idCurrent].m_pos;
|
||||
vecB.safeNormalize();
|
||||
vec2 vecC = vecA - vecB;
|
||||
if (vecC == vec2(0,0)) {
|
||||
// special case: 1 line ...
|
||||
m_listPoints[idCurrent].m_miterAxe = vec2(vecA.y(), vecA.x());
|
||||
} else {
|
||||
vecC.safeNormalize();
|
||||
m_listPoints[idCurrent].m_miterAxe = vecC;
|
||||
}
|
||||
} else if (m_listPoints[idCurrent].m_type == PointRender::typePoint_start) {
|
||||
vec2 vecB = m_listPoints[idNext].m_pos - m_listPoints[idCurrent].m_pos;
|
||||
vecB.safeNormalize();
|
||||
m_listPoints[idCurrent].m_miterAxe = vec2(vecB.y(), vecB.x());
|
||||
} else if (m_listPoints[idCurrent].m_type == PointRender::typePoint_stop) {
|
||||
if (idPevious < 0 ) {
|
||||
SVG_ERROR("an error occure a previous ID is < 0.... ");
|
||||
continue;
|
||||
}
|
||||
vec2 vecA = m_listPoints[idCurrent].m_pos - m_listPoints[idPevious].m_pos;
|
||||
vecA.safeNormalize();
|
||||
m_listPoints[idCurrent].m_miterAxe = vec2(vecA.y(), vecA.x());
|
||||
} else {
|
||||
SVG_TODO("lklklklklkl");
|
||||
}
|
||||
}
|
||||
float lineWidth = 5.0f;
|
||||
// create segment list:
|
||||
bool haveStartLine;
|
||||
vec2 leftPoint;
|
||||
vec2 rightPoint;
|
||||
for (int32_t iii=0;
|
||||
iii < m_listPoints.size();
|
||||
++iii) {
|
||||
switch (m_listPoints[iii].m_type) {
|
||||
case PointRender::typePoint_single:
|
||||
// just do nothing ....
|
||||
SVG_VERBOSE("[" << iii << "] Find Single " << m_listPoints[iii].m_pos);
|
||||
break;
|
||||
case PointRender::typePoint_start:
|
||||
{
|
||||
SVG_VERBOSE("[" << iii << "] Find Start " << m_listPoints[iii].m_pos);
|
||||
if (haveStartLine == true) {
|
||||
// close previous :
|
||||
SVG_WARNING(" find a non close path ...");
|
||||
addSegment(leftPoint, rightPoint);
|
||||
}
|
||||
haveStartLine = true;
|
||||
// TODO : Calculate intersection ... (now we do a simple fast test of path display ...)
|
||||
leftPoint = m_listPoints[iii].m_pos
|
||||
+ m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
rightPoint = m_listPoints[iii].m_pos
|
||||
- m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
addSegment(leftPoint, rightPoint);
|
||||
SVG_VERBOSE(" segment :" << leftPoint << " -> " << rightPoint);
|
||||
}
|
||||
break;
|
||||
case PointRender::typePoint_stop:
|
||||
{
|
||||
SVG_VERBOSE("[" << iii << "] Find Stop " << m_listPoints[iii].m_pos);
|
||||
if (haveStartLine == true) {
|
||||
SVG_WARNING("find close path without start part ...");
|
||||
break;
|
||||
}
|
||||
haveStartLine = false;
|
||||
// TODO : Calculate intersection ... (now we do a simple fast test of path display ...)
|
||||
vec2 left = m_listPoints[iii].m_pos
|
||||
+ m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
vec2 right = m_listPoints[iii].m_pos
|
||||
- m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint, left);
|
||||
SVG_VERBOSE(" segment :" << leftPoint << " -> " << left);
|
||||
addSegment(right, rightPoint);
|
||||
SVG_VERBOSE(" segment :" << right << " -> " << rightPoint);
|
||||
leftPoint = left;
|
||||
rightPoint = right;
|
||||
// end line ...
|
||||
addSegment(rightPoint, leftPoint);
|
||||
SVG_VERBOSE(" segment :" << rightPoint << " -> " << leftPoint);
|
||||
}
|
||||
break;
|
||||
case PointRender::typePoint_interpolation:
|
||||
{
|
||||
SVG_VERBOSE("[" << iii << "] Find interpolation " << m_listPoints[iii].m_pos);
|
||||
// TODO : Calculate intersection ... (now we do a simple fast test of path display ...)
|
||||
vec2 left = m_listPoints[iii].m_pos
|
||||
+ m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
vec2 right = m_listPoints[iii].m_pos
|
||||
- m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint, left);
|
||||
SVG_VERBOSE(" segment :" << leftPoint << " -> " << left);
|
||||
addSegment(right, rightPoint);
|
||||
SVG_VERBOSE(" segment :" << right << " -> " << rightPoint);
|
||||
leftPoint = left;
|
||||
rightPoint = right;
|
||||
}
|
||||
break;
|
||||
case PointRender::typePoint_join:
|
||||
{
|
||||
SVG_VERBOSE("[" << iii << "] Find Join " << m_listPoints[iii].m_pos);
|
||||
// TODO : Calculate intersection ... (now we do a simple fast test of path display ...)
|
||||
vec2 left = m_listPoints[iii].m_pos
|
||||
+ m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
vec2 right = m_listPoints[iii].m_pos
|
||||
- m_listPoints[iii].m_miterAxe*lineWidth*0.5f;
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint, left);
|
||||
SVG_VERBOSE(" segment :" << leftPoint << " -> " << left);
|
||||
addSegment(right, rightPoint);
|
||||
SVG_VERBOSE(" segment :" << right << " -> " << rightPoint);
|
||||
leftPoint = left;
|
||||
rightPoint = right;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sortSegment() {
|
||||
std::sort(m_listSegment.begin(), m_listSegment.end(), sortSegmentFunction);
|
||||
}
|
||||
Weighter createWeighter(ivec2 _size) {
|
||||
Weighter out(_size);
|
||||
// for each lines:
|
||||
for (int32_t yyy=0; yyy<_size.y(); ++yyy) {
|
||||
// Reduce the number of lines in the subsampling parsing:
|
||||
std::vector<Segment> availlableSegmentPixel;
|
||||
for (auto &it : m_listSegment) {
|
||||
if ( it.p0.y() <= float(yyy+1)
|
||||
&& it.p1.y() >= float(yyy)) {
|
||||
availlableSegmentPixel.push_back(it);
|
||||
}
|
||||
}
|
||||
// This represent the pondaration on the subSampling
|
||||
float deltaSize = 1.0f/m_subSamplingCount;
|
||||
for (int32_t kkk=0; kkk<m_subSamplingCount ; ++kkk) {
|
||||
Scanline scanline(_size.x());
|
||||
//find all the segment that cross the middle of the line of the center of the pixel line:
|
||||
float subSamplingCenterPos = yyy + deltaSize*0.5f + deltaSize*kkk;
|
||||
std::vector<Segment> availlableSegment;
|
||||
// find in the subList ...
|
||||
for (auto &it : availlableSegmentPixel) {
|
||||
if ( it.p0.y() <= subSamplingCenterPos
|
||||
&& it.p1.y() >= subSamplingCenterPos) {
|
||||
availlableSegment.push_back(it);
|
||||
}
|
||||
}
|
||||
// x position, angle
|
||||
std::vector<std::pair<float, float>> listPosition;
|
||||
for (auto &it : availlableSegment) {
|
||||
vec2 delta = it.p0 - it.p1;
|
||||
// x = coefficent*y+bbb;
|
||||
float coefficient = delta.x()/delta.y();
|
||||
float bbb = it.p0.x() - coefficient*it.p0.y();
|
||||
float xpos = coefficient * subSamplingCenterPos + bbb;
|
||||
listPosition.push_back(std::pair<float,float>(xpos, it.direction));
|
||||
}
|
||||
// now we order position of the xPosition:
|
||||
std::sort(listPosition.begin(), listPosition.end(), sortXPosFunction);
|
||||
// move through all element in the point:
|
||||
float lastState = 0.0f;
|
||||
float currentValue = 0.0f;
|
||||
int32_t lastPos = -1;
|
||||
int32_t currentPos = -1;
|
||||
float lastX = 0.0f;
|
||||
// * | \---------------/ |
|
||||
// * current pos
|
||||
// * pos ...
|
||||
// TODO : Code the Odd/even and non-zero ...
|
||||
for (auto &it : listPosition) {
|
||||
if (currentPos != int32_t(it.first)) {
|
||||
// fill to the new pos -1:
|
||||
float endValue = std::min(1.0f,std::abs(lastState)) * deltaSize;
|
||||
for (int32_t iii=currentPos+1; iii<int32_t(it.first); ++iii) {
|
||||
scanline.set(iii, endValue);
|
||||
}
|
||||
currentPos = int32_t(it.first);
|
||||
currentValue = endValue;
|
||||
}
|
||||
float oldState = lastState;
|
||||
lastState += it.second;
|
||||
if (oldState == 0.0f) {
|
||||
// nothing to draw before ...
|
||||
float ratio = 1.0f - (it.first - float(int32_t(it.first)));
|
||||
currentValue += ratio * deltaSize;
|
||||
} else if (lastState == 0.0f) {
|
||||
// something new to draw ...
|
||||
float ratio = 1.0f - (it.first - float(int32_t(it.first)));
|
||||
currentValue -= ratio * deltaSize;
|
||||
} else {
|
||||
// nothing to do ...
|
||||
}
|
||||
|
||||
if (currentPos == int32_t(it.first)) {
|
||||
scanline.set(currentPos, currentValue);
|
||||
}
|
||||
}
|
||||
out.append(yyy, scanline);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void esvg::Path::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Path");
|
||||
esvg::RenderPath path;
|
||||
path.clear();
|
||||
for(int32_t iii=0; iii<m_listElement.size(); iii++) {
|
||||
switch (m_listElement[iii].m_cmd) {
|
||||
case esvg::pathStop:
|
||||
abstractCloseSubpath(path);
|
||||
case esvg::path_stop:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_stop");
|
||||
path.stop();
|
||||
break;
|
||||
case esvg::pathMoveTo:
|
||||
abstractMoveTo(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1] );
|
||||
case esvg::path_moveTo:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_moveTo");
|
||||
path.moveTo(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1]) );
|
||||
break;
|
||||
case esvg::pathLineTo:
|
||||
abstractLineTo(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1] );
|
||||
case esvg::path_lineTo:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_lineTo");
|
||||
path.lineTo(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1]) );
|
||||
break;
|
||||
case esvg::pathLineToH:
|
||||
abstractHLineTo(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0] );
|
||||
case esvg::path_lineToH:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_lineToH");
|
||||
path.lineTo(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0], 0.0f) );
|
||||
break;
|
||||
case esvg::pathLineToV:
|
||||
abstractVLineTo(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0] );
|
||||
case esvg::path_lineToV:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_lineToV");
|
||||
path.lineTo(m_listElement[iii].m_relative,
|
||||
vec2(0.0f, m_listElement[iii].m_element[0]) );
|
||||
break;
|
||||
case esvg::pathCurveTo:
|
||||
abstractCurve4(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1],
|
||||
m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3],
|
||||
m_listElement[iii].m_element[4],
|
||||
m_listElement[iii].m_element[5] );
|
||||
//SVG_INFO(" draw : esvg::pathCurveTo");
|
||||
case esvg::path_curveTo:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_curveTo");
|
||||
path.curve4To(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1]),
|
||||
vec2(m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3]),
|
||||
vec2(m_listElement[iii].m_element[4],
|
||||
m_listElement[iii].m_element[5]) );
|
||||
break;
|
||||
case esvg::pathSmothCurveTo:
|
||||
abstractCurve4(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1],
|
||||
m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3] );
|
||||
//SVG_INFO(" draw : esvg::pathSmothCurveTo");
|
||||
case esvg::path_smothCurveTo:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_smothCurveTo");
|
||||
path.curve4SmoothTo(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1]),
|
||||
vec2(m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3]) );
|
||||
break;
|
||||
case esvg::pathBesizeCurveTo:
|
||||
abstractCurve3(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1],
|
||||
m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3] );
|
||||
//SVG_INFO(" draw : esvg::pathBesizeCurveTo");
|
||||
case esvg::path_bezierCurveTo:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_bezierCurveTo");
|
||||
path.curve3To(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1]),
|
||||
vec2(m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3]) );
|
||||
break;
|
||||
case esvg::pathBesizeSmothCurveTo:
|
||||
abstractCurve3(path, m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1] );
|
||||
//SVG_INFO(" draw : esvg::pathBesizeSmothCurveTo");
|
||||
case esvg::path_bezierSmothCurveTo:
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_bezierSmothCurveTo");
|
||||
path.curve3SmoothTo(m_listElement[iii].m_relative,
|
||||
vec2(m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1]) );
|
||||
break;
|
||||
case esvg::pathElliptic:
|
||||
SVG_TODO("Elliptic arc is not implemented NOW ...");
|
||||
case esvg::path_elliptic:
|
||||
/*
|
||||
SVG_VERBOSE(spacingDist(_level+1) << "Draw : esvg::path_elliptic");
|
||||
path.ellipticTo(m_listElement[iii].m_relative,
|
||||
m_listElement[iii].m_element[0],
|
||||
m_listElement[iii].m_element[1],
|
||||
m_listElement[iii].m_element[2],
|
||||
m_listElement[iii].m_element[3],
|
||||
m_listElement[iii].m_element[4],
|
||||
m_listElement[iii].m_element[5],
|
||||
m_listElement[iii].m_element[6] );
|
||||
*/
|
||||
SVG_TODO(spacingDist(_level+1) << "Draw : esvg::path_elliptic");
|
||||
break;
|
||||
default:
|
||||
SVG_ERROR("Unknow PATH commant (internal error)");
|
||||
@ -403,102 +894,49 @@ void esvg::Path::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicT
|
||||
}
|
||||
}
|
||||
|
||||
agg::trans_affine mtx = m_transformMatrix;
|
||||
mat2 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
agg::conv_curve<agg::path_storage> curve(path);
|
||||
if (m_paint.fill.a != 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);
|
||||
path.display();
|
||||
Weighter tmpFill;
|
||||
Weighter tmpStroke;
|
||||
//agg::conv_curve<esvg::RenderPath> curve(path);
|
||||
// Check if we need to display background
|
||||
if (m_paint.fill.a() != 0x00) {
|
||||
Transformation ttt;
|
||||
ttt.flattenShape(path, mtx);
|
||||
// Rasterize Segments
|
||||
ttt.sortSegment();
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill = ttt.createWeighter(ivec2(128,128));
|
||||
}
|
||||
if (m_paint.strokeWidth > 0 && m_paint.stroke.a!=0x00 ) {
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.r, m_paint.stroke.g, m_paint.stroke.b, m_paint.stroke.a));
|
||||
// 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);
|
||||
// check if we need to display stroke:
|
||||
if ( m_paint.strokeWidth > 0
|
||||
&& m_paint.stroke.a() != 0x00) {
|
||||
Transformation ttt;
|
||||
ttt.flattenShapeStroke(path, mtx);
|
||||
// Rasterize Segments
|
||||
ttt.sortSegment();
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpStroke = ttt.createWeighter(ivec2(128,128));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esvg::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 esvg::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 esvg::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;
|
||||
// add on images:
|
||||
for (int32_t yyy=0; yyy<_myRenderer.m_size.y(); ++yyy) {
|
||||
for (int32_t xxx=0; xxx<_myRenderer.m_size.x(); ++xxx) {
|
||||
ivec2 pos(xxx, yyy);
|
||||
float value = tmpFill.get(pos);
|
||||
float valueStroke = tmpStroke.get(pos);
|
||||
if (valueStroke != 0.0f) {
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 ] = uint8_t(valueStroke*m_paint.stroke.r());
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 + 1] = uint8_t(valueStroke*m_paint.stroke.g());
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 + 2] = uint8_t(valueStroke*m_paint.stroke.b());
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 + 3] = uint8_t(valueStroke*m_paint.stroke.a());
|
||||
} else {
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 ] = uint8_t(value*m_paint.fill.r());
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 + 1] = uint8_t(value*m_paint.fill.g());
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 + 2] = uint8_t(value*m_paint.fill.b());
|
||||
_myRenderer.m_buffer[(_myRenderer.m_size.x()*yyy + xxx)*4 + 3] = uint8_t(value*m_paint.fill.a());
|
||||
}
|
||||
}
|
||||
_path.line_to(_x, y2);
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::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 esvg::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 esvg::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 esvg::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 esvg::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 esvg::Path::abstractCloseSubpath(agg::path_storage& _path) {
|
||||
_path.end_poly(agg::path_flags_close);
|
||||
}
|
||||
|
46
esvg/Path.h
46
esvg/Path.h
@ -10,24 +10,24 @@
|
||||
#define __ESVG_PATH_H__
|
||||
|
||||
#include <esvg/Base.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
#include <esvg/RenderPath.h>
|
||||
|
||||
namespace esvg {
|
||||
enum pathProperty{
|
||||
pathStop,
|
||||
pathMoveTo,
|
||||
pathLineTo,
|
||||
pathLineToH,
|
||||
pathLineToV,
|
||||
pathCurveTo,
|
||||
pathSmothCurveTo,
|
||||
pathBesizeCurveTo,
|
||||
pathBesizeSmothCurveTo,
|
||||
pathElliptic
|
||||
path_stop,
|
||||
path_moveTo,
|
||||
path_lineTo,
|
||||
path_lineToH,
|
||||
path_lineToV,
|
||||
path_curveTo,
|
||||
path_smothCurveTo,
|
||||
path_bezierCurveTo,
|
||||
path_bezierSmothCurveTo,
|
||||
path_elliptic
|
||||
};
|
||||
class PathBasic {
|
||||
public:
|
||||
PathBasic() : m_cmd(esvg::pathStop), m_relative(false) {
|
||||
PathBasic() : m_cmd(esvg::path_stop), m_relative(false) {
|
||||
for(int32_t iii=0; iii<7; ++iii) {
|
||||
m_element[iii] = 0;
|
||||
}
|
||||
@ -42,19 +42,19 @@ namespace esvg {
|
||||
public:
|
||||
Path(PaintState _parentPaintState);
|
||||
~Path();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
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);
|
||||
void abstractMoveTo(esvg::RenderPath& _path, bool _rel, double _x, double _y);
|
||||
void abstractLineTo(esvg::RenderPath& _path, bool _rel, double _x, double _y);
|
||||
void abstractHLineTo(esvg::RenderPath& _path, bool _rel, double _x);
|
||||
void abstractVLineTo(esvg::RenderPath& _path, bool _rel, double _y);
|
||||
void abstractCurve3(esvg::RenderPath& _path, bool _rel, double _x1, double _y1, double _x, double _y);
|
||||
void abstractCurve3(esvg::RenderPath& _path, bool _rel, double _x, double _y);
|
||||
void abstractCurve4(esvg::RenderPath& _path, bool _rel, double _x1, double _y1, double _x2, double _y2, double _x, double _y);
|
||||
void abstractCurve4(esvg::RenderPath& _path, bool _rel, double _x2, double _y2, double _x, double _y);
|
||||
void abstractCloseSubpath(esvg::RenderPath& _path);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Polygon.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Polygon"
|
||||
@ -22,19 +20,19 @@ esvg::Polygon::~Polygon() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Polygon::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Polygon::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element == nullptr) {
|
||||
return false;
|
||||
}
|
||||
parseTransform(_element);
|
||||
parsePaintAttr(_element);
|
||||
|
||||
SVG_VERBOSE("parsed P1. trans : (" << m_transformMatrix.sx << "," << m_transformMatrix.shy << "," << m_transformMatrix.shx << "," << m_transformMatrix.sy << "," << m_transformMatrix.tx << "," << m_transformMatrix.ty << ")");
|
||||
SVG_VERBOSE("parsed P1. trans: " << m_transformMatrix);
|
||||
|
||||
// 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 << ")");
|
||||
SVG_VERBOSE("parsed P2. trans: " << m_transformMatrix);
|
||||
|
||||
const std::string sss1 = _element->getAttribute("points");
|
||||
if (sss1.size() == 0) {
|
||||
@ -66,10 +64,13 @@ void esvg::Polygon::display(int32_t _spacing) {
|
||||
SVG_DEBUG(spacingDist(_spacing) << "Polygon nbPoint=" << m_listPoint.size());
|
||||
}
|
||||
|
||||
void esvg::Polygon::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) {
|
||||
void esvg::Polygon::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Polygon");
|
||||
|
||||
#if 0
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.r, m_paint.fill.g, m_paint.fill.b, m_paint.fill.a));
|
||||
|
||||
agg::path_storage path;
|
||||
esvg::RenderPath path;
|
||||
path.start_new_path();
|
||||
|
||||
path.move_to(m_listPoint[0].x(), m_listPoint[0].y());
|
||||
@ -78,7 +79,7 @@ void esvg::Polygon::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _bas
|
||||
}
|
||||
path.close_polygon();
|
||||
/*
|
||||
// configure the end of the line :
|
||||
// configure the end of the line:
|
||||
switch (m_paint.lineCap) {
|
||||
case esvg::LINECAP_SQUARE:
|
||||
path.line_cap(agg::square_cap);
|
||||
@ -103,11 +104,11 @@ void esvg::Polygon::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _bas
|
||||
}
|
||||
*/
|
||||
|
||||
agg::trans_affine mtx = m_transformMatrix;
|
||||
mat2 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
if (m_paint.fill.a != 0x00) {
|
||||
agg::conv_transform<agg::path_storage, agg::trans_affine> trans(path, mtx);
|
||||
agg::conv_transform<esvg::RenderPath, mat2> 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);
|
||||
@ -117,13 +118,14 @@ void esvg::Polygon::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _bas
|
||||
if (m_paint.strokeWidth > 0 && m_paint.stroke.a!=0x00 ) {
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.r, m_paint.stroke.g, m_paint.stroke.b, m_paint.stroke.a));
|
||||
// drawing as an outline
|
||||
agg::conv_stroke<agg::path_storage> myPolygonStroke(path);
|
||||
agg::conv_stroke<esvg::RenderPath> myPolygonStroke(path);
|
||||
myPolygonStroke.width(m_paint.strokeWidth);
|
||||
agg::conv_transform<agg::conv_stroke<agg::path_storage>, agg::trans_affine> transStroke(myPolygonStroke, mtx);
|
||||
agg::conv_transform<agg::conv_stroke<esvg::RenderPath>, mat2> 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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -21,14 +21,14 @@ namespace esvg {
|
||||
*/
|
||||
class Polygon : public esvg::Base {
|
||||
private:
|
||||
std::vector<etk::Vector2D<float> > m_listPoint; //!< list of all point of the polygone
|
||||
std::vector<vec2 > m_listPoint; //!< list of all point of the polygone
|
||||
//enum esvg::polygonMode m_diplayMode; //!< polygone specific display mode
|
||||
public:
|
||||
Polygon(PaintState parentPaintState);
|
||||
~Polygon();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& parentTrans, etk::Vector2D<float>& sizeMax);
|
||||
virtual void display(int32_t spacing);
|
||||
virtual void aggDraw(esvg::Renderer& myRenderer, agg::trans_affine& basicTrans);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Polyline.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
|
||||
esvg::Polyline::Polyline(PaintState _parentPaintState) : esvg::Base(_parentPaintState) {
|
||||
|
||||
@ -19,7 +17,7 @@ esvg::Polyline::~Polyline() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Polyline::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Polyline::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
// line must have a minimum size...
|
||||
m_paint.strokeWidth = 1;
|
||||
if (_element == nullptr) {
|
||||
@ -40,7 +38,7 @@ bool esvg::Polyline::parse(const std::shared_ptr<exml::Element>& _element, agg::
|
||||
SVG_VERBOSE("Parse polyline : \"" << sss1 << "\"");
|
||||
const char* sss = sss1.c_str();
|
||||
while ('\0' != sss[0]) {
|
||||
etk::Vector2D<float> pos;
|
||||
vec2 pos;
|
||||
int32_t n;
|
||||
if (sscanf(sss, "%f,%f %n", &pos.m_floats[0], &pos.m_floats[1], &n) == 2) {
|
||||
m_listPoint.push_back(pos);
|
||||
@ -59,8 +57,12 @@ void esvg::Polyline::display(int32_t _spacing) {
|
||||
}
|
||||
|
||||
|
||||
void esvg::Polyline::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) {
|
||||
agg::path_storage path;
|
||||
void esvg::Polyline::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Polyline");
|
||||
|
||||
|
||||
#if 0
|
||||
esvg::RenderPath 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++) {
|
||||
@ -92,20 +94,21 @@ void esvg::Polyline::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _ba
|
||||
}
|
||||
*/
|
||||
|
||||
agg::trans_affine mtx = m_transformMatrix;
|
||||
mat2 mtx = m_transformMatrix;
|
||||
mtx *= _basicTrans;
|
||||
|
||||
if (m_paint.strokeWidth > 0) {
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.stroke.r, m_paint.stroke.g, m_paint.stroke.b, m_paint.stroke.a));
|
||||
// drawing as an outline
|
||||
agg::conv_stroke<agg::path_storage> myPolygonStroke(path);
|
||||
agg::conv_stroke<esvg::RenderPath> myPolygonStroke(path);
|
||||
myPolygonStroke.width(m_paint.strokeWidth);
|
||||
agg::conv_transform<agg::conv_stroke<agg::path_storage>, agg::trans_affine> transStroke(myPolygonStroke, mtx);
|
||||
agg::conv_transform<agg::conv_stroke<esvg::RenderPath>, mat2> 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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,13 +15,13 @@
|
||||
namespace esvg {
|
||||
class Polyline : public esvg::Base {
|
||||
private:
|
||||
std::vector<etk::Vector2D<float> > m_listPoint; //!< list of all point of the polyline
|
||||
std::vector<vec2 > m_listPoint; //!< list of all point of the polyline
|
||||
public:
|
||||
Polyline(PaintState _parentPaintState);
|
||||
~Polyline();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/Rectangle.h>
|
||||
#include <agg/agg_rounded_rect.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Rectangle"
|
||||
@ -25,7 +23,7 @@ esvg::Rectangle::~Rectangle() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Rectangle::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Rectangle::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
if (_element == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -58,19 +56,22 @@ void esvg::Rectangle::display(int32_t _spacing) {
|
||||
SVG_DEBUG(spacingDist(_spacing) << "Rectangle : pos=" << m_position << " size=" << m_size << " corner=" << m_roundedCorner);
|
||||
}
|
||||
|
||||
void esvg::Rectangle::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans) {
|
||||
void esvg::Rectangle::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Rectangle");
|
||||
|
||||
#if 0
|
||||
_myRenderer.m_renderArea->color(agg::rgba8(m_paint.fill.r, m_paint.fill.g, m_paint.fill.b, m_paint.fill.a));
|
||||
// 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;
|
||||
mat2 mtx = m_transformMatrix;
|
||||
// herited modifications ...
|
||||
mtx *= _basicTrans;
|
||||
|
||||
if (m_paint.fill.a != 0x00) {
|
||||
agg::conv_transform<agg::rounded_rect, agg::trans_affine> trans(rect_r, mtx);
|
||||
agg::conv_transform<agg::rounded_rect, mat2> 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);
|
||||
@ -84,10 +85,10 @@ void esvg::Rectangle::aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _b
|
||||
// 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);
|
||||
agg::conv_transform<agg::conv_stroke<agg::rounded_rect>, mat2> transStroke(rect_p, mtx);
|
||||
_myRenderer.m_rasterizer.add_path(transStroke);
|
||||
agg::render_scanlines(_myRenderer.m_rasterizer, _myRenderer.m_scanLine, *_myRenderer.m_renderArea);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -14,15 +14,15 @@
|
||||
namespace esvg {
|
||||
class Rectangle : public esvg::Base {
|
||||
private:
|
||||
etk::Vector2D<float> m_position; //!< position of the rectangle
|
||||
etk::Vector2D<float> m_size; //!< size of the rectangle
|
||||
etk::Vector2D<float> m_roundedCorner; //!< property of the rounded corner
|
||||
vec2 m_position; //!< position of the rectangle
|
||||
vec2 m_size; //!< size of the rectangle
|
||||
vec2 m_roundedCorner; //!< property of the rounded corner
|
||||
public:
|
||||
Rectangle(PaintState _parentPaintState);
|
||||
~Rectangle();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level);
|
||||
};
|
||||
};
|
||||
|
||||
|
103
esvg/RenderPath.cpp
Normal file
103
esvg/RenderPath.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#include <esvg/debug.h>
|
||||
#include <esvg/RenderPath.h>
|
||||
|
||||
void esvg::RenderPath::clear() {
|
||||
m_points.clear();
|
||||
}
|
||||
|
||||
void esvg::RenderPath::stop() {
|
||||
SVG_TODO("Must be implemented");
|
||||
}
|
||||
|
||||
void esvg::RenderPath::addPoint(const vec2& _pos) {
|
||||
m_points.push_back(_pos);
|
||||
}
|
||||
|
||||
void esvg::RenderPath::moveTo(bool _relative, vec2 _pos) {
|
||||
if(_relative == true) {
|
||||
_pos = relativeToAbsolute(_pos);
|
||||
}
|
||||
if (m_points.size() > 0) {
|
||||
m_points.back() = _pos;
|
||||
} else {
|
||||
addPoint(_pos);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 esvg::RenderPath::relativeToAbsolute(const vec2& _value) {
|
||||
vec2 out(_value);
|
||||
if (m_points.size() > 0) {
|
||||
out += m_points.back();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void esvg::RenderPath::lineTo(bool _relative, vec2 _pos) {
|
||||
if(_relative == true) {
|
||||
_pos = relativeToAbsolute(_pos);
|
||||
}
|
||||
vec2 pos;
|
||||
vec2 delta;
|
||||
if (m_points.size() > 0) {
|
||||
vec2 oldPos = m_points.back();
|
||||
vec2 delta = _pos - oldPos;
|
||||
// create a basic bezier curve ...
|
||||
addPoint(oldPos + delta*0.3333f);
|
||||
addPoint(oldPos - delta*0.3333f);
|
||||
addPoint(_pos);
|
||||
} else {
|
||||
SVG_ERROR("try to lineTo whith no previous point ...");
|
||||
}
|
||||
}
|
||||
|
||||
void esvg::RenderPath::curve3SmoothTo(bool _relative, vec2 _pos) {
|
||||
if(_relative == true) {
|
||||
_pos = relativeToAbsolute(_pos);
|
||||
}
|
||||
SVG_TODO("later ...");
|
||||
}
|
||||
|
||||
void esvg::RenderPath::curve3To(bool _relative, vec2 _pos1, vec2 _pos) {
|
||||
if(_relative == true) {
|
||||
_pos1 = relativeToAbsolute(_pos1);
|
||||
_pos = relativeToAbsolute(_pos);
|
||||
}
|
||||
SVG_TODO("later ...");
|
||||
}
|
||||
|
||||
void esvg::RenderPath::curve4SmoothTo(bool _relative, vec2 _pos2, vec2 _pos) {
|
||||
if(_relative == true) {
|
||||
_pos2 = relativeToAbsolute(_pos2);
|
||||
_pos = relativeToAbsolute(_pos);
|
||||
}
|
||||
SVG_TODO("later ...");
|
||||
}
|
||||
|
||||
void esvg::RenderPath::curve4To(bool _relative, vec2 _pos1, vec2 _pos2, vec2 _pos) {
|
||||
if(_relative == true) {
|
||||
_pos1 = relativeToAbsolute(_pos1);
|
||||
_pos2 = relativeToAbsolute(_pos2);
|
||||
_pos = relativeToAbsolute(_pos);
|
||||
}
|
||||
addPoint(_pos1);
|
||||
addPoint(_pos2);
|
||||
addPoint(_pos);
|
||||
}
|
||||
|
||||
void esvg::RenderPath::display() {
|
||||
SVG_VERBOSE("PATH : ");
|
||||
for (uint32_t iii=0; iii<m_points.size()-1; iii+=3) {
|
||||
SVG_VERBOSE(" point: " << m_points[iii]);
|
||||
SVG_VERBOSE(" v: " << m_points[iii+1]);
|
||||
SVG_VERBOSE(" v: " << m_points[iii+2]);
|
||||
}
|
||||
SVG_VERBOSE(" point: " << m_points.back());
|
||||
}
|
||||
|
45
esvg/RenderPath.h
Normal file
45
esvg/RenderPath.h
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ESVG_RENDERER_PATH_H__
|
||||
#define __ESVG_RENDERER_PATH_H__
|
||||
|
||||
#include <etk/types.h>
|
||||
#include <etk/math/Vector2D.h>
|
||||
|
||||
|
||||
namespace esvg {
|
||||
class RenderPath {
|
||||
public:
|
||||
std::vector<vec2> m_points;
|
||||
public:
|
||||
RenderPath() {
|
||||
|
||||
}
|
||||
|
||||
~RenderPath() {
|
||||
|
||||
}
|
||||
void clear();
|
||||
void stop();
|
||||
void addPoint(const vec2& _pos);
|
||||
|
||||
void moveTo(bool _relative, vec2 _pos);
|
||||
void lineTo(bool _relative, vec2 _pos);
|
||||
void curve4To(bool _relative, vec2 _pos1, vec2 _pos2, vec2 _pos);
|
||||
void curve4SmoothTo(bool _relative, vec2 _pos2, vec2 _pos);
|
||||
void curve3To(bool _relative, vec2 _pos1, vec2 _pos);
|
||||
void curve3SmoothTo(bool _relative, vec2 _pos);
|
||||
//void ellipticTo(bool _relative, 7 values ...);
|
||||
|
||||
vec2 relativeToAbsolute(const vec2& _value);
|
||||
void display();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -15,68 +15,138 @@
|
||||
#undef __class__
|
||||
#define __class__ "Renderer"
|
||||
|
||||
esvg::Renderer::Renderer(uint32_t width, uint32_t height) {
|
||||
m_allocatedSize = 0;
|
||||
m_size.setValue(width, height);
|
||||
|
||||
int32_t dataSize = ((int32_t)width * (int32_t)height * DATA_ALLOCATION_ELEMENT);
|
||||
m_allocatedSize = dataSize;
|
||||
|
||||
// allocate Data
|
||||
SVG_VERBOSE("Allocate buffer : " << dataSize);
|
||||
|
||||
m_buffer = new uint8_t[dataSize];
|
||||
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);
|
||||
esvg::Renderer::Renderer(const ivec2& _size) {
|
||||
m_size = _size;
|
||||
m_stride = DATA_ALLOCATION_ELEMENT;
|
||||
m_scanline.resize(m_size.x() * m_stride, 0);
|
||||
m_buffer.resize(m_size.x() * m_size.y() * m_stride, 0);
|
||||
}
|
||||
|
||||
esvg::Renderer::~Renderer() {
|
||||
if (NULL != m_buffer) {
|
||||
delete[] m_buffer;
|
||||
m_buffer = NULL;
|
||||
}
|
||||
m_buffer.clear();
|
||||
m_scanline.clear();
|
||||
m_stride = 0;
|
||||
m_size = ivec2(0,0);
|
||||
}
|
||||
|
||||
/*
|
||||
void nsvgRasterize(NSVGrasterizer* rrr, // this
|
||||
NSVGimage* image, // image definition
|
||||
float tx, // move x
|
||||
float ty, // move y
|
||||
float scale, // scale
|
||||
unsigned char* dst, //output image data
|
||||
int w, // output width
|
||||
int h, // output height
|
||||
int stride) // pixel stride
|
||||
{
|
||||
NSVGshape *shape = NULL;
|
||||
NSVGedge *eee = NULL;
|
||||
NSVGcachedPaint cache;
|
||||
int i;
|
||||
|
||||
rrr->bitmap = dst;
|
||||
rrr->width = w;
|
||||
rrr->height = h;
|
||||
rrr->stride = stride;
|
||||
|
||||
if (w > rrr->cscanline) {
|
||||
rrr->cscanline = w;
|
||||
rrr->scanline = (unsigned char*)realloc(rrr->scanline, w);
|
||||
if (rrr->scanline == NULL) return;
|
||||
}
|
||||
|
||||
for (i = 0; i < h; i++)
|
||||
memset(&dst[i*stride], 0, w*4);
|
||||
|
||||
for (shape = image->shapes;
|
||||
shape != NULL;
|
||||
shape = shape->next) {
|
||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE))
|
||||
continue;
|
||||
// ***********************
|
||||
// *** render "fill" *****
|
||||
// ***********************
|
||||
if (shape->fill.type != NSVG_PAINT_NONE) {
|
||||
nsvg__resetPool(rrr);
|
||||
rrr->freelist = NULL;
|
||||
rrr->nedges = 0;
|
||||
nsvg__flattenShape(rrr, shape, scale);
|
||||
// Scale and translate edges
|
||||
for (i = 0; i < r->nedges; i++) {
|
||||
eee = &rrr->edges[i];
|
||||
eee->x0 = tx + eee->x0;
|
||||
eee->y0 = (ty + eee->y0) * NSVG__SUBSAMPLES;
|
||||
eee->x1 = tx + eee->x1;
|
||||
eee->y1 = (ty + eee->y1) * NSVG__SUBSAMPLES;
|
||||
}
|
||||
// Rasterize edges
|
||||
qsort(rrr->edges,
|
||||
rrr->nedges,
|
||||
sizeof(NSVGedge),
|
||||
nsvg__cmpEdge);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
nsvg__initPaint(&cache,
|
||||
&shape->fill,
|
||||
shape->opacity);
|
||||
nsvg__rasterizeSortedEdges(rrr,
|
||||
tx,
|
||||
ty,
|
||||
scale,
|
||||
&cache,
|
||||
shape->fillRule);
|
||||
}
|
||||
// *************************
|
||||
// *** render "stroke" *****
|
||||
// *************************
|
||||
if ( shape->stroke.type != NSVG_PAINT_NONE
|
||||
&& (shape->strokeWidth * scale) > 0.01f) {
|
||||
nsvg__resetPool(r);
|
||||
rrr->freelist = NULL;
|
||||
rrr->nedges = 0;
|
||||
nsvg__flattenShapeStroke(rrr, shape, scale);
|
||||
// dumpEdges(r, "edge.svg");
|
||||
// Scale and translate edges
|
||||
for (i = 0; i < rrr->nedges; i++) {
|
||||
eee = &rrr->edges[i];
|
||||
eee->x0 = tx + eee->x0;
|
||||
eee->y0 = (ty + eee->y0) * NSVG__SUBSAMPLES;
|
||||
eee->x1 = tx + eee->x1;
|
||||
eee->y1 = (ty + eee->y1) * NSVG__SUBSAMPLES;
|
||||
}
|
||||
// Rasterize edges
|
||||
qsort(rrr->edges,
|
||||
rrr->nedges,
|
||||
sizeof(NSVGedge),
|
||||
nsvg__cmpEdge);
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
nsvg__initPaint(&cache,
|
||||
&shape->stroke,
|
||||
shape->opacity);
|
||||
nsvg__rasterizeSortedEdges(rrr,
|
||||
tx,
|
||||
ty,
|
||||
scale,
|
||||
&cache,
|
||||
NSVG_FILLRULE_NONZERO);
|
||||
}
|
||||
}
|
||||
nsvg__unpremultiplyAlpha(dst,
|
||||
w,
|
||||
h,
|
||||
stride);
|
||||
rrr->bitmap = NULL;
|
||||
rrr->width = 0;
|
||||
rrr->height = 0;
|
||||
rrr->stride = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Writing the buffer to a .PPM file, assuming it has
|
||||
// RGB-structure, one byte per color component
|
||||
//--------------------------------------------------
|
||||
void esvg::Renderer::writePpm(std::string fileName) {
|
||||
if (NULL == m_buffer) {
|
||||
if (m_buffer.size() == 0) {
|
||||
return;
|
||||
}
|
||||
FILE* fd = fopen(fileName.c_str(), "wb");
|
||||
@ -86,10 +156,12 @@ void esvg::Renderer::writePpm(std::string fileName) {
|
||||
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);
|
||||
fwrite(&m_buffer[iii*DATA_ALLOCATION_ELEMENT], 1, 3, fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -11,63 +11,26 @@
|
||||
|
||||
#include <etk/types.h>
|
||||
#include <etk/math/Vector2D.h>
|
||||
#include <draw/Color.h>
|
||||
|
||||
#include <agg/agg_basics.h>
|
||||
#include <agg/agg_rendering_buffer.h>
|
||||
#include <agg/agg_rasterizer_scanline_aa.h>
|
||||
#include <agg/agg_scanline_p.h>
|
||||
#include <agg/agg_renderer_scanline.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
#include <agg/agg_conv_transform.h>
|
||||
#include <agg/agg_bounding_rect.h>
|
||||
#include <agg/agg_color_rgba.h>
|
||||
#include <agg/agg_pixfmt_rgba.h>
|
||||
#include <etk/Color.h>
|
||||
|
||||
namespace esvg {
|
||||
enum lineCap{
|
||||
lineCapButt,
|
||||
lineCapRound,
|
||||
lineCapSquare
|
||||
};
|
||||
enum lineJoin{
|
||||
lineJoinMiter,
|
||||
lineJoinRound,
|
||||
lineJoinBevel
|
||||
};
|
||||
|
||||
class PaintState {
|
||||
public:
|
||||
draw::Color fill;
|
||||
draw::Color stroke;
|
||||
float strokeWidth;
|
||||
bool flagEvenOdd;
|
||||
enum esvg::lineCap lineCap;
|
||||
enum esvg::lineJoin lineJoin;
|
||||
etk::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);
|
||||
std::vector<uint8_t> m_scanline;
|
||||
std::vector<uint8_t> m_buffer;
|
||||
ivec2 m_size;
|
||||
int32_t m_stride;
|
||||
public:
|
||||
Renderer(const ivec2& _size);
|
||||
~Renderer();
|
||||
void writePpm(std::string fileName);
|
||||
etk::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() { return m_buffer; };
|
||||
uint32_t getDataSize() { return m_allocatedSize; };
|
||||
uint8_t* getDataPointer() {
|
||||
return &m_buffer[0];
|
||||
};
|
||||
uint32_t getDataSize() {
|
||||
return m_buffer.size();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ esvg::Text::~Text() {
|
||||
|
||||
}
|
||||
|
||||
bool esvg::Text::parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax) {
|
||||
bool esvg::Text::parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax) {
|
||||
_sizeMax.setValue(0,0);
|
||||
SVG_ERROR("NOT IMPLEMENTED");
|
||||
return false;
|
||||
|
@ -16,7 +16,7 @@ namespace esvg {
|
||||
public:
|
||||
Text(PaintState _parentPaintState);
|
||||
~Text();
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, agg::trans_affine& _parentTrans, etk::Vector2D<float>& _sizeMax);
|
||||
virtual bool parse(const std::shared_ptr<exml::Element>& _element, mat2& _parentTrans, vec2& _sizeMax);
|
||||
virtual void display(int32_t _spacing);
|
||||
};
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ namespace esvg {
|
||||
};
|
||||
#define SVG_BASE(info,data) TK_LOG_BASE(esvg::getLogId(),info,data)
|
||||
|
||||
#define SVG_PRINT(data) SVG_BASE(-1, data)
|
||||
#define SVG_CRITICAL(data) SVG_BASE(1, data)
|
||||
#define SVG_ERROR(data) SVG_BASE(2, data)
|
||||
#define SVG_WARNING(data) SVG_BASE(3, data)
|
||||
|
385
esvg/esvg.cpp
385
esvg/esvg.cpp
@ -19,67 +19,235 @@
|
||||
#include <esvg/Text.h>
|
||||
#include <esvg/Group.h>
|
||||
|
||||
#include <agg/agg_basics.h>
|
||||
#include <agg/agg_rendering_buffer.h>
|
||||
#include <agg/agg_rasterizer_scanline_aa.h>
|
||||
#include <agg/agg_scanline_p.h>
|
||||
#include <agg/agg_renderer_scanline.h>
|
||||
#include <agg/agg_path_storage.h>
|
||||
#include <agg/agg_conv_transform.h>
|
||||
#include <agg/agg_bounding_rect.h>
|
||||
#include <agg/agg_color_rgba.h>
|
||||
#include <agg/agg_pixfmt_rgba.h>
|
||||
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Document"
|
||||
|
||||
|
||||
esvg::Document::Document(const std::string& _fileName) :
|
||||
esvg::Document::Document() :
|
||||
m_renderedElement(nullptr) {
|
||||
m_fileName = _fileName;
|
||||
m_fileName = "";
|
||||
m_version = "0.0";
|
||||
m_loadOK = true;
|
||||
m_paint.fill = (int32_t)0xFF0000FF;
|
||||
m_paint.stroke = (int32_t)0xFFFFFF00;
|
||||
m_loadOK = false;
|
||||
m_paint.fill = etk::color::red;
|
||||
m_paint.stroke = etk::color::white;
|
||||
|
||||
m_paint.strokeWidth = 1.0;
|
||||
m_paint.viewPort.setValue(255,255);
|
||||
m_paint.flagEvenOdd = false;
|
||||
m_paint.lineJoin = esvg::lineJoinMiter;
|
||||
m_paint.lineCap = esvg::lineCapButt;
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
m_size.setValue(0,0);
|
||||
|
||||
exml::Document doc;
|
||||
if (false == doc.load(m_fileName)) {
|
||||
SVG_ERROR("Error occured when loading XML : " << m_fileName);
|
||||
m_loadOK = false;
|
||||
return;
|
||||
}
|
||||
|
||||
esvg::Document::~Document() {
|
||||
delete(m_renderedElement);
|
||||
m_renderedElement = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void esvg::Document::displayDebug() {
|
||||
SVG_DEBUG("Main SVG node : size=" << m_size);
|
||||
for (int32_t iii=0; iii<m_subElementList.size(); iii++) {
|
||||
if (m_subElementList[iii] != nullptr) {
|
||||
m_subElementList[iii]->display(1);
|
||||
}
|
||||
}
|
||||
if (0 == doc.size() ) {
|
||||
SVG_ERROR("(l ?) No nodes in the xml file ... \"" << m_fileName << "\"");
|
||||
}
|
||||
|
||||
|
||||
void esvg::Document::aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans)
|
||||
{
|
||||
for (int32_t iii=0; iii<m_subElementList.size(); iii++) {
|
||||
if (m_subElementList[iii] != nullptr) {
|
||||
m_subElementList[iii]->aggDraw(_myRenderer, _basicTrans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esvg::Document::generateTestFile()
|
||||
{
|
||||
int32_t sizeX = m_size.x();
|
||||
if (sizeX == 0) {
|
||||
sizeX = 64;
|
||||
}
|
||||
int32_t sizeY = m_size.y();
|
||||
if (sizeY == 0) {
|
||||
sizeY = 64;
|
||||
}
|
||||
delete(m_renderedElement);
|
||||
m_renderedElement = nullptr;
|
||||
m_renderedElement = new esvg::Renderer(ivec2(sizeX, sizeY));
|
||||
// create the first element matrix modification ...
|
||||
mat2 basicTrans;
|
||||
//basicTrans *= etk::mat2Translate(vec2(-g_base_dx, -g_base_dy));
|
||||
//basicTrans *= etk::mat2Scale(vec2(2, 2));
|
||||
//basicTrans *= etk::mat2Rotate(vec2(g_angle));
|
||||
//basicTrans *= etk::mat2Skew(vec2(2.0, 5.0));
|
||||
//basicTrans *= etk::mat2Translate(vec2(width*0.3, height/2));
|
||||
//basicTrans *= etk::mat2Translate(vec2(width/3, height/3));
|
||||
|
||||
|
||||
aggDraw(*m_renderedElement, basicTrans);
|
||||
std::string tmpFileOut = "yyy_out_";
|
||||
tmpFileOut += m_fileName;
|
||||
tmpFileOut += ".ppm";
|
||||
m_renderedElement->writePpm(tmpFileOut);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void esvg::Document::generateAnImage(int32_t _sizeX, int32_t _sizeY) {
|
||||
int32_t sizeX = _sizeX;
|
||||
if (sizeX == 0) {
|
||||
SVG_ERROR("SizeX == 0 ==> set 64");
|
||||
sizeX = 64;
|
||||
}
|
||||
int32_t sizeY = _sizeY;
|
||||
if (sizeY == 0) {
|
||||
SVG_ERROR("SizeY == 0 ==> set 64");
|
||||
sizeY = 64;
|
||||
}
|
||||
SVG_INFO("Generate size (" << sizeX << "," << sizeY << ")");
|
||||
delete(m_renderedElement);
|
||||
m_renderedElement = nullptr;
|
||||
|
||||
m_renderedElement = new esvg::Renderer(ivec2(sizeX, sizeY));
|
||||
// create the first element matrix modification ...
|
||||
mat2 basicTrans;
|
||||
//basicTrans *= etk::mat2Translate(vec2(-g_base_dx, -g_base_dy));
|
||||
basicTrans *= etk::mat2Scale(vec2(sizeX/m_size.x(), sizeY/m_size.y()));
|
||||
//basicTrans *= etk::mat2Rotate(g_angle);// + agg::pi);
|
||||
//basicTrans *= etk::mat2Skew(vec2(2.0, 5.0));
|
||||
//basicTrans *= etk::mat2Translate(vec2(width*0.3, height/2));
|
||||
//basicTrans *= etk::mat2Translate(vec2(width/3, height/3));
|
||||
|
||||
aggDraw(*m_renderedElement, basicTrans);
|
||||
std::string tmpFileOut = "zzz_out_test.ppm";
|
||||
m_renderedElement->writePpm(tmpFileOut);
|
||||
}
|
||||
/*
|
||||
void esvg::Document::generateAnImage(draw::Image& _output) {
|
||||
generateAnImage(ivec2(m_size.x(),m_size.y()), _output);
|
||||
}
|
||||
|
||||
void esvg::Document::generateAnImage(ivec2 _size, draw::Image& _output) {
|
||||
generateAnImage(_size.x(), _size.y());
|
||||
_output.resize(_size);
|
||||
draw::Color tmpp(0,0,0,0);
|
||||
_output.setFillColor(tmpp);
|
||||
_output.clear();
|
||||
if(NULL != m_renderedElement) {
|
||||
uint8_t* pointerOnData = m_renderedElement->getDataPointer();
|
||||
int32_t sizeData = m_renderedElement->getDataSize();
|
||||
uint8_t* tmpOut = (uint8_t*)_output.getTextureDataPointer();
|
||||
memcpy(tmpOut, pointerOnData, sizeData);
|
||||
}
|
||||
}
|
||||
*/
|
||||
uint8_t* esvg::Document::getPointerOnData() {
|
||||
if(m_renderedElement == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_renderedElement->getDataPointer();
|
||||
}
|
||||
|
||||
uint32_t esvg::Document::getSizeOnData() {
|
||||
if(m_renderedElement == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return m_renderedElement->getDataSize();
|
||||
}
|
||||
|
||||
void esvg::Document::clear() {
|
||||
m_fileName = "";
|
||||
m_version = "0.0";
|
||||
m_loadOK = true;
|
||||
m_paint.fill = etk::color::red;
|
||||
m_paint.stroke = etk::color::white;
|
||||
|
||||
m_paint.strokeWidth = 1.0;
|
||||
m_paint.viewPort.setValue(255,255);
|
||||
m_paint.flagEvenOdd = false;
|
||||
m_paint.lineJoin = esvg::join_miter;
|
||||
m_paint.lineCap = esvg::cap_butt;
|
||||
m_size.setValue(0,0);
|
||||
}
|
||||
|
||||
|
||||
bool esvg::Document::parse(const std::string& _data) {
|
||||
clear();
|
||||
exml::Document doc;
|
||||
if (doc.parse(_data) == false) {
|
||||
SVG_ERROR("Error occured when loading SVG : " << m_fileName);
|
||||
m_loadOK = false;
|
||||
return;
|
||||
return m_loadOK;
|
||||
}
|
||||
if (doc.size() == 0) {
|
||||
SVG_ERROR("(l ?) No nodes in the SVG file ... \"" << m_fileName << "\"");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
std::shared_ptr<exml::Element> root = doc.getNamed("svg" );
|
||||
if (root == nullptr) {
|
||||
SVG_ERROR("(l ?) main node not find: \"svg\" in \"" << m_fileName << "\"");
|
||||
m_loadOK = false;
|
||||
return;
|
||||
return m_loadOK;
|
||||
}
|
||||
m_loadOK = parseXMLData(root);
|
||||
return m_loadOK;
|
||||
}
|
||||
|
||||
bool esvg::Document::generate(std::string& _data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool esvg::Document::load(const std::string& _file) {
|
||||
clear();
|
||||
m_fileName = _file;
|
||||
exml::Document doc;
|
||||
if (doc.load(m_fileName) == false) {
|
||||
SVG_ERROR("Error occured when loading SVG : " << m_fileName);
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
if (doc.size() == 0) {
|
||||
SVG_ERROR("(l ?) No nodes in the SVG file ... \"" << m_fileName << "\"");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
std::shared_ptr<exml::Element> root = doc.getNamed("svg" );
|
||||
if (root == nullptr) {
|
||||
SVG_ERROR("(l ?) main node not find: \"svg\" in \"" << m_fileName << "\"");
|
||||
m_loadOK = false;
|
||||
return m_loadOK;
|
||||
}
|
||||
m_loadOK = parseXMLData(root);
|
||||
return m_loadOK;
|
||||
}
|
||||
|
||||
bool esvg::Document::store(const std::string& _file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool esvg::Document::parseXMLData(const std::shared_ptr<exml::Element>& _root) {
|
||||
// get the svg version :
|
||||
m_version = root->getAttribute("version");
|
||||
m_version = _root->getAttribute("version");
|
||||
// parse ...
|
||||
vec2 pos(0,0);
|
||||
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 << ")");
|
||||
parseTransform(_root);
|
||||
parsePosition(_root, pos, m_size);
|
||||
parsePaintAttr(_root);
|
||||
SVG_VERBOSE("parsed .ROOT trans: " << m_transformMatrix);
|
||||
vec2 maxSize(0,0);
|
||||
vec2 size(0,0);
|
||||
// parse all sub node :
|
||||
for(int32_t iii=0; iii< root->size(); iii++) {
|
||||
std::shared_ptr<exml::Element> child = root->getElement(iii);
|
||||
for(int32_t iii=0; iii< _root->size(); iii++) {
|
||||
std::shared_ptr<exml::Element> child = _root->getElement(iii);
|
||||
if (child == nullptr) {
|
||||
// comment trsh here...
|
||||
continue;
|
||||
@ -121,14 +289,14 @@ esvg::Document::Document(const std::string& _fileName) :
|
||||
} else {
|
||||
SVG_ERROR("(l "<<child->getPos()<<") node not suported : \""<<child->getValue()<<"\" must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
|
||||
}
|
||||
if (NULL == elementParser) {
|
||||
if (elementParser == nullptr) {
|
||||
SVG_ERROR("(l "<<child->getPos()<<") error on node: \""<<child->getValue()<<"\" allocation error or not supported ...");
|
||||
continue;
|
||||
}
|
||||
if (false == elementParser->parse(child, m_transformMatrix, size)) {
|
||||
if (elementParser->parse(child, m_transformMatrix, size) == false) {
|
||||
SVG_ERROR("(l "<<child->getPos()<<") error on node: \""<<child->getValue()<<"\" Sub Parsing ERROR");
|
||||
delete(elementParser);
|
||||
elementParser = NULL;
|
||||
elementParser = nullptr;
|
||||
continue;
|
||||
}
|
||||
if (maxSize.x()<size.x()) {
|
||||
@ -145,143 +313,8 @@ esvg::Document::Document(const std::string& _fileName) :
|
||||
} else {
|
||||
m_size.setValue((int32_t)m_size.x(), (int32_t)m_size.y());
|
||||
}
|
||||
//DisplayDebug();
|
||||
}
|
||||
|
||||
esvg::Document::~Document() {
|
||||
if(NULL != m_renderedElement) {
|
||||
delete(m_renderedElement);
|
||||
m_renderedElement = NULL;
|
||||
}
|
||||
displayDebug();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void esvg::Document::displayDebug() {
|
||||
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 esvg::Document::aggDraw(esvg::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 esvg::Document::generateTestFile()
|
||||
{
|
||||
int32_t sizeX = m_size.x();
|
||||
if (sizeX == 0) {
|
||||
sizeX = 64;
|
||||
}
|
||||
int32_t sizeY = m_size.y();
|
||||
if (sizeY == 0) {
|
||||
sizeY = 64;
|
||||
}
|
||||
if(NULL != m_renderedElement) {
|
||||
delete(m_renderedElement);
|
||||
m_renderedElement = NULL;
|
||||
}
|
||||
m_renderedElement = new esvg::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);
|
||||
std::string tmpFileOut = "yyy_out_";
|
||||
tmpFileOut += m_fileName;
|
||||
tmpFileOut += ".ppm";
|
||||
m_renderedElement->writePpm(tmpFileOut);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void esvg::Document::generateAnImage(int32_t _sizeX, int32_t _sizeY)
|
||||
{
|
||||
int32_t sizeX = _sizeX;
|
||||
if (sizeX == 0) {
|
||||
SVG_ERROR("SizeX == 0 ==> set 64");
|
||||
sizeX = 64;
|
||||
}
|
||||
int32_t sizeY = _sizeY;
|
||||
if (sizeY == 0) {
|
||||
SVG_ERROR("SizeY == 0 ==> set 64");
|
||||
sizeY = 64;
|
||||
}
|
||||
SVG_INFO("Generate size (" << sizeX << "," << sizeY << ")");
|
||||
if(NULL != m_renderedElement) {
|
||||
delete(m_renderedElement);
|
||||
m_renderedElement = NULL;
|
||||
}
|
||||
|
||||
m_renderedElement = new esvg::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);
|
||||
/*
|
||||
std::string tmpFileOut = "zzz_out_test.ppm";
|
||||
m_renderedElement->WritePpm(tmpFileOut);
|
||||
*/
|
||||
}
|
||||
|
||||
void esvg::Document::generateAnImage(draw::Image& _output)
|
||||
{
|
||||
generateAnImage(ivec2(m_size.x(),m_size.y()), _output);
|
||||
}
|
||||
|
||||
void esvg::Document::generateAnImage(ivec2 _size, draw::Image& _output)
|
||||
{
|
||||
generateAnImage(_size.x(), _size.y());
|
||||
_output.resize(_size);
|
||||
draw::Color tmpp(0,0,0,0);
|
||||
_output.setFillColor(tmpp);
|
||||
_output.clear();
|
||||
if(NULL != m_renderedElement) {
|
||||
uint8_t* pointerOnData = m_renderedElement->getDataPointer();
|
||||
int32_t sizeData = m_renderedElement->getDataSize();
|
||||
uint8_t* tmpOut = (uint8_t*)_output.getTextureDataPointer();
|
||||
memcpy(tmpOut, pointerOnData, sizeData);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* esvg::Document::getPointerOnData()
|
||||
{
|
||||
if(NULL == m_renderedElement) {
|
||||
return NULL;
|
||||
}
|
||||
return m_renderedElement->getDataPointer();
|
||||
}
|
||||
|
||||
uint32_t esvg::Document::getSizeOnData()
|
||||
{
|
||||
if(NULL == m_renderedElement) {
|
||||
return 0;
|
||||
}
|
||||
return m_renderedElement->getDataSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
51
esvg/esvg.h
51
esvg/esvg.h
@ -15,7 +15,7 @@
|
||||
#include <etk/os/FSNode.h>
|
||||
|
||||
#include <esvg/Base.h>
|
||||
#include <draw/Image.h>
|
||||
//#include <draw/Image.h>
|
||||
|
||||
namespace esvg {
|
||||
class Document : public esvg::Base {
|
||||
@ -24,22 +24,59 @@ namespace esvg {
|
||||
bool m_loadOK;
|
||||
std::string m_version;
|
||||
std::string m_title;
|
||||
std::vector<esvg::Base *> m_subElementList;
|
||||
std::vector<esvg::Base*> m_subElementList;
|
||||
vec2 m_size;
|
||||
esvg::Renderer* m_renderedElement;
|
||||
public:
|
||||
Document();
|
||||
Document(const std::string& _fileName);
|
||||
~Document();
|
||||
bool isLoadOk() { return m_loadOK; };
|
||||
void clear();
|
||||
/**
|
||||
* @brief parse a string that contain an svg stream
|
||||
* @param[in] _data Data to parse
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool parse(const std::string& _data);
|
||||
/**
|
||||
* @brief generate a string that contain the created SVG
|
||||
* @param[out] _data Data where the svg is stored
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool generate(std::string& _data);
|
||||
/**
|
||||
* @brief Load the file that might contain the svg
|
||||
* @param[in] _file Filename of the svg (compatible with etk FSNode naming)
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool load(const std::string& _file);
|
||||
/**
|
||||
* @brief Store the SVG in the file
|
||||
* @param[in] _file Filename of the svg (compatible with etk FSNode naming)
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool store(const std::string& _file);
|
||||
protected:
|
||||
bool parseXMLData(const std::shared_ptr<exml::Element>& _root);
|
||||
public:
|
||||
bool isLoadOk() {
|
||||
return m_loadOK;
|
||||
};
|
||||
void displayDebug();
|
||||
void generateTestFile();
|
||||
void generateAnImage(int32_t _sizeX, int32_t _sizeY);
|
||||
void generateAnImage(ivec2 _size, draw::Image& _output);
|
||||
void generateAnImage(draw::Image& _output);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, agg::trans_affine& _basicTrans);
|
||||
//void generateAnImage(ivec2 _size, draw::Image& _output);
|
||||
//void generateAnImage(draw::Image& _output);
|
||||
virtual void aggDraw(esvg::Renderer& _myRenderer, mat2& _basicTrans);
|
||||
uint8_t* getPointerOnData();
|
||||
uint32_t getSizeOnData();
|
||||
vec2 getDefinedSize() { return m_size;};
|
||||
vec2 getDefinedSize() {
|
||||
return m_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
36
lutin_esvg-test.py
Normal file
36
lutin_esvg-test.py
Normal file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_sub_type():
|
||||
return "TEST"
|
||||
|
||||
def get_desc():
|
||||
return "eSVG test-unit"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'test/main.cpp',
|
||||
'test/testParsingFile.cpp',
|
||||
'test/testPath.cpp',
|
||||
])
|
||||
my_module.add_module_depend(['esvg', 'gtest', 'test-debug'])
|
||||
return my_module
|
||||
|
@ -26,7 +26,7 @@ def get_version():
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_module_depend(['etk', 'agg', 'exml'])
|
||||
my_module.add_module_depend(['etk', 'exml'])
|
||||
my_module.add_src_file([
|
||||
'esvg/Base.cpp',
|
||||
'esvg/Circle.cpp',
|
||||
@ -40,6 +40,7 @@ def create(target, module_name):
|
||||
'esvg/Polyline.cpp',
|
||||
'esvg/Rectangle.cpp',
|
||||
'esvg/Renderer.cpp',
|
||||
'esvg/RenderPath.cpp',
|
||||
'esvg/Stroking.cpp',
|
||||
'esvg/Text.cpp'
|
||||
])
|
||||
|
22
test/main.cpp
Normal file
22
test/main.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <test-debug/debug.h>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <etk/etk.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "esvg::test"
|
||||
|
||||
int main(int _argc, const char *_argv[]) {
|
||||
::testing::InitGoogleTest(&_argc, const_cast<char **>(_argv));
|
||||
etk::init(_argc, _argv);
|
||||
//etk::initDefaultFolder("esvg-test");
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
0
test/testParsingFile.cpp
Normal file
0
test/testParsingFile.cpp
Normal file
31
test/testPath.cpp
Normal file
31
test/testPath.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <esvg/esvg.h>
|
||||
|
||||
TEST(TestPath, basicTest) {
|
||||
esvg::Document doc;
|
||||
/*
|
||||
doc.parse( "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg width='64' height='64'>"
|
||||
" <g transform='matrix(1.2,0,0,1.2,-579.7336,-567.9832)'>"
|
||||
" <path d='m 50,50 c -12.426,0 -22.5,10.072 -22.5,22.5 0,12.426 10.074,22.5 22.5,22.5 12.428,0 22.5,-10.074 22.5,-22.5 0,-12.427 -10.072,-22.5 -22.5,-22.5 z'"
|
||||
" style='fill:#333333;fill-rule:evenodd' />"
|
||||
" </g>"
|
||||
"</svg>");
|
||||
*/
|
||||
doc.parse( "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
|
||||
"<svg width='64' height='64'>"
|
||||
" <g transform='matrix(1.2,0,0,1.2,-579.7336,-567.9832)'>"
|
||||
" <path d='m 50,50 c -12.426,0 -22.5,10.072 -22.5,22.5 0,12.426 10.074,22.5 22.5,22.5 12.428,0 22.5,-10.074 22.5,-22.5 0,-12.427 -10.072,-22.5 -22.5,-22.5 z'"
|
||||
" style='stroke:#00F;stroke-width:5;fill-rule:evenodd' />"
|
||||
" </g>"
|
||||
"</svg>");
|
||||
doc.generateAnImage(128, 128);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user