loader/svg: support the focal property in the radial gradient.

@Issue: https://github.com/thorvg/thorvg/issues/1555
This commit is contained in:
Mira Grudzinska 2023-09-04 16:38:47 +09:00 committed by Hermet Park
parent ce3c11838c
commit fd014df1a9
3 changed files with 41 additions and 8 deletions

View file

@ -2100,6 +2100,12 @@ static void _handleRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial
}
static void _handleRadialFrAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value)
{
radial->fr = _gradientToFloat(loader->svgParse, value, radial->isFrPercentage);
}
static void _handleRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value)
{
radial->r = _gradientToFloat(loader->svgParse, value, radial->isRPercentage);
@ -2130,6 +2136,13 @@ static void _recalcRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial
}
static void _recalcRadialFrAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
{
// scaling factor based on the Units paragraph from : https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html
if (userSpace && !radial->isFrPercentage) radial->fr = radial->fr / (sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0));
}
static void _recalcRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
{
// scaling factor based on the Units paragraph from : https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html
@ -2173,6 +2186,15 @@ static void _recalcInheritedRadialFyAttr(SvgLoaderData* loader, SvgRadialGradien
}
static void _recalcInheritedRadialFrAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
{
if (!radial->isFrPercentage) {
if (userSpace) radial->fr /= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0);
else radial->fr *= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0);
}
}
static void _recalcInheritedRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
{
if (!radial->isRPercentage) {
@ -2214,6 +2236,14 @@ static void _inheritRadialFyAttr(SvgStyleGradient* to, SvgStyleGradient* from)
}
static void _inheritRadialFrAttr(SvgStyleGradient* to, SvgStyleGradient* from)
{
to->radial->fr = from->radial->fr;
to->radial->isFrPercentage = from->radial->isFrPercentage;
to->flags = (to->flags | SvgGradientFlags::Fr);
}
static void _inheritRadialRAttr(SvgStyleGradient* to, SvgStyleGradient* from)
{
to->radial->r = from->radial->r;
@ -2247,7 +2277,8 @@ static constexpr struct
RADIAL_DEF(cy, Cy, SvgGradientFlags::Cy),
RADIAL_DEF(fx, Fx, SvgGradientFlags::Fx),
RADIAL_DEF(fy, Fy, SvgGradientFlags::Fy),
RADIAL_DEF(r, R, SvgGradientFlags::R)
RADIAL_DEF(r, R, SvgGradientFlags::R),
RADIAL_DEF(fr, Fr, SvgGradientFlags::Fr)
};
@ -2315,6 +2346,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char
grad->radial->isFxPercentage = true;
grad->radial->isFyPercentage = true;
grad->radial->isRPercentage = true;
grad->radial->isFrPercentage = true;
loader->svgParse->gradient.parsedFx = false;
loader->svgParse->gradient.parsedFy = false;

View file

@ -184,7 +184,8 @@ enum class SvgGradientFlags
Cy = 0x80,
R = 0x100,
Fx = 0x200,
Fy = 0x400
Fy = 0x400,
Fr = 0x800
};
constexpr bool operator &(SvgGradientFlags a, SvgGradientFlags b)
@ -392,11 +393,13 @@ struct SvgRadialGradient
float fx;
float fy;
float r;
float fr;
bool isCxPercentage;
bool isCyPercentage;
bool isFxPercentage;
bool isFyPercentage;
bool isRPercentage;
bool isFrPercentage;
};
struct SvgComposite

View file

@ -26,11 +26,12 @@
#include "tvgShapeImpl.h"
#include "tvgCompressor.h"
#include "tvgPaint.h"
#include "tvgFill.h"
#include "tvgStr.h"
#include "tvgSvgLoaderCommon.h"
#include "tvgSvgSceneBuilder.h"
#include "tvgSvgPath.h"
#include "tvgSvgUtil.h"
#include "tvgStr.h"
/************************************************************************/
/* Internal Class Implementation */
@ -151,6 +152,7 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
g->radial->r = g->radial->r * sqrtf(powf(vBox.w, 2.0f) + powf(vBox.h, 2.0f)) / sqrtf(2.0f);
g->radial->fx = g->radial->fx * vBox.w;
g->radial->fy = g->radial->fy * vBox.h;
g->radial->fr = g->radial->fr * sqrtf(powf(vBox.w, 2.0f) + powf(vBox.h, 2.0f)) / sqrtf(2.0f);
} else {
Matrix m = {vBox.w, 0, vBox.x, 0, vBox.h, vBox.y, 0, 0, 1};
if (isTransform) _transformMultiply(&m, &finalTransform);
@ -162,11 +164,7 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
if (isTransform) fillGrad->transform(finalTransform);
//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);
P(fillGrad)->radial(g->radial->cx, g->radial->cy, g->radial->r, g->radial->fx, g->radial->fy, g->radial->fr);
fillGrad->spread(g->spread);
//Update the stops