Merge "SvgLoader: Support to linear, radial gradient" into tizen

This commit is contained in:
Hermet Park 2020-07-10 00:19:51 +00:00 committed by Gerrit Code Review
commit 22581040f3
5 changed files with 279 additions and 50 deletions

View file

@ -1365,11 +1365,18 @@ static SvgNode* _findChildById(SvgNode* node, const char* id)
} }
static vector<SvgGradientStop*> _cloneGradStops(vector<SvgGradientStop*> src) static void _cloneGradStops(vector<Fill::ColorStop*> *dst, vector<Fill::ColorStop*> src)
{ {
vector<SvgGradientStop*> dst; for(vector<Fill::ColorStop*>::iterator itrStop = src.begin(); itrStop != src.end(); itrStop++) {
copy(src.begin(), src.end(), dst.begin()); Fill::ColorStop *stop = (Fill::ColorStop *)malloc(sizeof(Fill::ColorStop));
return dst; stop->r = (*itrStop)->r;
stop->g = (*itrStop)->g;
stop->b = (*itrStop)->b;
stop->a = (*itrStop)->a;
stop->offset = (*itrStop)->offset;
dst->push_back(stop);
}
} }
@ -1381,8 +1388,8 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient)); grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
grad->type = from->type; grad->type = from->type;
grad->id = _copyId(from->id->c_str()); grad->id = from->id ? _copyId(from->id->c_str()) : nullptr;
grad->ref = _copyId(from->ref->c_str()); grad->ref = from->ref ? _copyId(from->ref->c_str()) : nullptr;
grad->spread = from->spread; grad->spread = from->spread;
grad->usePercentage = from->usePercentage; grad->usePercentage = from->usePercentage;
grad->userSpace = from->userSpace; grad->userSpace = from->userSpace;
@ -1390,7 +1397,6 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
grad->transform = (Matrix*)calloc(1, sizeof(Matrix)); grad->transform = (Matrix*)calloc(1, sizeof(Matrix));
memcpy(grad->transform, from->transform, sizeof(Matrix)); memcpy(grad->transform, from->transform, sizeof(Matrix));
} }
grad->stops = _cloneGradStops(from->stops);
if (grad->type == SvgGradientType::Linear) { if (grad->type == SvgGradientType::Linear) {
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient)); grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient)); memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient));
@ -1399,6 +1405,7 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient)); memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient));
} }
_cloneGradStops(&(grad->stops), from->stops);
return grad; return grad;
} }
@ -1562,14 +1569,14 @@ FIND_FACTORY(Group, groupTags);
FIND_FACTORY(Graphics, graphicsTags); FIND_FACTORY(Graphics, graphicsTags);
SvgGradientSpread _parseSpreadValue(const char* value) FillSpread _parseSpreadValue(const char* value)
{ {
SvgGradientSpread spread = SvgGradientSpread::Pad; FillSpread spread = FillSpread::Pad;
if (!strcmp(value, "reflect")) { if (!strcmp(value, "reflect")) {
spread = SvgGradientSpread::Reflect; spread = FillSpread::Reflect;
} else if (!strcmp(value, "repeat")) { } else if (!strcmp(value, "repeat")) {
spread = SvgGradientSpread::Repeat; spread = FillSpread::Repeat;
} }
return spread; return spread;
@ -1730,7 +1737,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char
static bool _attrParseStops(void* data, const char* key, const char* value) static bool _attrParseStops(void* data, const char* key, const char* value)
{ {
SvgLoaderData* loader = (SvgLoaderData*)data; SvgLoaderData* loader = (SvgLoaderData*)data;
SvgGradientStop* stop = loader->svgParse->gradStop; Fill::ColorStop* stop = loader->svgParse->gradStop;
if (!strcmp(key, "offset")) { if (!strcmp(key, "offset")) {
stop->offset = _toOffset(value); stop->offset = _toOffset(value);
@ -2008,7 +2015,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
} }
loader->latestGradient = gradient; loader->latestGradient = gradient;
} else if (!strcmp(tagName, "stop")) { } else if (!strcmp(tagName, "stop")) {
SvgGradientStop* stop = (SvgGradientStop*)calloc(1, sizeof(SvgGradientStop)); Fill::ColorStop* stop = (Fill::ColorStop*)calloc(1, sizeof(Fill::ColorStop));
loader->svgParse->gradStop = stop; loader->svgParse->gradStop = stop;
/* default value for opacity */ /* default value for opacity */
stop->a = 255; stop->a = 255;
@ -2067,7 +2074,7 @@ static void _styleInherit(SvgStyleProperty* child, SvgStyleProperty* parent)
child->fill.paint.b = parent->fill.paint.b; child->fill.paint.b = parent->fill.paint.b;
child->fill.paint.none = parent->fill.paint.none; child->fill.paint.none = parent->fill.paint.none;
child->fill.paint.curColor = parent->fill.paint.curColor; child->fill.paint.curColor = parent->fill.paint.curColor;
child->fill.paint.url = parent->fill.paint.url ? _copyId(parent->fill.paint.url->c_str()) : nullptr; if (parent->fill.paint.url) child->fill.paint.url = _copyId(parent->fill.paint.url->c_str());
} }
if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) { if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) {
child->fill.opacity = parent->fill.opacity; child->fill.opacity = parent->fill.opacity;
@ -2109,12 +2116,12 @@ static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle)
} }
static SvgStyleGradient* _gradientDup(vector<SvgStyleGradient*> gradList, const char* id) static SvgStyleGradient* _gradientDup(vector<SvgStyleGradient*> gradList, string* id)
{ {
SvgStyleGradient* result = nullptr; SvgStyleGradient* result = nullptr;
for (vector<SvgStyleGradient*>::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) { for (vector<SvgStyleGradient*>::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) {
if ((*itrGrad)->id->compare(string(id))) { if (!((*itrGrad)->id->compare(*id))) {
result = _cloneGradient(*itrGrad); result = _cloneGradient(*itrGrad);
break; break;
} }
@ -2122,9 +2129,9 @@ static SvgStyleGradient* _gradientDup(vector<SvgStyleGradient*> gradList, const
if (result && result->ref) { if (result && result->ref) {
for (vector<SvgStyleGradient*>::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) { for (vector<SvgStyleGradient*>::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) {
if ((*itrGrad)->id->compare(*result->ref)) { if (!((*itrGrad)->id->compare(*result->ref))) {
if (!result->stops.empty()) { if (!result->stops.empty()) {
result->stops = _cloneGradStops((*itrGrad)->stops); _cloneGradStops(&(result->stops), (*itrGrad)->stops);
} }
//TODO: Properly inherit other property //TODO: Properly inherit other property
break; break;
@ -2138,15 +2145,15 @@ static SvgStyleGradient* _gradientDup(vector<SvgStyleGradient*> gradList, const
static void _updateGradient(SvgNode* node, vector<SvgStyleGradient*> gradList) static void _updateGradient(SvgNode* node, vector<SvgStyleGradient*> gradList)
{ {
if (node->child.empty()) { if (!node->child.empty()) {
for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) {
_updateGradient(*itrChild, gradList); _updateGradient(*itrChild, gradList);
} }
} else { } else {
if (node->style->fill.paint.url) { if (node->style->fill.paint.url) {
node->style->fill.paint.gradient = _gradientDup(gradList, node->style->fill.paint.url->c_str()); node->style->fill.paint.gradient = _gradientDup(gradList, node->style->fill.paint.url);
} else if (node->style->stroke.paint.url) { } else if (node->style->stroke.paint.url) {
node->style->stroke.paint.gradient = _gradientDup(gradList, node->style->stroke.paint.url->c_str()); //node->style->stroke.paint.gradient = _gradientDup(gradList, node->style->stroke.paint.url);
} }
} }
} }
@ -2161,7 +2168,7 @@ static void _freeGradientStyle(SvgStyleGradient* grad)
free(grad->linear); free(grad->linear);
if (grad->transform) free(grad->transform); if (grad->transform) free(grad->transform);
for(vector<SvgGradientStop*>::iterator itrStop = grad->stops.begin(); itrStop != grad->stops.end(); itrStop++) { for(vector<Fill::ColorStop*>::iterator itrStop = grad->stops.begin(); itrStop != grad->stops.end(); itrStop++) {
free(*itrStop); free(*itrStop);
} }
free(grad); free(grad);
@ -2284,7 +2291,9 @@ bool SvgLoader::read()
else { else {
if (!loader->loaderData.gradients.empty()) { if (!loader->loaderData.gradients.empty()) {
vector<SvgStyleGradient*> gradientList; vector<SvgStyleGradient*> gradientList;
std::copy(loader->loaderData.gradients.begin(), loader->loaderData.gradients.end(), gradientList.begin()); for(vector<SvgStyleGradient*>::iterator itrGrad = loader->loaderData.gradients.begin(); itrGrad != loader->loaderData.gradients.end(); itrGrad++) {
gradientList.push_back(*itrGrad);
}
_updateGradient(loader->loaderData.doc, gradientList); _updateGradient(loader->loaderData.doc, gradientList);
gradientList.clear(); gradientList.clear();
} }

View file

@ -97,14 +97,6 @@ enum class SvgStyleType
CompOp CompOp
}; };
enum class SvgGradientSpread
{
Pad = 0,
Reflect,
Repeat,
Last
};
enum class SvgFillRule enum class SvgFillRule
{ {
Winding = 0, Winding = 0,
@ -240,11 +232,11 @@ struct _SvgStyleGradient
SvgGradientType type; SvgGradientType type;
string *id; string *id;
string *ref; string *ref;
SvgGradientSpread spread; FillSpread spread;
vector<SvgGradientStop *> stops;
SvgRadialGradient* radial; SvgRadialGradient* radial;
SvgLinearGradient* linear; SvgLinearGradient* linear;
Matrix* transform; Matrix* transform;
vector<Fill::ColorStop *> stops;
bool userSpace; bool userSpace;
bool usePercentage; bool usePercentage;
}; };
@ -309,7 +301,7 @@ struct SvgParser
{ {
SvgNode* node; SvgNode* node;
SvgStyleGradient* styleGrad; SvgStyleGradient* styleGrad;
SvgGradientStop* gradStop; Fill::ColorStop* gradStop;
struct struct
{ {
int x, y; int x, y;

View file

@ -40,7 +40,188 @@ static void _getTransformationData(Matrix* m, float* tx, float* ty, float* s, fl
} }
unique_ptr<tvg::Shape> _applyProperty(SvgNode* node, unique_ptr<tvg::Shape> vg) unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient* g, Shape* vg, float rx, float ry, float rw, float rh)
{
Fill::ColorStop* stops;
int stopCount = 0;
float fillOpacity = 255.0f;
float gx, gy, gw, gh;
auto fillGrad = LinearGradient::gen();
if (g->usePercentage) {
g->linear->x1 = g->linear->x1 * rw + rx;
g->linear->y1 = g->linear->y1 * rh + ry;
g->linear->x2 = g->linear->x2 * rw + rx;
g->linear->y2 = g->linear->y2 * rh + ry;
}
//In case of objectBoundingBox it need proper scaling
if (!g->userSpace) {
float scaleX = 1.0, scaleReversedX = 1.0;
float scaleY = 1.0, scaleReversedY = 1.0;
//Check the smallest size, find the scale value
if (rh > rw) {
scaleY = ((float)rw) / rh;
scaleReversedY = ((float)rh) / rw;
} else {
scaleX = ((float)rh) / rw;
scaleReversedX = ((float)rw) / rh;
}
vg->bounds(&gx, &gy, &gw, &gh);
float cy = ((float)gh) * 0.5 + gy;
float cy_scaled = (((float)gh) * 0.5) * scaleReversedY;
float cx = ((float)gw) * 0.5 + gx;
float cx_scaled = (((float)gw) * 0.5) * scaleReversedX;
//= T(gx, gy) x S(scaleX, scaleY) x T(cx_scaled - cx, cy_scaled - cy) x (radial->x, radial->y)
g->linear->x1 = g->linear->x1 * scaleX + scaleX * (cx_scaled - cx) + gx;
g->linear->y1 = g->linear->y1 * scaleY + scaleY * (cy_scaled - cy) + gy;
g->linear->x2 = g->linear->x2 * scaleX + scaleX * (cx_scaled - cx) + gx;
g->linear->y2 = g->linear->y2 * scaleY + scaleY * (cy_scaled - cy) + gy;
}
if (g->transform) {
float cy = ((float) rh) * 0.5 + ry;
float cx = ((float) rw) * 0.5 + rx;
//Calc start point
//= T(x - cx, y - cy) x g->transform x T(cx, cy)
g->linear->x1 = cx * (g->transform->e11 + g->transform->e31 * (g->linear->x1 - cx)) +
cx * (g->transform->e12 + g->transform->e32 * (g->linear->x1 - cx)) +
cx * (g->transform->e13 + g->transform->e33 * (g->linear->x1 - cx));
g->linear->y1 = cy * (g->transform->e21 + g->transform->e31 * (g->linear->y1 - cy)) +
cy * (g->transform->e22 + g->transform->e32 * (g->linear->y1 - cy)) +
cy * (g->transform->e23 + g->transform->e33 * (g->linear->y1 - cy));
//Calc end point
g->linear->x2 = cx * (g->transform->e11 + g->transform->e31 * (g->linear->x2 - cx)) +
cx * (g->transform->e12 + g->transform->e32 * (g->linear->x2 - cx)) +
cx * (g->transform->e13 + g->transform->e33 * (g->linear->x2 - cx));
g->linear->y2 = cy * (g->transform->e21 + g->transform->e31 * (g->linear->y2 - cy)) +
cy * (g->transform->e22 + g->transform->e32 * (g->linear->y2 - cy)) +
cy * (g->transform->e23 + g->transform->e33 * (g->linear->y2 - cy));
}
fillGrad->linear(g->linear->x1, g->linear->y1, g->linear->x2, g->linear->y2);
fillGrad->spread(g->spread);
//Update the stops
stopCount = g->stops.size();
if (stopCount > 0) {
float opacity;
float fopacity = fillOpacity / 255.0f; //fill opacity if any exists.
int i = 0;
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
for (vector<Fill::ColorStop*>::iterator itrStop = g->stops.begin(); itrStop != g->stops.end(); itrStop++) {
//Use premultiplied color
opacity = ((float)(*itrStop)->a / 255) * fopacity;
stops[i].r = ((*itrStop)->r * opacity);
stops[i].g = ((*itrStop)->g * opacity);
stops[i].b = ((*itrStop)->b * opacity);
stops[i].a = ((*itrStop)->a * fopacity);
stops[i].offset = (*itrStop)->offset;
i++;
}
fillGrad->colorStops(stops, stopCount);
free(stops);
}
return move(fillGrad);
}
unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient* g, Shape* vg, float rx, float ry, float rw, float rh)
{
Fill::ColorStop *stops;
int stopCount = 0;
float gx, gy, gw, gh;
int radius;
float fillOpacity = 255.0f;
auto fillGrad = RadialGradient::gen();
radius = sqrt(pow(rw, 2) + pow(rh, 2)) / sqrt(2.0);
if (!g->userSpace) {
//That is according to Units in here
//https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html
int min = (rh > rw) ? rw : rh;
radius = sqrt(pow(min, 2) + pow(min, 2)) / sqrt(2.0);
}
if (g->usePercentage) {
g->radial->cx = g->radial->cx * rw + rx;
g->radial->cy = g->radial->cy * rh + ry;
g->radial->r = g->radial->r * radius;
g->radial->fx = g->radial->fx * rw + rx;
g->radial->fy = g->radial->fy * rh + ry;
}
//In case of objectBoundingBox it need proper scaling
if (!g->userSpace) {
float scaleX = 1.0, scaleReversedX = 1.0;
float scaleY = 1.0, scaleReversedY = 1.0;
//Check the smallest size, find the scale value
if (rh > rw) {
scaleY = ((float)rw) / rh;
scaleReversedY = ((float)rh) / rw;
} else {
scaleX = ((float)rh) / rw;
scaleReversedX = ((float)rw) / rh;
}
vg->bounds(&gx, &gy, &gw, &gh);
float cy = ((float)gh) * 0.5 + gy;
float cy_scaled = (((float)gh) * 0.5) * scaleReversedY;
float cx = ((float)gw) * 0.5 + gx;
float cx_scaled = (((float)gw) * 0.5) * scaleReversedX;
//= T(gx, gy) x S(scaleX, scaleY) x T(cx_scaled - cx, cy_scaled - cy) x (radial->x, radial->y)
g->radial->cx = g->radial->cx * scaleX + scaleX * (cx_scaled - cx) + gx;
g->radial->cy = g->radial->cy * scaleY + scaleY * (cy_scaled - cy) + gy;
}
//TODO: Radial gradient transformation is not yet supported.
//if (g->transform) {}
//TODO: Tvg is not support to focal
//if (g->radial->fx != 0 && g->radial->fy != 0) {
// fillGrad->radial(g->radial->fx, g->radial->fy, g->radial->r);
//}
fillGrad->radial(g->radial->cx, g->radial->cy, g->radial->r);
fillGrad->spread(g->spread);
//Update the stops
stopCount = g->stops.size();
if (stopCount > 0) {
float opacity;
float fopacity = fillOpacity / 255.0f; //fill opacity if any exists.
int i = 0;
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
for (vector<Fill::ColorStop*>::iterator itrStop = g->stops.begin(); itrStop != g->stops.end(); itrStop++) {
//Use premultiplied color
opacity = ((float)(*itrStop)->a / 255) * fopacity;
stops[i].r = ((*itrStop)->r * opacity);
stops[i].g = ((*itrStop)->g * opacity);
stops[i].b = ((*itrStop)->b * opacity);
stops[i].a = ((*itrStop)->a * fopacity);
stops[i].offset = (*itrStop)->offset;
i++;
}
fillGrad->colorStops(stops, stopCount);
free(stops);
}
return move(fillGrad);
}
unique_ptr<Shape> _applyProperty(SvgNode* node, unique_ptr<Shape> vg, float vx, float vy, float vw, float vh)
{ {
SvgStyleProperty* style = node->style; SvgStyleProperty* style = node->style;
@ -59,7 +240,15 @@ unique_ptr<tvg::Shape> _applyProperty(SvgNode* node, unique_ptr<tvg::Shape> vg)
if (style->fill.paint.none) { if (style->fill.paint.none) {
//Do nothing //Do nothing
} else if (style->fill.paint.gradient) { } else if (style->fill.paint.gradient) {
//TODO: Support gradient style if (!style->fill.paint.gradient->userSpace) vg->bounds(&vx, &vy, &vw, &vh);
if (style->fill.paint.gradient->type == SvgGradientType::Linear) {
auto linear = _applyLinearGradientProperty(style->fill.paint.gradient, vg.get(), vx, vy, vw, vh);
vg->fill(move(linear));
} else if (style->fill.paint.gradient->type == SvgGradientType::Radial) {
auto radial = _applyRadialGradientProperty(style->fill.paint.gradient, vg.get(), vx, vy, vw, vh);
vg->fill(move(radial));
}
} else if (style->fill.paint.curColor) { } else if (style->fill.paint.curColor) {
//Apply the current style color //Apply the current style color
float fa = ((float)style->fill.opacity / 255.0); float fa = ((float)style->fill.opacity / 255.0);
@ -113,9 +302,9 @@ unique_ptr<tvg::Shape> _applyProperty(SvgNode* node, unique_ptr<tvg::Shape> vg)
} }
unique_ptr<tvg::Shape> _shapeBuildHelper(SvgNode* node) unique_ptr<Shape> _shapeBuildHelper(SvgNode* node, float vx, float vy, float vw, float vh)
{ {
auto shape = tvg::Shape::gen(); auto shape = Shape::gen();
switch (node->type) { switch (node->type) {
case SvgNodeType::Path: { case SvgNodeType::Path: {
if (node->node.path.path) { if (node->node.path.path) {
@ -162,15 +351,15 @@ unique_ptr<tvg::Shape> _shapeBuildHelper(SvgNode* node)
break; break;
} }
} }
shape = move(_applyProperty(node, move(shape))); shape = move(_applyProperty(node, move(shape), vx, vy, vw, vh));
return shape; return shape;
} }
unique_ptr<tvg::Scene> _sceneBuildHelper(SvgNode* node) unique_ptr<Scene> _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, float vh)
{ {
if (node->type == SvgNodeType::Doc || node->type == SvgNodeType::G) { if (node->type == SvgNodeType::Doc || node->type == SvgNodeType::G) {
auto scene = tvg::Scene::gen(); auto scene = Scene::gen();
if (node->transform) { if (node->transform) {
float tx = 0, ty = 0, s = 0, z = 0; float tx = 0, ty = 0, s = 0, z = 0;
_getTransformationData(node->transform, &tx, &ty, &s, &z); _getTransformationData(node->transform, &tx, &ty, &s, &z);
@ -180,8 +369,8 @@ unique_ptr<tvg::Scene> _sceneBuildHelper(SvgNode* node)
} }
for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) {
SvgNode* child = *itrChild; SvgNode* child = *itrChild;
if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild)); if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild, vx, vy, vw, vh));
else scene->push(_shapeBuildHelper(*itrChild)); else scene->push(_shapeBuildHelper(*itrChild, vx, vy, vw, vh));
} }
return move(scene); return move(scene);
} }
@ -209,7 +398,7 @@ unique_ptr<Scene> SvgSceneBuilder::build(SvgNode* node)
viewBox.h = node->node.doc.vh; viewBox.h = node->node.doc.vh;
preserveAspect = node->node.doc.preserveAspect; preserveAspect = node->node.doc.preserveAspect;
staticViewBox = true; staticViewBox = true;
return _sceneBuildHelper(node); return _sceneBuildHelper(node, viewBox.x, viewBox.y, viewBox.w, viewBox.h);
} }

20
test/svgs/lineargrad1.svg Normal file
View file

@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs
id="defs4">
<linearGradient
id="linearGradient1"
x1="0"
y1="0"
x2="0.2"
y2="0.2"
spreadMethod="reflect">
<stop
style="stop-color:#ff0000;stop-opacity:1;"
offset="0"/>
<stop
style="stop-color:#0000ff;stop-opacity:1;"
offset="1"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="100" height="100" fill="url(#linearGradient1)"/>
</svg>

After

Width:  |  Height:  |  Size: 514 B

19
test/svgs/radialgrad1.svg Normal file
View file

@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs
id="defs4">
<radialGradient
id="radialGradient1"
r="0.2"
cx="0.3"
cy="0.3"
spreadMethod="reflect">
<stop
style="stop-color:#ff0000;stop-opacity:1;"
offset="0"/>
<stop
style="stop-color:#0000ff;stop-opacity:1;"
offset="1"/>
</radialGradient>
</defs>
<rect x="0" y="0" width="100" height="100" fill="url(#radialGradient1)"/>
</svg>

After

Width:  |  Height:  |  Size: 501 B