svg_loader: proper svg resizing

Solves the problem of 'vx' and 'vy' < 0 and cases with 'width'
and 'height' values different than widht and height from the 'viewBox'
attribute.
This commit is contained in:
Mira Grudzinska 2021-09-15 01:43:45 +02:00 committed by Hermet Park
parent 1d8625d40d
commit c9c3776207
3 changed files with 52 additions and 20 deletions

View file

@ -2770,7 +2770,7 @@ void SvgLoader::run(unsigned tid)
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes); if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes);
} }
root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh); root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect);
}; };
@ -2855,31 +2855,31 @@ bool SvgLoader::resize(Paint* paint, float w, float h)
{ {
if (!paint) return false; if (!paint) return false;
auto sx = w / vw; auto sx = w / this->w;
auto sy = h / vh; auto sy = h / this->h;
if (preserveAspect) { if (preserveAspect) {
//Scale //Scale
auto scale = sx < sy ? sx : sy; auto scale = sx < sy ? sx : sy;
paint->scale(scale); paint->scale(scale);
//Align //Align
auto vx = this->vx * scale; auto tx = 0.0f;
auto vy = this->vy * scale; auto ty = 0.0f;
auto vw = this->vw * scale; auto tw = this->w * scale;
auto vh = this->vh * scale; auto th = this->h * scale;
if (vw > vh) vy -= (h - vh) * 0.5f; if (tw > th) ty -= (h - th) * 0.5f;
else vx -= (w - vw) * 0.5f; else tx -= (w - tw) * 0.5f;
paint->translate(-vx, -vy); paint->translate(-tx, -ty);
} else { } else {
//Align //Align
auto vx = this->vx * sx; auto tx = 0.0f;
auto vy = this->vy * sy; auto ty = 0.0f;
auto vw = this->vw * sx; auto tw = this->w * sx;
auto vh = this->vh * sy; auto th = this->h * sy;
if (vw > vh) vy -= (h - vh) * 0.5f; if (tw > th) ty -= (h - th) * 0.5f;
else vx -= (w - vw) * 0.5f; else tx -= (w - tw) * 0.5f;
Matrix m = {sx, 0, -vx, 0, sy, -vy, 0, 0, 1}; Matrix m = {sx, 0, -tx, 0, sy, -ty, 0, 0, 1};
paint->transform(m); paint->transform(m);
} }
return true; return true;

View file

@ -25,6 +25,7 @@
#include "tvgSvgSceneBuilder.h" #include "tvgSvgSceneBuilder.h"
#include "tvgSvgPath.h" #include "tvgSvgPath.h"
#include "tvgSvgUtil.h" #include "tvgSvgUtil.h"
#include <float.h>
static bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh); static bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh);
@ -516,14 +517,45 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, float vx, float
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh) unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect)
{ {
if (!node || (node->type != SvgNodeType::Doc)) return nullptr; if (!node || (node->type != SvgNodeType::Doc)) return nullptr;
auto docNode = _sceneBuildHelper(node, vx, vy, vw, vh); auto docNode = _sceneBuildHelper(node, vx, vy, vw, vh);
if (fabsf(w - vw) > FLT_EPSILON || fabsf(h - vh) > FLT_EPSILON) {
auto sx = w / vw;
auto sy = h / vh;
if (preserveAspect) {
//Scale
auto scale = sx < sy ? sx : sy;
docNode->scale(scale);
//Align
auto tvx = vx * scale;
auto tvy = vy * scale;
auto tvw = vw * scale;
auto tvh = vh * scale;
if (vw > vh) tvy -= (h - tvh) * 0.5f;
else tvx -= (w - tvw) * 0.5f;
docNode->translate(-tvx, -tvy);
} else {
//Align
auto tvx = vx * sx;
auto tvy = vy * sy;
auto tvw = vw * sx;
auto tvh = vh * sy;
if (tvw > tvh) tvy -= (h - tvh) * 0.5f;
else tvx -= (w - tvw) * 0.5f;
Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
docNode->transform(m);
}
} else if (vx < 0 || vy < 0) {
docNode->translate(-vx, -vy);
}
auto viewBoxClip = Shape::gen(); auto viewBoxClip = Shape::gen();
viewBoxClip->appendRect(vx, vy, vw, vh, 0, 0); viewBoxClip->appendRect(0, 0, w, h, 0, 0);
viewBoxClip->fill(0, 0, 0, 255); viewBoxClip->fill(0, 0, 0, 255);
auto compositeLayer = Scene::gen(); auto compositeLayer = Scene::gen();

View file

@ -25,6 +25,6 @@
#include "tvgCommon.h" #include "tvgCommon.h"
unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh); unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect);
#endif //_TVG_SVG_SCENE_BUILDER_H_ #endif //_TVG_SVG_SCENE_BUILDER_H_