[DEV] all basic class and separators are here ... (good job)
This commit is contained in:
parent
9b64e85733
commit
bed717cae9
410
esvg/Path.cpp
410
esvg/Path.cpp
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <esvg/debug.h>
|
#include <esvg/debug.h>
|
||||||
#include <esvg/Path.h>
|
#include <esvg/Path.h>
|
||||||
|
#include <esvg/render/Weight.h>
|
||||||
|
|
||||||
#undef __class__
|
#undef __class__
|
||||||
#define __class__ "Path"
|
#define __class__ "Path"
|
||||||
@ -246,400 +247,6 @@ void esvg::Path::display(int32_t _spacing) {
|
|||||||
m_listElement.display(_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<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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void addSegment(std::vector<Segment>& _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<Segment> createSegmentList(const std::vector<esvg::render::Point>& _listPoint) {
|
|
||||||
std::vector<Segment> 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<Segment> createSegmentListStroke(std::vector<esvg::render::Point>& _listPoint) {
|
|
||||||
std::vector<Segment> 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<Segment>& _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<Segment> 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<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::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
void esvg::Path::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) {
|
||||||
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Path");
|
SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Path");
|
||||||
int32_t recurtionMax = 10;
|
int32_t recurtionMax = 10;
|
||||||
@ -648,22 +255,23 @@ void esvg::Path::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _l
|
|||||||
|
|
||||||
mat2 mtx = m_transformMatrix;
|
mat2 mtx = m_transformMatrix;
|
||||||
mtx *= _basicTrans;
|
mtx *= _basicTrans;
|
||||||
Weighter tmpFill;
|
esvg::render::Weight tmpFill;
|
||||||
Weighter tmpStroke;
|
esvg::render::Weight tmpStroke;
|
||||||
// Check if we need to display background
|
// Check if we need to display background
|
||||||
int32_t nbSubScanLine = 8;
|
int32_t nbSubScanLine = 8;
|
||||||
if (m_paint.fill.a() != 0x00) {
|
if (m_paint.fill.a() != 0x00) {
|
||||||
|
esvg::render::SegmentList listSegment;
|
||||||
std::vector<Segment> listSegment = createSegmentList(listPoints);
|
listSegment.createSegmentList(listPoints);
|
||||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||||
tmpFill = createWeighter(ivec2(128,128), nbSubScanLine, listSegment);
|
tmpFill.generate(ivec2(128,128), nbSubScanLine, listSegment);
|
||||||
}
|
}
|
||||||
// check if we need to display stroke:
|
// check if we need to display stroke:
|
||||||
if ( m_paint.strokeWidth > 0
|
if ( m_paint.strokeWidth > 0
|
||||||
&& m_paint.stroke.a() != 0x00) {
|
&& m_paint.stroke.a() != 0x00) {
|
||||||
std::vector<Segment> 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
|
// 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:
|
// add on images:
|
||||||
for (int32_t yyy=0; yyy<_myRenderer.m_size.y(); ++yyy) {
|
for (int32_t yyy=0; yyy<_myRenderer.m_size.y(); ++yyy) {
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esvg/render/Point.h>
|
||||||
|
#include <esvg/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
@ -35,26 +35,8 @@ namespace esvg {
|
|||||||
m_type(_type) {
|
m_type(_type) {
|
||||||
// nothing to do ...
|
// nothing to do ...
|
||||||
}
|
}
|
||||||
void setEndPath() {
|
void setEndPath();
|
||||||
if (m_type == esvg::render::Point::type_interpolation) {
|
void normalize(const vec2& _nextPoint);
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
esvg/render/Scanline.cpp
Normal file
41
esvg/render/Scanline.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esvg/render/Scanline.h>
|
||||||
|
#include <esvg/debug.h>
|
||||||
|
|
||||||
|
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<m_data.size()) {
|
||||||
|
return m_data[_pos];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esvg::render::Scanline::set(int32_t _pos, float _newColor) {
|
||||||
|
if( _pos>=0
|
||||||
|
&& _pos<m_data.size()) {
|
||||||
|
m_data[_pos] = _newColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
34
esvg/render/Scanline.h
Normal file
34
esvg/render/Scanline.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ESVG_RENDER_SCANLINE_H__
|
||||||
|
#define __ESVG_RENDER_SCANLINE_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
#include <etk/math/Vector2D.h>
|
||||||
|
|
||||||
|
namespace esvg {
|
||||||
|
namespace render {
|
||||||
|
class Scanline {
|
||||||
|
private:
|
||||||
|
std::vector<float> 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
|
26
esvg/render/Segment.cpp
Normal file
26
esvg/render/Segment.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esvg/render/Segment.h>
|
||||||
|
#include <esvg/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
27
esvg/render/Segment.h
Normal file
27
esvg/render/Segment.h
Normal file
@ -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 <etk/types.h>
|
||||||
|
#include <etk/math/Vector2D.h>
|
||||||
|
|
||||||
|
namespace esvg {
|
||||||
|
namespace render {
|
||||||
|
class Segment {
|
||||||
|
public:
|
||||||
|
Segment(const vec2& _p0, const vec2& _p1);
|
||||||
|
vec2 p0;
|
||||||
|
vec2 p1;
|
||||||
|
float direction;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
193
esvg/render/SegmentList.cpp
Normal file
193
esvg/render/SegmentList.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esvg/render/SegmentList.h>
|
||||||
|
#include <esvg/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
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<esvg::render::Point>& _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<esvg::render::Point>& _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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
31
esvg/render/SegmentList.h
Normal file
31
esvg/render/SegmentList.h
Normal file
@ -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 <etk/types.h>
|
||||||
|
#include <etk/math/Vector2D.h>
|
||||||
|
#include <esvg/render/Segment.h>
|
||||||
|
#include <esvg/render/Point.h>
|
||||||
|
|
||||||
|
namespace esvg {
|
||||||
|
namespace render {
|
||||||
|
class SegmentList {
|
||||||
|
public:
|
||||||
|
std::vector<esvg::render::Segment> m_data;
|
||||||
|
public:
|
||||||
|
SegmentList();
|
||||||
|
void addSegment(const esvg::render::Point& _pos0, const esvg::render::Point& _pos1);
|
||||||
|
void createSegmentList(const std::vector<esvg::render::Point>& _listPoint);
|
||||||
|
void createSegmentListStroke(std::vector<esvg::render::Point>& _listPoint);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
171
esvg/render/Weight.cpp
Normal file
171
esvg/render/Weight.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esvg/render/Weight.h>
|
||||||
|
#include <esvg/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
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; iii<m_size.x()*m_size.y(); iii++) {
|
||||||
|
m_data[iii] = _fill;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float esvg::render::Weight::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 esvg::render::Weight::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 esvg::render::Weight::set(int32_t _posY, const esvg::render::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 esvg::render::Weight::append(int32_t _posY, const esvg::render::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 sortXPosFunction(const std::pair<float,float>& _e1, const std::pair<float,float>& _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<Segment> 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<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
append(yyy, scanline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
esvg/render/Weight.h
Normal file
47
esvg/render/Weight.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
*
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
*
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ESVG_RENDER_WEIGTH_H__
|
||||||
|
#define __ESVG_RENDER_WEIGTH_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
#include <etk/math/Vector2D.h>
|
||||||
|
#include <esvg/render/Scanline.h>
|
||||||
|
#include <esvg/render/SegmentList.h>
|
||||||
|
|
||||||
|
namespace esvg {
|
||||||
|
namespace render {
|
||||||
|
class Weight {
|
||||||
|
private:
|
||||||
|
ivec2 m_size;
|
||||||
|
std::vector<float> 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
|
@ -53,7 +53,12 @@ def create(target, module_name):
|
|||||||
'esvg/render/ElementSmoothCurveTo.cpp',
|
'esvg/render/ElementSmoothCurveTo.cpp',
|
||||||
'esvg/render/ElementBezierCurveTo.cpp',
|
'esvg/render/ElementBezierCurveTo.cpp',
|
||||||
'esvg/render/ElementBezierSmoothCurveTo.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([
|
my_module.add_header_file([
|
||||||
@ -82,7 +87,11 @@ def create(target, module_name):
|
|||||||
'esvg/render/ElementBezierSmoothCurveTo.h',
|
'esvg/render/ElementBezierSmoothCurveTo.h',
|
||||||
'esvg/render/ElementElliptic.h',
|
'esvg/render/ElementElliptic.h',
|
||||||
'esvg/render/Path.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__))
|
my_module.add_path(tools.get_current_path(__file__))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user