[DEV] add methodologie of gradient

This commit is contained in:
Edouard DUPIN 2015-12-18 20:50:24 +01:00
parent 3bba1c8ba4
commit e464194e37
6 changed files with 52 additions and 8 deletions

View File

@ -102,7 +102,8 @@ static enum esvg::distance parseType(std::string& _config) {
type = esvg::distance_meter;
_config.erase(_config.size()-1, 1);
} else {
ESVG_CRITICAL("Can not parse dimention : \"" << _config << "\"");
type = esvg::distance_pixel;
ESVG_VERBOSE("default dimention type for: '" << _config << "' ==> pixel");
}
return type;
}

View File

@ -53,6 +53,18 @@ bool esvg::LinearGradient::parseXML(const std::shared_ptr<exml::Element>& _eleme
&& contentY != "") {
m_pos2.set(contentX, contentY);
}
contentX = _element->getAttribute("gradientUnits");
if (contentX == "userSpaceOnUse") {
m_unit = gradientUnits_userSpaceOnUse;
} else if (contentX == "objectBoundingBox") {
m_unit = gradientUnits_objectBoundingBox;
} else {
// by default we will use "objectBoundingBox"
m_unit = gradientUnits_objectBoundingBox;
if (contentX.size() != 0) {
ESVG_ERROR("Parsing error of 'gradientUnits' ==> not suported value: '" << contentX << "' not in : {userSpaceOnUse/objectBoundingBox}");
}
}
// note: xlink:href is incompatible with subNode "stop"
m_href = _element->getAttribute("xlink:href");
if (m_href.size() != 0) {
@ -71,7 +83,10 @@ bool esvg::LinearGradient::parseXML(const std::shared_ptr<exml::Element>& _eleme
std::string content = child->getAttribute("offset");
if (content.size()!=0) {
std::pair<float, enum esvg::distance> tmp = parseLength2(content);
if (tmp.second != esvg::distance_pourcent) {
if (tmp.second == esvg::distance_pixel) {
// special case ==> all time % then no type define ==> % in [0.0 .. 1.0]
offset = tmp.first*100.0f;
} else if (tmp.second != esvg::distance_pourcent) {
ESVG_ERROR("offset : " << content << " res=" << tmp.first << "," << tmp.second << " Not support other than pourcent %");
} else {
offset = tmp.first;

View File

@ -13,10 +13,17 @@
namespace esvg {
class Document;
enum gradientUnits {
gradientUnits_userSpaceOnUse,
gradientUnits_objectBoundingBox
};
class LinearGradient : public esvg::Base {
private:
esvg::Dimension m_pos1; //!< gradient position x1 y1
esvg::Dimension m_pos2; //!< gradient position x2 y2
public:
enum gradientUnits m_unit;
private:
std::string m_href; //!< in case of using a single gradient in multiple gradient, the gradient is store in an other element...
std::vector<std::pair<float, etk::Color<float,4>>> m_data; //!< incompatible with href
public:

View File

@ -48,15 +48,16 @@ etk::Color<float,4> esvg::render::DynamicColorLinear::getColor(const ivec2& _pos
if (m_data.size() < 2) {
return etk::color::purple;
}
#if 0
float ratio = 0.0f;
if (m_boundingBoxMode == false) {
vec2 vectorBase = m_pos2 - m_pos1;
vec2 vectorOrtho(vectorBase.y(), -vectorBase.x());
vec2 intersec = getIntersect(m_pos1, vectorBase,
vec2(_pos.x(), _pos.y()), vectorOrtho);
float baseSize = vectorBase.length();
float baseDraw = (m_pos1 - intersec).length();
float ratio = baseDraw / baseSize;
#else
ratio = baseDraw / baseSize;
} else {
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
vec2 intersecX = getIntersect(m_pos1, m_axeX,
vec2(_pos.x(), _pos.y()), m_axeY);
@ -64,7 +65,6 @@ etk::Color<float,4> esvg::render::DynamicColorLinear::getColor(const ivec2& _pos
vec2(_pos.x(), _pos.y()), m_axeX);
float baseDrawX = (m_pos1 - intersecX).length();
float baseDrawY = (m_pos1 - intersecY).length();
float ratio = 0.0f;
if (m_baseSize.x() != 0.0f) {
if (m_baseSize.y() != 0.0f) {
ratio += baseDrawX/m_baseSize.x() * 0.5f;
@ -79,7 +79,7 @@ etk::Color<float,4> esvg::render::DynamicColorLinear::getColor(const ivec2& _pos
ratio += baseDrawY/m_baseSize.y();
}
}
#endif
}
//ESVG_DEBUG("plop " << ratio);
if (ratio <= m_data[0].first*0.01f) {
return m_data[0].second;
@ -87,7 +87,6 @@ etk::Color<float,4> esvg::render::DynamicColorLinear::getColor(const ivec2& _pos
if (ratio >= m_data.back().first*0.01f) {
return m_data.back().second;
}
for (size_t iii=1; iii<m_data.size(); ++iii) {
if (ratio <= m_data[iii].first*0.01f) {
float localRatio = ratio - m_data[iii-1].first*0.01f;
@ -118,6 +117,7 @@ void esvg::render::DynamicColorLinear::generate(esvg::Document* _document) {
}
ESVG_INFO("get for color linear:");
gradient->display(2);
m_boundingBoxMode = gradient->m_unit == esvg::gradientUnits_objectBoundingBox;
ESVG_INFO(" viewport = {" << m_viewPort.first << "," << m_viewPort.second << "}");
vec2 size = m_viewPort.second - m_viewPort.first;

View File

@ -48,6 +48,7 @@ namespace esvg {
};
class DynamicColorLinear : public esvg::render::DynamicColor {
public:
bool m_boundingBoxMode;
std::string m_colorName;
mat2 m_matrix;
std::pair<vec2, vec2> m_viewPort;

View File

@ -187,3 +187,23 @@ TEST(TestGradientLinear, internalHref) {
etk::FSNodeWriteAllData("TestGradientLinear_internalHref.svg", data);
doc.generateAnImage(ivec2(100, 100), "TestGradientLinear_internalHref.bmp", g_visualDebug);
}
TEST(TestGradientLinear, inkscape) {
std::string data("<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
"<svg height='100' width='100'>\n"
" <defs>\n"
" <linearGradient id='grad2Values'>\n"
" <stop offset='0' style='stop-color:#ba4f4f;stop-opacity:1' />\n"
" <stop offset='1' style='stop-color:#57ba4f;stop-opacity:1' />\n"
" </linearGradient>\n"
" <linearGradient id='grad2' x1='40.653418' y1='63.601116' x2='71.911972' y2='47.372902' gradientUnits='userSpaceOnUse' xlink:href='#grad2Values' />\n"
" </defs>\n"
" <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
"</svg>\n");
esvg::Document doc;
doc.parse(data);
etk::FSNodeWriteAllData("TestGradientLinear_inkscape.svg", data);
doc.generateAnImage(ivec2(100, 100), "TestGradientLinear_inkscape.bmp", g_visualDebug);
}