186 lines
5.8 KiB
C++
186 lines
5.8 KiB
C++
/** @file
|
|
* @author Edouard DUPIN
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
* @license MPL v2.0 (see license file)
|
|
*/
|
|
|
|
#include <esvg/debug.hpp>
|
|
#include <esvg/LinearGradient.hpp>
|
|
#include <esvg/RadialGradient.hpp>
|
|
#include <esvg/render/Path.hpp>
|
|
#include <esvg/render/Weight.hpp>
|
|
#include <esvg/esvg.hpp>
|
|
|
|
esvg::RadialGradient::RadialGradient(PaintState _parentPaintState) :
|
|
esvg::Base(_parentPaintState),
|
|
m_center(vec2(50,50), esvg::distance_pourcent),
|
|
m_radius(50, esvg::distance_pourcent),
|
|
m_focal(vec2(50,50), esvg::distance_pourcent),
|
|
m_unit(gradientUnits_objectBoundingBox),
|
|
m_spread(spreadMethod_pad) {
|
|
|
|
}
|
|
|
|
esvg::RadialGradient::~RadialGradient() {
|
|
|
|
}
|
|
|
|
|
|
bool esvg::RadialGradient::parseXML(const exml::Element& _element, mat2x3& _parentTrans, vec2& _sizeMax) {
|
|
// line must have a minimum size...
|
|
//m_paint.strokeWidth = 1;
|
|
if (_element.exist() == false) {
|
|
return false;
|
|
}
|
|
|
|
// ---------------- get unique ID ----------------
|
|
m_id = _element.attributes["id"];
|
|
|
|
//parseTransform(_element);
|
|
//parsePaintAttr(_element);
|
|
|
|
// add the property of the parrent modifications ...
|
|
m_transformMatrix *= _parentTrans;
|
|
|
|
etk::String contentX = _element.attributes["cx"];
|
|
etk::String contentY = _element.attributes["cy"];
|
|
if ( contentX != ""
|
|
&& contentY != "") {
|
|
m_center.set(contentX, contentY);
|
|
}
|
|
contentX = _element.attributes["r"];
|
|
if (contentX != "") {
|
|
m_radius.set(contentX);
|
|
}
|
|
contentX = _element.attributes["fx"];
|
|
contentY = _element.attributes["fy"];
|
|
if ( contentX != ""
|
|
&& contentY != "") {
|
|
m_focal.set(contentX, contentY);
|
|
}
|
|
contentX = _element.attributes["gradientUnits"];
|
|
if (contentX == "userSpaceOnUse") {
|
|
m_unit = gradientUnits_userSpaceOnUse;
|
|
} else {
|
|
m_unit = gradientUnits_objectBoundingBox;
|
|
if ( contentX.size() != 0
|
|
&& contentX != "objectBoundingBox") {
|
|
ESVG_ERROR("Parsing error of 'gradientUnits' ==> not suported value: '" << contentX << "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
|
}
|
|
}
|
|
contentX = _element.attributes["spreadMethod"];
|
|
if (contentX == "reflect") {
|
|
m_spread = spreadMethod_reflect;
|
|
} else if (contentX == "repeat") {
|
|
m_spread = spreadMethod_repeat;
|
|
} else {
|
|
m_spread = spreadMethod_pad;
|
|
if ( contentX.size() != 0
|
|
&& contentX != "pad") {
|
|
ESVG_ERROR("Parsing error of 'spreadMethod' ==> not suported value: '" << contentX << "' not in : {reflect/repeate/pad} use pad");
|
|
}
|
|
}
|
|
// note: xlink:href is incompatible with subNode "stop"
|
|
m_href = _element.attributes["xlink:href"];
|
|
if (m_href.size() != 0) {
|
|
m_href = etk::String(m_href.begin()+1, m_href.end());
|
|
}
|
|
// parse all sub node :
|
|
for(auto it : _element.nodes) {
|
|
exml::Element child = it.toElement();
|
|
if (child.exist() == false) {
|
|
// can be a comment ...
|
|
continue;
|
|
}
|
|
if (child.getValue() == "stop") {
|
|
float offset = 100;
|
|
etk::Color<float,4> stopColor = etk::color::none;
|
|
etk::String content = child.attributes["offset"];
|
|
if (content.size()!=0) {
|
|
etk::Pair<float, enum esvg::distance> tmp = parseLength2(content);
|
|
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;
|
|
}
|
|
}
|
|
content = child.attributes["stop-color"];
|
|
if (content.size()!=0) {
|
|
stopColor = parseColor(content).first;
|
|
ESVG_VERBOSE(" color : \"" << content << "\" == > " << stopColor);
|
|
}
|
|
content = child.attributes["stop-opacity"];
|
|
if (content.size()!=0) {
|
|
float opacity = parseLength(content);
|
|
opacity = etk::avg(0.0f, opacity, 1.0f);
|
|
stopColor.setA(opacity);
|
|
ESVG_VERBOSE(" opacity : '" << content << "' == > " << stopColor);
|
|
}
|
|
m_data.pushBack(etk::Pair<float, etk::Color<float,4>>(offset, stopColor));
|
|
} else {
|
|
ESVG_ERROR("(l " << child.getPos() << ") node not suported : '" << child.getValue() << "' must be [stop]");
|
|
}
|
|
}
|
|
if (m_data.size() != 0) {
|
|
if (m_href != "") {
|
|
ESVG_ERROR("(l " << _element.getPos() << ") node can not have an xlink:href element with sub node named: stop ==> removing href");
|
|
m_href = "";
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void esvg::RadialGradient::display(int32_t _spacing) {
|
|
ESVG_DEBUG(spacingDist(_spacing) << "RadialGradient center=" << m_center << " focal=" << m_focal << " radius=" << m_radius);
|
|
for (auto &it : m_data) {
|
|
ESVG_DEBUG(spacingDist(_spacing+1) << "STOP: offset=" << it.first << " color=" << it.second);
|
|
}
|
|
}
|
|
|
|
void esvg::RadialGradient::draw(esvg::Renderer& _myRenderer, mat2x3& _basicTrans, int32_t _level) {
|
|
ESVG_VERBOSE(spacingDist(_level) << "DRAW esvg::RadialGradient");
|
|
}
|
|
|
|
const esvg::Dimension& esvg::RadialGradient::getCenter() {
|
|
return m_center;
|
|
}
|
|
|
|
const esvg::Dimension& esvg::RadialGradient::getFocal() {
|
|
return m_focal;
|
|
}
|
|
|
|
const esvg::Dimension1D& esvg::RadialGradient::getRadius() {
|
|
return m_radius;
|
|
}
|
|
|
|
const etk::Vector<etk::Pair<float, etk::Color<float,4>>>& esvg::RadialGradient::getColors(esvg::Document* _document) {
|
|
if (m_href == "") {
|
|
return m_data;
|
|
}
|
|
if (_document == null) {
|
|
ESVG_ERROR("Get null input for document");
|
|
return m_data;
|
|
}
|
|
ememory::SharedPtr<esvg::Base> base = _document->getReference(m_href);
|
|
if (base == null) {
|
|
ESVG_ERROR("Can not get base : '" << m_href << "'");
|
|
return m_data;
|
|
}
|
|
ememory::SharedPtr<esvg::RadialGradient> gradientR = ememory::dynamicPointerCast<esvg::RadialGradient>(base);
|
|
if (gradientR == null) {
|
|
ememory::SharedPtr<esvg::LinearGradient> gradientL = ememory::dynamicPointerCast<esvg::LinearGradient>(base);
|
|
if (gradientL == null) {
|
|
ESVG_ERROR("Can not cast in a linear/radial gradient: '" << m_href << "' ==> wrong type");
|
|
return m_data;
|
|
}
|
|
return gradientL->getColors(_document);
|
|
}
|
|
return gradientR->getColors(_document);
|
|
}
|
|
|
|
|
|
|