diff --git a/esvg/Path.cpp b/esvg/Path.cpp index 47927ef..0de58c2 100644 --- a/esvg/Path.cpp +++ b/esvg/Path.cpp @@ -8,6 +8,7 @@ #include #include +#include #undef __class__ #define __class__ "Path" @@ -246,400 +247,6 @@ void esvg::Path::display(int32_t _spacing) { m_listElement.display(_spacing); } -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 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=0 - && _pos 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; iii0 && _pos.x()0 && _pos.y()=0 && _pos.x()=0 && _pos.y()=0 - && _posY=0 - && _posY& _e1, const std::pair& _e2) { - return _e1.first < _e2.first; -} - - -void addSegment(std::vector& _seg, const esvg::render::Point& _pos0, const esvg::render::Point& _pos1) { - // Skip horizontal Segments - if (_pos0.m_pos.y() == _pos1.m_pos.y()) { - // remove /0 operation - return; - } - _seg.push_back(Segment(_pos0.m_pos, _pos1.m_pos)); -} - -std::vector createSegmentList(const std::vector& _listPoint) { - std::vector out; - // Build Segments - for (int32_t iii=0, jjj=_listPoint.size()-1; - iii < _listPoint.size(); - jjj = iii++) { - addSegment(out, _listPoint[jjj], _listPoint[iii]); - } - // TODO : Check if it is really usefull ... - std::sort(out.begin(), out.end(), sortSegmentFunction); - return out; -} - -std::vector createSegmentListStroke(std::vector& _listPoint) { - std::vector out; - - // 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 < _listPoint.size(); - idPevious++, idCurrent++, idNext++) { - if ( _listPoint[idCurrent].m_type == esvg::render::Point::type_join - || _listPoint[idCurrent].m_type == esvg::render::Point::type_interpolation) { - if (idPevious < 0 ) { - SVG_ERROR("an error occure a previous ID is < 0.... "); - continue; - } - if (idNext >= _listPoint.size()) { - SVG_ERROR("an error occure a next ID is >= nbPoint len .... "); - continue; - } - vec2 vecA = _listPoint[idCurrent].m_pos - _listPoint[idPevious].m_pos; - vecA.safeNormalize(); - vec2 vecB = _listPoint[idNext].m_pos - _listPoint[idCurrent].m_pos; - vecB.safeNormalize(); - vec2 vecC = vecA - vecB; - if (vecC == vec2(0,0)) { - // special case: 1 line ... - _listPoint[idCurrent].m_miterAxe = vec2(vecA.y(), vecA.x()); - } else { - vecC.safeNormalize(); - _listPoint[idCurrent].m_miterAxe = vecC; - } - } else if (_listPoint[idCurrent].m_type == esvg::render::Point::type_start) { - vec2 vecB = _listPoint[idNext].m_pos - _listPoint[idCurrent].m_pos; - vecB.safeNormalize(); - _listPoint[idCurrent].m_miterAxe = vec2(vecB.y(), vecB.x()); - } else if (_listPoint[idCurrent].m_type == esvg::render::Point::type_stop) { - if (idPevious < 0 ) { - SVG_ERROR("an error occure a previous ID is < 0.... "); - continue; - } - vec2 vecA = _listPoint[idCurrent].m_pos - _listPoint[idPevious].m_pos; - vecA.safeNormalize(); - _listPoint[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 < _listPoint.size(); - ++iii) { - switch (_listPoint[iii].m_type) { - case esvg::render::Point::type_single: - // just do nothing .... - SVG_VERBOSE("[" << iii << "] Find Single " << _listPoint[iii].m_pos); - break; - case esvg::render::Point::type_start: - { - SVG_VERBOSE("[" << iii << "] Find Start " << _listPoint[iii].m_pos); - if (haveStartLine == true) { - // close previous : - SVG_WARNING(" find a non close path ..."); - addSegment(out, leftPoint, rightPoint); - } - haveStartLine = true; - // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) - leftPoint = _listPoint[iii].m_pos - + _listPoint[iii].m_miterAxe*lineWidth*0.5f; - rightPoint = _listPoint[iii].m_pos - - _listPoint[iii].m_miterAxe*lineWidth*0.5f; - addSegment(out, leftPoint, rightPoint); - SVG_VERBOSE(" segment :" << leftPoint << " -> " << rightPoint); - } - break; - case esvg::render::Point::type_stop: - { - SVG_VERBOSE("[" << iii << "] Find Stop " << _listPoint[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 = _listPoint[iii].m_pos - + _listPoint[iii].m_miterAxe*lineWidth*0.5f; - vec2 right = _listPoint[iii].m_pos - - _listPoint[iii].m_miterAxe*lineWidth*0.5f; - //Draw from previous point: - addSegment(out, leftPoint, left); - SVG_VERBOSE(" segment :" << leftPoint << " -> " << left); - addSegment(out, right, rightPoint); - SVG_VERBOSE(" segment :" << right << " -> " << rightPoint); - leftPoint = left; - rightPoint = right; - // end line ... - addSegment(out, rightPoint, leftPoint); - SVG_VERBOSE(" segment :" << rightPoint << " -> " << leftPoint); - } - break; - case esvg::render::Point::type_interpolation: - { - SVG_VERBOSE("[" << iii << "] Find interpolation " << _listPoint[iii].m_pos); - // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) - vec2 left = _listPoint[iii].m_pos - + _listPoint[iii].m_miterAxe*lineWidth*0.5f; - vec2 right = _listPoint[iii].m_pos - - _listPoint[iii].m_miterAxe*lineWidth*0.5f; - //Draw from previous point: - addSegment(out, leftPoint, left); - SVG_VERBOSE(" segment :" << leftPoint << " -> " << left); - addSegment(out, right, rightPoint); - SVG_VERBOSE(" segment :" << right << " -> " << rightPoint); - leftPoint = left; - rightPoint = right; - } - break; - case esvg::render::Point::type_join: - { - SVG_VERBOSE("[" << iii << "] Find Join " << _listPoint[iii].m_pos); - // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) - vec2 left = _listPoint[iii].m_pos - + _listPoint[iii].m_miterAxe*lineWidth*0.5f; - vec2 right = _listPoint[iii].m_pos - - _listPoint[iii].m_miterAxe*lineWidth*0.5f; - //Draw from previous point: - addSegment(out, leftPoint, left); - SVG_VERBOSE(" segment :" << leftPoint << " -> " << left); - addSegment(out, right, rightPoint); - SVG_VERBOSE(" segment :" << right << " -> " << rightPoint); - leftPoint = left; - rightPoint = right; - } - break; - } - } - // TODO : Check if it is really usefull ... - std::sort(out.begin(), out.end(), sortSegmentFunction); - return out; -} - - -Weighter createWeighter(ivec2 _size, int32_t _subSamplingCount, const std::vector& _listSegment) { - 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 availlableSegmentPixel; - for (auto &it : _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/_subSamplingCount; - for (int32_t kkk=0; kkk<_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 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> 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(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 listSegment = createSegmentList(listPoints); + esvg::render::SegmentList listSegment; + listSegment.createSegmentList(listPoints); // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule - tmpFill = createWeighter(ivec2(128,128), nbSubScanLine, listSegment); + tmpFill.generate(ivec2(128,128), nbSubScanLine, listSegment); } // check if we need to display stroke: if ( m_paint.strokeWidth > 0 && m_paint.stroke.a() != 0x00) { - std::vector listSegment = createSegmentListStroke(listPoints); + esvg::render::SegmentList listSegment; + listSegment.createSegmentListStroke(listPoints); // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule - tmpStroke = createWeighter(ivec2(128,128), nbSubScanLine, listSegment); + tmpStroke.generate(ivec2(128,128), nbSubScanLine, listSegment); } // add on images: for (int32_t yyy=0; yyy<_myRenderer.m_size.y(); ++yyy) { diff --git a/esvg/render/Point.cpp b/esvg/render/Point.cpp index e69de29..844f2ea 100644 --- a/esvg/render/Point.cpp +++ b/esvg/render/Point.cpp @@ -0,0 +1,34 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include +#include + + +void esvg::render::Point::setEndPath() { + if (m_type == esvg::render::Point::type_interpolation) { + SVG_WARNING("Request stop path of an interpolate Point"); + m_type = esvg::render::Point::type_stop; + return; + } + if (m_type == esvg::render::Point::type_stop) { + SVG_WARNING("Request stop path of an STOP Point"); + return; + } + if (m_type == esvg::render::Point::type_start) { + m_type = esvg::render::Point::type_single; + return; + } + m_type = esvg::render::Point::type_stop; +} + +void esvg::render::Point::normalize(const vec2& _nextPoint) { + m_delta = _nextPoint - m_pos; + m_len = m_delta.length(); +} + diff --git a/esvg/render/Point.h b/esvg/render/Point.h index 1df8602..25ee595 100644 --- a/esvg/render/Point.h +++ b/esvg/render/Point.h @@ -35,26 +35,8 @@ namespace esvg { m_type(_type) { // nothing to do ... } - void setEndPath() { - if (m_type == esvg::render::Point::type_interpolation) { - SVG_WARNING("Request stop path of an interpolate Point"); - m_type = esvg::render::Point::type_stop; - return; - } - if (m_type == esvg::render::Point::type_stop) { - SVG_WARNING("Request stop path of an STOP Point"); - return; - } - if (m_type == esvg::render::Point::type_start) { - m_type = esvg::render::Point::type_single; - return; - } - m_type = esvg::render::Point::type_stop; - } - void normalize(const vec2& _nextPoint) { - m_delta = _nextPoint - m_pos; - m_len = m_delta.length(); - } + void setEndPath(); + void normalize(const vec2& _nextPoint); }; } } diff --git a/esvg/render/Scanline.cpp b/esvg/render/Scanline.cpp new file mode 100644 index 0000000..5f004f9 --- /dev/null +++ b/esvg/render/Scanline.cpp @@ -0,0 +1,41 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include +#include + +esvg::render::Scanline::Scanline(size_t _size) { + float tmp(0); + m_data.resize(_size, tmp); +} + +size_t esvg::render::Scanline::size() const { + return m_data.size(); +} + +void esvg::render::Scanline::clear(float _fill) { + for (auto &it : m_data) { + it = _fill; + } +} + +float esvg::render::Scanline::get(int32_t _pos) const { + if( _pos>=0 + && _pos=0 + && _pos +#include + +namespace esvg { + namespace render { + class Scanline { + private: + std::vector m_data; + public: + // constructor : + Scanline(size_t _size=32); + // destructor + ~Scanline() { }; + public: + size_t size() const; + void clear(float _fill); + float get(int32_t _pos) const; + void set(int32_t _pos, float _newColor); + }; + } +} + +#endif diff --git a/esvg/render/Segment.cpp b/esvg/render/Segment.cpp new file mode 100644 index 0000000..c20a8e2 --- /dev/null +++ b/esvg/render/Segment.cpp @@ -0,0 +1,26 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include +#include + + +esvg::render::Segment::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 + } +} + + diff --git a/esvg/render/Segment.h b/esvg/render/Segment.h new file mode 100644 index 0000000..eecb0cb --- /dev/null +++ b/esvg/render/Segment.h @@ -0,0 +1,27 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#ifndef __ESVG_RENDER_SEGMENT_H__ +#define __ESVG_RENDER_SEGMENT_H__ + +#include +#include + +namespace esvg { + namespace render { + class Segment { + public: + Segment(const vec2& _p0, const vec2& _p1); + vec2 p0; + vec2 p1; + float direction; + }; + } +} + +#endif diff --git a/esvg/render/SegmentList.cpp b/esvg/render/SegmentList.cpp new file mode 100644 index 0000000..282f434 --- /dev/null +++ b/esvg/render/SegmentList.cpp @@ -0,0 +1,193 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include +#include + + +bool sortSegmentFunction(const esvg::render::Segment& _e1, const esvg::render::Segment& _e2) { + return _e1.p0.y() < _e2.p0.y(); +} + +esvg::render::SegmentList::SegmentList() { + +} + +void esvg::render::SegmentList::addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1) { + // Skip horizontal Segments + if (_pos0.m_pos.y() == _pos1.m_pos.y()) { + // remove /0 operation + return; + } + m_data.push_back(Segment(_pos0.m_pos, _pos1.m_pos)); +} + +void esvg::render::SegmentList::createSegmentList(const std::vector& _listPoint) { + // Build Segments + for (int32_t iii=0, jjj=_listPoint.size()-1; + iii < _listPoint.size(); + jjj = iii++) { + addSegment(_listPoint[jjj], _listPoint[iii]); + } + // TODO : Check if it is really usefull ... + std::sort(m_data.begin(), m_data.end(), sortSegmentFunction); +} + +void esvg::render::SegmentList::createSegmentListStroke(std::vector& _listPoint) { + // 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 < _listPoint.size(); + idPevious++, idCurrent++, idNext++) { + if ( _listPoint[idCurrent].m_type == esvg::render::Point::type_join + || _listPoint[idCurrent].m_type == esvg::render::Point::type_interpolation) { + if (idPevious < 0 ) { + SVG_ERROR("an error occure a previous ID is < 0.... "); + continue; + } + if (idNext >= _listPoint.size()) { + SVG_ERROR("an error occure a next ID is >= nbPoint len .... "); + continue; + } + vec2 vecA = _listPoint[idCurrent].m_pos - _listPoint[idPevious].m_pos; + vecA.safeNormalize(); + vec2 vecB = _listPoint[idNext].m_pos - _listPoint[idCurrent].m_pos; + vecB.safeNormalize(); + vec2 vecC = vecA - vecB; + if (vecC == vec2(0,0)) { + // special case: 1 line ... + _listPoint[idCurrent].m_miterAxe = vec2(vecA.y(), vecA.x()); + } else { + vecC.safeNormalize(); + _listPoint[idCurrent].m_miterAxe = vecC; + } + } else if (_listPoint[idCurrent].m_type == esvg::render::Point::type_start) { + vec2 vecB = _listPoint[idNext].m_pos - _listPoint[idCurrent].m_pos; + vecB.safeNormalize(); + _listPoint[idCurrent].m_miterAxe = vec2(vecB.y(), vecB.x()); + } else if (_listPoint[idCurrent].m_type == esvg::render::Point::type_stop) { + if (idPevious < 0 ) { + SVG_ERROR("an error occure a previous ID is < 0.... "); + continue; + } + vec2 vecA = _listPoint[idCurrent].m_pos - _listPoint[idPevious].m_pos; + vecA.safeNormalize(); + _listPoint[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 < _listPoint.size(); + ++iii) { + switch (_listPoint[iii].m_type) { + case esvg::render::Point::type_single: + // just do nothing .... + SVG_VERBOSE("[" << iii << "] Find Single " << _listPoint[iii].m_pos); + break; + case esvg::render::Point::type_start: + { + SVG_VERBOSE("[" << iii << "] Find Start " << _listPoint[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 = _listPoint[iii].m_pos + + _listPoint[iii].m_miterAxe*lineWidth*0.5f; + rightPoint = _listPoint[iii].m_pos + - _listPoint[iii].m_miterAxe*lineWidth*0.5f; + addSegment(leftPoint, rightPoint); + SVG_VERBOSE(" segment :" << leftPoint << " -> " << rightPoint); + } + break; + case esvg::render::Point::type_stop: + { + SVG_VERBOSE("[" << iii << "] Find Stop " << _listPoint[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 = _listPoint[iii].m_pos + + _listPoint[iii].m_miterAxe*lineWidth*0.5f; + vec2 right = _listPoint[iii].m_pos + - _listPoint[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 esvg::render::Point::type_interpolation: + { + SVG_VERBOSE("[" << iii << "] Find interpolation " << _listPoint[iii].m_pos); + // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) + vec2 left = _listPoint[iii].m_pos + + _listPoint[iii].m_miterAxe*lineWidth*0.5f; + vec2 right = _listPoint[iii].m_pos + - _listPoint[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 esvg::render::Point::type_join: + { + SVG_VERBOSE("[" << iii << "] Find Join " << _listPoint[iii].m_pos); + // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) + vec2 left = _listPoint[iii].m_pos + + _listPoint[iii].m_miterAxe*lineWidth*0.5f; + vec2 right = _listPoint[iii].m_pos + - _listPoint[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; + } + } + // TODO : Check if it is really usefull ... + std::sort(m_data.begin(), m_data.end(), sortSegmentFunction); +} + + diff --git a/esvg/render/SegmentList.h b/esvg/render/SegmentList.h new file mode 100644 index 0000000..82e07f5 --- /dev/null +++ b/esvg/render/SegmentList.h @@ -0,0 +1,31 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#ifndef __ESVG_RENDER_SEGMENT_LIST_H__ +#define __ESVG_RENDER_SEGMENT_LIST_H__ + +#include +#include +#include +#include + +namespace esvg { + namespace render { + class SegmentList { + public: + std::vector m_data; + public: + SegmentList(); + void addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1); + void createSegmentList(const std::vector& _listPoint); + void createSegmentListStroke(std::vector& _listPoint); + }; + } +} + +#endif diff --git a/esvg/render/Weight.cpp b/esvg/render/Weight.cpp new file mode 100644 index 0000000..6d7def9 --- /dev/null +++ b/esvg/render/Weight.cpp @@ -0,0 +1,171 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#include +#include + + +esvg::render::Weight::Weight() { + +} + +esvg::render::Weight::Weight(const ivec2& _size): + m_size(_size) { + resize(_size); +} + +esvg::render::Weight::~Weight() { + +} + +void esvg::render::Weight::resize(const ivec2& _size) { + 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()) { + SVG_WARNING("Wrong weigth buffer size ..."); + return; + } +} + +const ivec2& esvg::render::Weight::getSize() const { + return m_size; +} + +int32_t esvg::render::Weight::getWidth() const { + return m_size.x(); +} + +int32_t esvg::render::Weight::getHeight() const { + return m_size.y(); +} + +void esvg::render::Weight::clear(float _fill) { + for (int32_t iii=0; iii0 && _pos.x()0 && _pos.y()=0 && _pos.x()=0 && _pos.y()=0 + && _posY=0 + && _posY& _e1, const std::pair& _e2) { + return _e1.first < _e2.first; +} + + +void esvg::render::Weight::generate(ivec2 _size, int32_t _subSamplingCount, const esvg::render::SegmentList& _listSegment) { + resize(_size); + // for each lines: + for (int32_t yyy=0; yyy<_size.y(); ++yyy) { + // Reduce the number of lines in the subsampling parsing: + std::vector availlableSegmentPixel; + for (auto &it : _listSegment.m_data) { + 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/_subSamplingCount; + for (int32_t kkk=0; kkk<_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 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> 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(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 +#include +#include +#include + +namespace esvg { + namespace render { + class Weight { + private: + ivec2 m_size; + std::vector m_data; + public: + // constructor : + Weight(); + Weight(const ivec2& _size); + // destructor + ~Weight(); + // ----------------------------------------------- + // -- basic tools : + // ----------------------------------------------- + public: + void resize(const ivec2& _size); + const ivec2& getSize() const; + int32_t getWidth() const; + int32_t getHeight() const; + void clear(float _fill); + float get(const ivec2& _pos) const; + void set(const ivec2& _pos, float _newColor); + void set(int32_t _posY, const esvg::render::Scanline& _data); + void append(int32_t _posY, const esvg::render::Scanline& _data); + void generate(ivec2 _size, int32_t _subSamplingCount, const esvg::render::SegmentList& _listSegment); + }; + } +} + +#endif diff --git a/lutin_esvg.py b/lutin_esvg.py index cd543e0..c6259fb 100644 --- a/lutin_esvg.py +++ b/lutin_esvg.py @@ -53,7 +53,12 @@ def create(target, module_name): 'esvg/render/ElementSmoothCurveTo.cpp', 'esvg/render/ElementBezierCurveTo.cpp', 'esvg/render/ElementBezierSmoothCurveTo.cpp', - 'esvg/render/ElementElliptic.cpp' + 'esvg/render/ElementElliptic.cpp', + 'esvg/render/Point.cpp', + 'esvg/render/Scanline.cpp', + 'esvg/render/Segment.cpp', + 'esvg/render/SegmentList.cpp', + 'esvg/render/Weight.cpp' ]) my_module.add_header_file([ @@ -82,7 +87,11 @@ def create(target, module_name): 'esvg/render/ElementBezierSmoothCurveTo.h', 'esvg/render/ElementElliptic.h', 'esvg/render/Path.h', - 'esvg/render/Point.h' + 'esvg/render/Scanline.h', + 'esvg/render/Point.h', + 'esvg/render/Segment.h', + 'esvg/render/SegmentList.h', + 'esvg/render/Weight.h' ]) my_module.add_path(tools.get_current_path(__file__))