evas_vg_load_svg: Prevent duplicate operations on radial gradient variables

Summary:
This solves the problem of radial gradient being displayed
abnormally when the radial gradient variables are 0 to 1.

Test Plan:
Sample SVG
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <defs
     id="defs11">
    <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>
    <radialGradient id="radialGradient222" r="0.2" cx="0.3" cy="0.3" spreadMethod="reflect">
      <stop style="stop-color:#ffFF00;stop-opacity:1;" offset="0"/>
      <stop style="stop-color:#00FFff;stop-opacity:1;" offset="1"/>
    </radialGradient>
  </defs>
  <rect x="0" y="0" width="100" height="100" fill="url(#linearGradient1)"/>
  <rect x="50" y="50" width="50" height="50" fill="url(#radialGradient222)"/>
</svg>

Reviewers: Hermet, kimcinoo, smohanty

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D9312
This commit is contained in:
junsu choi 2019-07-15 21:22:03 +09:00 committed by Hermet Park
parent 01d6683e32
commit 84fcc5d073
2 changed files with 67 additions and 5 deletions

View File

@ -1758,15 +1758,63 @@ _handle_radial_r_attr(Evas_SVG_Loader *loader, Svg_Radial_Gradient* radial, cons
radial->r = _gradient_to_double(loader->svg_parse, value, SVG_PARSER_LENGTH_OTHER);
}
static void
_recalc_radial_cx_attr(Evas_SVG_Loader *loader, Svg_Radial_Gradient* radial, Eina_Bool user_space)
{
if (!user_space)
{
radial->cx = radial->cx * loader->svg_parse->global.width;
}
}
static void
_recalc_radial_cy_attr(Evas_SVG_Loader *loader, Svg_Radial_Gradient* radial, Eina_Bool user_space)
{
if (!user_space)
{
radial->cy = radial->cy * loader->svg_parse->global.height;
}
}
static void
_recalc_radial_fx_attr(Evas_SVG_Loader *loader, Svg_Radial_Gradient* radial, Eina_Bool user_space)
{
if (!user_space)
{
radial->fx = radial->fx * loader->svg_parse->global.width;
}
}
static void
_recalc_radial_fy_attr(Evas_SVG_Loader *loader, Svg_Radial_Gradient* radial, Eina_Bool user_space)
{
if (!user_space)
{
radial->fy = radial->fy * loader->svg_parse->global.height;
}
}
static void
_recalc_radial_r_attr(Evas_SVG_Loader *loader, Svg_Radial_Gradient* radial, Eina_Bool user_space)
{
if (!user_space)
{
radial->r = radial->r * (sqrt(pow(loader->svg_parse->global.height, 2) + pow(loader->svg_parse->global.width, 2)) / sqrt(2.0));
}
}
typedef void (*Radial_Method)(Evas_SVG_Loader *loader, Svg_Radial_Gradient *radial, const char *value);
typedef void (*Radial_Method_Recalc)(Evas_SVG_Loader *loader, Svg_Radial_Gradient *radial, Eina_Bool user_space);
#define RADIAL_DEF(Name) \
{ #Name, sizeof (#Name), _handle_radial_##Name##_attr}
{ #Name, sizeof (#Name), _handle_radial_##Name##_attr, _recalc_radial_##Name##_attr}
static const struct {
const char *tag;
int sz;
Radial_Method tag_handler;;
Radial_Method_Recalc tag_recalc;
} radial_tags[] = {
RADIAL_DEF(cx),
RADIAL_DEF(cy),
@ -1814,6 +1862,7 @@ _attr_parse_radial_gradient_node(void *data, const char *key, const char *value)
static Svg_Style_Gradient *
_create_radialGradient(Evas_SVG_Loader *loader, const char *buf, unsigned buflen)
{
unsigned int i = 0;
Svg_Style_Gradient *grad = calloc(1, sizeof(Svg_Style_Gradient));
loader->svg_parse->style_grad = grad;
@ -1834,6 +1883,11 @@ _create_radialGradient(Evas_SVG_Loader *loader, const char *buf, unsigned buflen
eina_simple_xml_attributes_parse(buf, buflen,
_attr_parse_radial_gradient_node, loader);
for (i = 0; i < sizeof (radial_tags) / sizeof(radial_tags[0]); i++)
radial_tags[i].tag_recalc(loader, grad->radial, grad->user_space);
grad->use_percentage = EINA_TRUE;
return loader->svg_parse->style_grad;
}

View File

@ -618,10 +618,18 @@ _apply_gradient_property(Svg_Style_Gradient *g, Efl_VG *vg, Efl_VG *parent, Vg_F
int min = (r.h > r.w) ? r.w : r.h;
radius = sqrt(pow(min, 2) + pow(min, 2)) / sqrt(2.0);
}
if (g->use_percentage)
{
g->radial->cx = g->radial->cx * r.w + r.x;
g->radial->cy = g->radial->cy * r.h + r.y;
g->radial->r = g->radial->r * radius;
g->radial->fx = g->radial->fx * r.w + r.x;
g->radial->fy = g->radial->fy * r.h + r.y;
}
grad_obj = efl_add(EFL_CANVAS_VG_GRADIENT_RADIAL_CLASS, parent);
efl_gfx_gradient_radial_center_set(grad_obj, g->radial->cx * r.w + r.x, g->radial->cy * r.h + r.y);
efl_gfx_gradient_radial_radius_set(grad_obj, g->radial->r * radius);
efl_gfx_gradient_radial_focal_set(grad_obj, g->radial->fx * r.w + r.x, g->radial->fy * r.h + r.y);
efl_gfx_gradient_radial_center_set(grad_obj, g->radial->cx, g->radial->cy);
efl_gfx_gradient_radial_radius_set(grad_obj, g->radial->r);
efl_gfx_gradient_radial_focal_set(grad_obj, g->radial->fx, g->radial->fy);
/* in case of objectBoundingBox it need proper scaling */
if (!g->user_space)
@ -955,7 +963,6 @@ _create_gradient_node(Efl_VG *vg)
if (!grad->linear) goto oom_error;
efl_gfx_gradient_linear_start_get(vg, &grad->linear->x1, &grad->linear->y1);
efl_gfx_gradient_linear_end_get(vg, &grad->linear->x2, &grad->linear->y2);
grad->use_percentage = EINA_FALSE;
}
else
{
@ -966,6 +973,7 @@ _create_gradient_node(Efl_VG *vg)
efl_gfx_gradient_radial_focal_get(vg, &grad->radial->fx, &grad->radial->fy);
grad->radial->r = efl_gfx_gradient_radial_radius_get(vg);
}
grad->use_percentage = EINA_FALSE;
return grad;