mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
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:
parent
1d8625d40d
commit
c9c3776207
3 changed files with 52 additions and 20 deletions
|
@ -2770,7 +2770,7 @@ void SvgLoader::run(unsigned tid)
|
|||
|
||||
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;
|
||||
|
||||
auto sx = w / vw;
|
||||
auto sy = h / vh;
|
||||
auto sx = w / this->w;
|
||||
auto sy = h / this->h;
|
||||
|
||||
if (preserveAspect) {
|
||||
//Scale
|
||||
auto scale = sx < sy ? sx : sy;
|
||||
paint->scale(scale);
|
||||
//Align
|
||||
auto vx = this->vx * scale;
|
||||
auto vy = this->vy * scale;
|
||||
auto vw = this->vw * scale;
|
||||
auto vh = this->vh * scale;
|
||||
if (vw > vh) vy -= (h - vh) * 0.5f;
|
||||
else vx -= (w - vw) * 0.5f;
|
||||
paint->translate(-vx, -vy);
|
||||
auto tx = 0.0f;
|
||||
auto ty = 0.0f;
|
||||
auto tw = this->w * scale;
|
||||
auto th = this->h * scale;
|
||||
if (tw > th) ty -= (h - th) * 0.5f;
|
||||
else tx -= (w - tw) * 0.5f;
|
||||
paint->translate(-tx, -ty);
|
||||
} else {
|
||||
//Align
|
||||
auto vx = this->vx * sx;
|
||||
auto vy = this->vy * sy;
|
||||
auto vw = this->vw * sx;
|
||||
auto vh = this->vh * sy;
|
||||
if (vw > vh) vy -= (h - vh) * 0.5f;
|
||||
else vx -= (w - vw) * 0.5f;
|
||||
auto tx = 0.0f;
|
||||
auto ty = 0.0f;
|
||||
auto tw = this->w * sx;
|
||||
auto th = this->h * sy;
|
||||
if (tw > th) ty -= (h - th) * 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);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "tvgSvgSceneBuilder.h"
|
||||
#include "tvgSvgPath.h"
|
||||
#include "tvgSvgUtil.h"
|
||||
#include <float.h>
|
||||
|
||||
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 */
|
||||
/************************************************************************/
|
||||
|
||||
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;
|
||||
|
||||
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();
|
||||
viewBoxClip->appendRect(vx, vy, vw, vh, 0, 0);
|
||||
viewBoxClip->appendRect(0, 0, w, h, 0, 0);
|
||||
viewBoxClip->fill(0, 0, 0, 255);
|
||||
|
||||
auto compositeLayer = Scene::gen();
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
|
||||
#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_
|
||||
|
|
Loading…
Add table
Reference in a new issue