diff --git a/esvg/Base.h b/esvg/Base.h index 37b5a1b..6dbe721 100644 --- a/esvg/Base.h +++ b/esvg/Base.h @@ -6,6 +6,10 @@ * @license APACHE v2.0 (see license file) */ + +#include +#include + #ifndef __ESVG_BASE_H__ #define __ESVG_BASE_H__ @@ -38,18 +42,6 @@ namespace esvg { spread_repead, //!< 'repead' spread. }; - enum cap { - cap_butt, - cap_round, - cap_square - }; - - enum join { - join_miter, - join_round, - join_bevel - }; - class PaintState { public: PaintState(); diff --git a/esvg/cap.h b/esvg/cap.h new file mode 100644 index 0000000..68958d8 --- /dev/null +++ b/esvg/cap.h @@ -0,0 +1,22 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#ifndef __ESVG_CAP_H__ +#define __ESVG_CAP_H__ + +#include +namespace esvg { + enum cap { + cap_butt, + cap_round, + cap_square + }; +} + +#endif + diff --git a/esvg/join.h b/esvg/join.h new file mode 100644 index 0000000..2ab0a8c --- /dev/null +++ b/esvg/join.h @@ -0,0 +1,23 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#ifndef __ESVG_JOIN_H__ +#define __ESVG_JOIN_H__ + +#include + +namespace esvg { + enum join { + join_miter, + join_round, + join_bevel + }; +} + +#endif + diff --git a/esvg/render/SegmentList.cpp b/esvg/render/SegmentList.cpp index 3fd8c1f..660e720 100644 --- a/esvg/render/SegmentList.cpp +++ b/esvg/render/SegmentList.cpp @@ -8,6 +8,8 @@ #include #include +#include + #undef __class__ @@ -145,9 +147,9 @@ void esvg::render::SegmentList::createSegmentListStroke(esvg::render::PointList& } } // create segment list: - bool haveStartLine; - vec2 leftPoint; - vec2 rightPoint; + bool haveStartLine = false; + vec2 leftPoint(0,0); + vec2 rightPoint(0,0); if (itListPoint.size() > 0) { if (itListPoint.front().m_type == esvg::render::Point::type_join) { // cyclic path... @@ -173,85 +175,30 @@ void esvg::render::SegmentList::createSegmentListStroke(esvg::render::PointList& SVG_VERBOSE("Find Single " << it.m_pos); break; case esvg::render::Point::type_start: - { - SVG_VERBOSE("Find Start " << it.m_pos); - if (haveStartLine == true) { - // close previous : - SVG_WARNING(" find a non close path ..."); - addSegment(leftPoint, rightPoint); - } - haveStartLine = true; - leftPoint = it.m_pos - + it.m_miterAxe*_width*0.5f; - rightPoint = it.m_pos - - it.m_miterAxe*_width*0.5f; + SVG_VERBOSE("Find Start " << it.m_pos); + if (haveStartLine == true) { + // close previous : + SVG_WARNING(" find a non close path ..."); addSegment(leftPoint, rightPoint); - SVG_VERBOSE(" segment :" << leftPoint << " -> " << rightPoint); } + haveStartLine = true; + startStopPoint(leftPoint, rightPoint, it, _cap, _width, true); break; case esvg::render::Point::type_stop: - { - SVG_VERBOSE("Find Stop " << it.m_pos); - if (haveStartLine == false) { - SVG_WARNING("find close path without start part ..."); - break; - } - haveStartLine = false; - vec2 left = it.m_pos - + it.m_miterAxe*_width*0.5f; - vec2 right = it.m_pos - - it.m_miterAxe*_width*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 ... - if (rightPoint.y() <= leftPoint.y()) { - addSegment(leftPoint, rightPoint); - } else { - addSegment(rightPoint, leftPoint); - } - SVG_VERBOSE(" segment :" << rightPoint << " -> " << leftPoint); + SVG_VERBOSE("Find Stop " << it.m_pos); + if (haveStartLine == false) { + SVG_WARNING("find close path without start part ..."); + break; } + haveStartLine = false; + startStopPoint(leftPoint, rightPoint, it, _cap, _width, false); break; case esvg::render::Point::type_interpolation: - { - SVG_VERBOSE("Find interpolation " << it.m_pos); - // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) - #if 1 - vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe); - vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe); - #else - vec2 left = it.m_pos - + it.m_miterAxe*_width*0.5f; - vec2 right = it.m_pos - - it.m_miterAxe*_width*0.5f; - #endif - //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 esvg::render::Point::type_join: { - SVG_VERBOSE("Find Join " << it.m_pos); - // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) - #if 1 - vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe); - vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe); - #else - vec2 left = it.m_pos - + it.m_miterAxe*_width*0.5f; - vec2 right = it.m_pos - - it.m_miterAxe*_width*0.5f; - #endif + SVG_VERBOSE("Find interpolation/join " << it.m_pos); + vec2 left = getIntersect(leftPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe); + vec2 right = getIntersect(rightPoint, it.m_pos-it.m_posPrevious, it.m_pos, it.m_miterAxe); //Draw from previous point: addSegment(leftPoint, left); SVG_VERBOSE(" segment :" << leftPoint << " -> " << left); @@ -269,3 +216,134 @@ void esvg::render::SegmentList::createSegmentListStroke(esvg::render::PointList& } + +void esvg::render::SegmentList::startStopPoint(vec2& _leftPoint, + vec2& _rightPoint, + const esvg::render::Point& _point, + enum esvg::cap _cap, + float _width, + bool _isStart) { + switch (_cap) { + case cap_butt: + { + vec2 left = _point.m_pos + + _point.m_miterAxe*_width*0.5f; + vec2 right = _point.m_pos + - _point.m_miterAxe*_width*0.5f; + if (_isStart == false) { + //Draw from previous point: + addSegment(_leftPoint, left); + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << left); + addSegment(right, _rightPoint); + SVG_VERBOSE(" segment :" << right << " -> " << _rightPoint); + } + _leftPoint = left; + _rightPoint = right; + } + if (_isStart == false) { + addSegment(_leftPoint, _rightPoint); + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << _rightPoint); + } else { + addSegment(_rightPoint, _leftPoint); + SVG_VERBOSE(" segment :" << _rightPoint << " -> " << _leftPoint); + } + break; + case cap_round: + { + if (_isStart == false) { + vec2 left = _point.m_pos + + _point.m_miterAxe*_width*0.5f; + vec2 right = _point.m_pos + - _point.m_miterAxe*_width*0.5f; + if (_isStart == false) { + //Draw from previous point: + addSegment(_leftPoint, left); + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << left); + addSegment(right, _rightPoint); + SVG_VERBOSE(" segment :" << right << " -> " << _rightPoint); + } + _leftPoint = left; + _rightPoint = right; + } + int32_t nbDot = int32_t(_width); + if (nbDot <= 2) { + nbDot = 2; + } + float baseAngle = M_PI/float(nbDot); + float iii; + _rightPoint = _point.m_pos + - _point.m_miterAxe*_width*0.5f; + vec2 storeOld(_rightPoint); + for (iii=baseAngle; iii " << _rightPoint); + } else { + addSegment(_rightPoint, _leftPoint); + SVG_VERBOSE(" segment :" << _rightPoint << " -> " << _leftPoint); + } + _rightPoint = _leftPoint; + } + _leftPoint = _point.m_pos + + _point.m_miterAxe*_width*0.5f; + if (_isStart == false) { + addSegment(_leftPoint, _rightPoint); + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << _rightPoint); + } else { + addSegment(_rightPoint, _leftPoint); + SVG_VERBOSE(" segment :" << _rightPoint << " -> " << _leftPoint); + } + _rightPoint = storeOld; + } + break; + case cap_square: + { + vec2 nextAxe; + if (_isStart == true) { + nextAxe = _point.m_posNext - _point.m_pos; + } else { + nextAxe = _point.m_posPrevious - _point.m_pos; + } + vec2 left = _point.m_pos + + _point.m_miterAxe*_width*0.5f; + vec2 right = _point.m_pos + - _point.m_miterAxe*_width*0.5f; + mat2 tmpMat = etk::mat2Translate(nextAxe.safeNormalize()*_width*-0.5f); + left = tmpMat*left; + right = tmpMat*right; + if (_isStart == false) { + if (_isStart == false) { + //Draw from previous point: + addSegment(_leftPoint, left); + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << left); + addSegment(right, _rightPoint); + SVG_VERBOSE(" segment :" << right << " -> " << _rightPoint); + } + } + _leftPoint = left; + _rightPoint = right; + if (_isStart == false) { + addSegment(_leftPoint, _rightPoint); + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << _rightPoint); + } else { + addSegment(_rightPoint, _leftPoint); + SVG_VERBOSE(" segment :" << _rightPoint << " -> " << _leftPoint); + } + SVG_VERBOSE(" segment :" << _leftPoint << " -> " << _rightPoint); + } + break; + default: + SVG_ERROR(" Undefined CAP TYPE"); + break; + } +} + diff --git a/esvg/render/SegmentList.h b/esvg/render/SegmentList.h index 52379dd..ab4b15d 100644 --- a/esvg/render/SegmentList.h +++ b/esvg/render/SegmentList.h @@ -29,6 +29,13 @@ namespace esvg { float _width, enum esvg::cap _cap, enum esvg::join _join); + private: + void startStopPoint(vec2& _leftPoint, + vec2& _rightPoint, + const esvg::render::Point& _point, + enum esvg::cap _cap, + float _width, + bool _isStart); }; } } diff --git a/esvg/render/Weight.cpp b/esvg/render/Weight.cpp index 8f20adc..91e6d40 100644 --- a/esvg/render/Weight.cpp +++ b/esvg/render/Weight.cpp @@ -169,6 +169,14 @@ void esvg::render::Weight::generate(ivec2 _size, int32_t _subSamplingCount, cons scanline.set(currentPos, currentValue); } } + // if the counter is not at 0 ==> fill if to the end with full value ... 2.0 + if (lastState != 0.0f) { + // just past the last state to the end of the image ... + SVG_ERROR("end of Path whith no end ... " << currentPos << " -> " << _size.x()); + for (int32_t xxx=currentPos; xxx<_size.x(); ++xxx) { + scanline.set(xxx, 100.0); + } + } append(yyy, scanline); } } diff --git a/esvg/render/Weight.h b/esvg/render/Weight.h index 6e6ecdc..18f1604 100644 --- a/esvg/render/Weight.h +++ b/esvg/render/Weight.h @@ -11,7 +11,6 @@ #include #include -#include #include #include diff --git a/lutin_esvg.py b/lutin_esvg.py index ad95995..fffc731 100644 --- a/lutin_esvg.py +++ b/lutin_esvg.py @@ -77,6 +77,8 @@ def create(target, module_name): 'esvg/Renderer.h', 'esvg/Stroking.h', 'esvg/Text.h', + 'esvg/cap.h', + 'esvg/join.h', 'esvg/render/Element.h', 'esvg/render/ElementStop.h', 'esvg/render/ElementClose.h', diff --git a/test/testCap.cpp b/test/testCap.cpp index e0d1236..1de7711 100644 --- a/test/testCap.cpp +++ b/test/testCap.cpp @@ -16,7 +16,8 @@ TEST(TestCap, butt) { std::string data("" "" - " " + " " + " " ""); esvg::Document doc; doc.parse(data); @@ -27,7 +28,8 @@ TEST(TestCap, butt) { TEST(TestCap, round) { std::string data("" "" - " " + " " + " " ""); esvg::Document doc; doc.parse(data); @@ -38,7 +40,8 @@ TEST(TestCap, round) { TEST(TestCap, square) { std::string data("" "" - " " + " " + " " ""); esvg::Document doc; doc.parse(data); @@ -46,3 +49,115 @@ TEST(TestCap, square) { doc.generateAnImage(ivec2(100, 100), "TestCap_square.bmp", g_visualDebug); } + +TEST(TestCap, buttVert) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_buttVert.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_buttVert.bmp", g_visualDebug); +} + +TEST(TestCap, roundVert) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_roundVert.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_roundVert.bmp", g_visualDebug); +} + +TEST(TestCap, squareVert) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_squareVert.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_squareVert.bmp", g_visualDebug); +} + + + +TEST(TestCap, buttDiag1) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_buttDiag1.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_buttDiag1.bmp", g_visualDebug); +} + +TEST(TestCap, roundDiag1) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_roundDiag1.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_roundDiag1.bmp", g_visualDebug); +} + +TEST(TestCap, squareDiag1) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_squareDiag1.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_squareDiag1.bmp", g_visualDebug); +} + + +TEST(TestCap, buttDiag2) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_buttDiag2.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_buttDiag2.bmp", g_visualDebug); +} + +TEST(TestCap, roundDiag2) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_roundDiag2.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_roundDiag2.bmp", g_visualDebug); +} + +TEST(TestCap, squareDiag2) { + std::string data("" + "" + " " + " " + ""); + esvg::Document doc; + doc.parse(data); + etk::FSNodeWriteAllData("TestCap_squareDiag2.svg", data); + doc.generateAnImage(ivec2(100, 100), "TestCap_squareDiag2.bmp", g_visualDebug); +} + diff --git a/test/testPath.cpp b/test/testPath.cpp index a2319ec..5745ac7 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -94,7 +94,7 @@ TEST(TestPath, bezierCurveTo) { TEST(TestPath, bezierSmoothCurveTo) { std::string data("" "" - " " ""); esvg::Document doc;