From 0ba45b8b8c08dea65bd9053e07e7a7ad76cfb415 Mon Sep 17 00:00:00 2001 From: jykeon Date: Tue, 14 Dec 2021 16:09:26 +0900 Subject: [PATCH 01/16] bump up version 0.6.4 Change-Id: I2f1e645ab71d37430503341c4b16d32e053331f1 Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 7adaa29..16eba8a 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.6.3 +Version: 0.6.4 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From 88e83a7c76ba78bd76e0d0891947c1be13499d6a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 13 Dec 2021 18:56:25 +0900 Subject: [PATCH 02/16] common: revise the identifier() implementation Migrate the id property to the base class internals so that pimpl classes could access the data easier. This is a sort of prerequisite change for the coming texmap anti-aliasing. --- inc/thorvg.h | 10 ++-------- src/lib/tvgFill.cpp | 5 +++++ src/lib/tvgFill.h | 1 + src/lib/tvgLinearGradient.cpp | 2 +- src/lib/tvgPaint.cpp | 6 ++++++ src/lib/tvgPaint.h | 1 + src/lib/tvgPicture.cpp | 2 +- src/lib/tvgRadialGradient.cpp | 2 +- src/lib/tvgScene.cpp | 2 +- src/lib/tvgShape.cpp | 2 +- 10 files changed, 20 insertions(+), 13 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 80d19e4..49e112d 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -53,10 +53,6 @@ protected: \ friend IteratorAccessor -#define _TVG_DECALRE_IDENTIFIER() \ -protected: \ - unsigned _id - namespace tvg { @@ -345,10 +341,9 @@ public: * * @BETA_API */ - uint32_t identifier() const { return _id; } + uint32_t identifier() const noexcept; _TVG_DECLARE_ACCESSOR(); - _TVG_DECALRE_IDENTIFIER(); _TVG_DECLARE_PRIVATE(Paint); }; @@ -454,9 +449,8 @@ public: * * @BETA_API */ - uint32_t identifier() const { return _id; } + uint32_t identifier() const noexcept; - _TVG_DECALRE_IDENTIFIER(); _TVG_DECLARE_PRIVATE(Fill); }; diff --git a/src/lib/tvgFill.cpp b/src/lib/tvgFill.cpp index f26168a..4bfb93c 100644 --- a/src/lib/tvgFill.cpp +++ b/src/lib/tvgFill.cpp @@ -108,3 +108,8 @@ Fill* Fill::duplicate() const noexcept { return pImpl->duplicate(); } + +uint32_t Fill::identifier() const noexcept +{ + return pImpl->id; +} \ No newline at end of file diff --git a/src/lib/tvgFill.h b/src/lib/tvgFill.h index 4251849..912091f 100644 --- a/src/lib/tvgFill.h +++ b/src/lib/tvgFill.h @@ -54,6 +54,7 @@ struct Fill::Impl uint32_t cnt = 0; FillSpread spread; DuplicateMethod* dup = nullptr; + uint32_t id; ~Impl() { diff --git a/src/lib/tvgLinearGradient.cpp b/src/lib/tvgLinearGradient.cpp index 46ca45f..6ec7dda 100644 --- a/src/lib/tvgLinearGradient.cpp +++ b/src/lib/tvgLinearGradient.cpp @@ -54,7 +54,7 @@ struct LinearGradient::Impl LinearGradient::LinearGradient():pImpl(new Impl()) { - _id = TVG_CLASS_ID_LINEAR; + Fill::pImpl->id = TVG_CLASS_ID_LINEAR; Fill::pImpl->method(new FillDup(pImpl)); } diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 5a63402..d256ac0 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -395,3 +395,9 @@ uint8_t Paint::opacity() const noexcept { return pImpl->opacity; } + + +uint32_t Paint::identifier() const noexcept +{ + return pImpl->id; +} \ No newline at end of file diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index 5b9e0db..8cfae71 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -58,6 +58,7 @@ namespace tvg Paint* cmpTarget = nullptr; CompositeMethod cmpMethod = CompositeMethod::None; uint32_t ctxFlag = ContextFlag::Invalid; + uint32_t id; uint8_t opacity = 255; ~Impl() { diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 580cb5b..52f73cb 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -28,7 +28,7 @@ Picture::Picture() : pImpl(new Impl(this)) { - _id = TVG_CLASS_ID_PICTURE; + Paint::pImpl->id = TVG_CLASS_ID_PICTURE; Paint::pImpl->method(new PaintMethod(pImpl)); } diff --git a/src/lib/tvgRadialGradient.cpp b/src/lib/tvgRadialGradient.cpp index c289ca5..42a8346 100644 --- a/src/lib/tvgRadialGradient.cpp +++ b/src/lib/tvgRadialGradient.cpp @@ -52,7 +52,7 @@ struct RadialGradient::Impl RadialGradient::RadialGradient():pImpl(new Impl()) { - _id = TVG_CLASS_ID_RADIAL; + Fill::pImpl->id = TVG_CLASS_ID_RADIAL; Fill::pImpl->method(new FillDup(pImpl)); } diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index 1516b2e..4b2f77d 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -27,7 +27,7 @@ Scene::Scene() : pImpl(new Impl()) { - _id = TVG_CLASS_ID_SCENE; + Paint::pImpl->id = TVG_CLASS_ID_SCENE; Paint::pImpl->method(new PaintMethod(pImpl)); } diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 42b2c0d..8db5635 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -34,7 +34,7 @@ constexpr auto PATH_KAPPA = 0.552284f; Shape :: Shape() : pImpl(new Impl(this)) { - _id = TVG_CLASS_ID_SHAPE; + Paint::pImpl->id = TVG_CLASS_ID_SHAPE; Paint::pImpl->method(new PaintMethod(pImpl)); } -- 2.7.4 From 50342ec162f52dc305a223235068c5c43637d0e6 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 13 Dec 2021 19:26:56 +0900 Subject: [PATCH 03/16] common picture: remove unused variable. --- src/lib/tvgPicture.cpp | 2 +- src/lib/tvgPictureImpl.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 52f73cb..1d97763 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -26,7 +26,7 @@ /* External Class Implementation */ /************************************************************************/ -Picture::Picture() : pImpl(new Impl(this)) +Picture::Picture() : pImpl(new Impl) { Paint::pImpl->id = TVG_CLASS_ID_PICTURE; Paint::pImpl->method(new PaintMethod(pImpl)); diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 794363f..2e27471 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -63,16 +63,10 @@ struct Picture::Impl Paint* paint = nullptr; //vector picture uses Surface* surface = nullptr; //bitmap picture uses - - Picture* picture = nullptr; void* rdata = nullptr; //engine data float w = 0, h = 0; bool resizing = false; - Impl(Picture* p) : picture(p) - { - } - ~Impl() { if (paint) delete(paint); -- 2.7.4 From 023556e46a16120591a3866275903b45e17e59cf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 13 Dec 2021 20:34:43 +0900 Subject: [PATCH 04/16] common paint: code refactoring Grouping the composite data to add source paint necessarily. this refactoring is a prerequisite job for the texmap anti-aliasing. --- src/lib/tvgPaint.cpp | 53 +++++++++++++++++++++++++----------------------- src/lib/tvgPaint.h | 39 +++++++++++++++++++++++++++-------- src/lib/tvgPictureImpl.h | 1 - src/lib/tvgSceneImpl.h | 2 +- src/lib/tvgShapeImpl.h | 1 - 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index d256ac0..909e6be 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -95,7 +95,6 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, Paint* Paint::Impl::duplicate() { auto ret = smethod->duplicate(); - if (!ret) return nullptr; //duplicate Transform if (rTransform) { @@ -106,9 +105,7 @@ Paint* Paint::Impl::duplicate() ret->pImpl->opacity = opacity; - if (cmpTarget) ret->pImpl->cmpTarget = cmpTarget->duplicate(); - - ret->pImpl->cmpMethod = cmpMethod; + if (compData) ret->pImpl->composite(ret, compData->target->duplicate(), compData->method); return ret; } @@ -168,15 +165,15 @@ bool Paint::Impl::render(RenderMethod& renderer) /* Note: only ClipPath is processed in update() step. Create a composition image. */ - if (cmpTarget && cmpMethod != CompositeMethod::ClipPath && !(cmpTarget->pImpl->ctxFlag & ContextFlag::FastTrack)) { + if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { auto region = smethod->bounds(renderer); if (region.w == 0 || region.h == 0) return true; cmp = renderer.target(region); renderer.beginComposite(cmp, CompositeMethod::None, 255); - cmpTarget->pImpl->render(renderer); + compData->target->pImpl->render(renderer); } - if (cmp) renderer.beginComposite(cmp, cmpMethod, cmpTarget->pImpl->opacity); + if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity); auto ret = smethod->render(renderer); @@ -197,35 +194,37 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } /* 1. Composition Pre Processing */ - void *cmpData = nullptr; + void *tdata = nullptr; RenderRegion viewport; - bool cmpFastTrack = false; + bool compFastTrack = false; - if (cmpTarget) { - cmpTarget->pImpl->ctxFlag = ContextFlag::Invalid; //reset + if (compData) { + auto target = compData->target; + auto method = compData->method; + target->pImpl->ctxFlag = ContextFlag::Invalid; //reset /* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle, we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */ auto tryFastTrack = false; - if (cmpMethod == CompositeMethod::ClipPath) tryFastTrack = true; - else if (cmpMethod == CompositeMethod::AlphaMask && cmpTarget->identifier() == TVG_CLASS_ID_SHAPE) { - auto shape = static_cast(cmpTarget); + if (method == CompositeMethod::ClipPath) tryFastTrack = true; + else if (method == CompositeMethod::AlphaMask && target->identifier() == TVG_CLASS_ID_SHAPE) { + auto shape = static_cast(target); uint8_t a; shape->fillColor(nullptr, nullptr, nullptr, &a); if (a == 255 && shape->opacity() == 255 && !shape->fill()) tryFastTrack = true; } if (tryFastTrack) { RenderRegion viewport2; - if ((cmpFastTrack = _compFastTrack(cmpTarget, pTransform, cmpTarget->pImpl->rTransform, viewport2))) { + if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2))) { viewport = renderer.viewport(); viewport2.intersect(viewport); renderer.viewport(viewport2); - cmpTarget->pImpl->ctxFlag |= ContextFlag::FastTrack; + target->pImpl->ctxFlag |= ContextFlag::FastTrack; } } - if (!cmpFastTrack) { - cmpData = cmpTarget->pImpl->update(renderer, pTransform, 255, clips, pFlag); - if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData); + if (!compFastTrack) { + tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag); + if (method == CompositeMethod::ClipPath) clips.push(tdata); } } @@ -244,8 +243,8 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } /* 3. Composition Post Processing */ - if (cmpFastTrack) renderer.viewport(viewport); - else if (cmpData && cmpMethod == CompositeMethod::ClipPath) clips.pop(); + if (compFastTrack) renderer.viewport(viewport); + else if (tdata && compData->method == CompositeMethod::ClipPath) clips.pop(); return edata; } @@ -366,7 +365,7 @@ Paint* Paint::duplicate() const noexcept Result Paint::composite(std::unique_ptr target, CompositeMethod method) noexcept { auto p = target.release(); - if (pImpl->composite(p, method)) return Result::Success; + if (pImpl->composite(this, p, method)) return Result::Success; if (p) delete(p); return Result::InvalidArguments; } @@ -374,9 +373,13 @@ Result Paint::composite(std::unique_ptr target, CompositeMethod method) n CompositeMethod Paint::composite(const Paint** target) const noexcept { - if (target) *target = pImpl->cmpTarget; - - return pImpl->cmpMethod; + if (pImpl->compData) { + if (target) *target = pImpl->compData->target; + return pImpl->compData->method; + } else { + if (target) *target = nullptr; + return CompositeMethod::None; + } } diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index 8cfae71..1f36ec3 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -50,19 +50,28 @@ namespace tvg virtual Iterator* iterator() = 0; }; + struct Composite + { + Paint* target; + Paint* source; + CompositeMethod method; + }; + struct Paint::Impl { StrategyMethod* smethod = nullptr; RenderTransform* rTransform = nullptr; + Composite* compData = nullptr; uint32_t renderFlag = RenderUpdateFlag::None; - Paint* cmpTarget = nullptr; - CompositeMethod cmpMethod = CompositeMethod::None; uint32_t ctxFlag = ContextFlag::Invalid; uint32_t id; uint8_t opacity = 255; ~Impl() { - if (cmpTarget) delete(cmpTarget); + if (compData) { + delete(compData->target); + free(compData); + } if (smethod) delete(smethod); if (rTransform) delete(rTransform); } @@ -100,7 +109,7 @@ namespace tvg bool dispose(RenderMethod& renderer) { - if (cmpTarget) cmpTarget->pImpl->dispose(renderer); + if (compData) compData->target->pImpl->dispose(renderer); return smethod->dispose(renderer); } @@ -109,12 +118,26 @@ namespace tvg return smethod->iterator(); } - bool composite(Paint* target, CompositeMethod method) + bool composite(Paint* source, Paint* target, CompositeMethod method) { + //Invalid case if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false; - if (cmpTarget) delete(cmpTarget); - cmpTarget = target; - cmpMethod = method; + + if (compData) { + delete(compData->target); + //Reset scenario + if (!target && method == CompositeMethod::None) { + free(compData); + compData = nullptr; + return true; + } + } else { + if (!target && method == CompositeMethod::None) return true; + compData = static_cast(calloc(1, sizeof(Composite))); + } + compData->target = target; + compData->source = source; + compData->method = method; return true; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 2e27471..00e8aa6 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -225,7 +225,6 @@ struct Picture::Impl reload(); auto ret = Picture::gen(); - if (!ret) return nullptr; auto dup = ret.get()->pImpl; if (paint) dup->paint = paint->duplicate(); diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 5e8ce3d..de94a66 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -184,7 +184,7 @@ struct Scene::Impl Paint* duplicate() { auto ret = Scene::gen(); - if (!ret) return nullptr; + auto dup = ret.get()->pImpl; dup->paints.reserve(paints.count); diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 32aa00a..dcf4e6e 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -352,7 +352,6 @@ struct Shape::Impl Paint* duplicate() { auto ret = Shape::gen(); - if (!ret) return nullptr; auto dup = ret.get()->pImpl; dup->rule = rule; -- 2.7.4 From 5234c376e818c44060c722ddde77fa6a13628d65 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 14 Dec 2021 16:33:17 +0900 Subject: [PATCH 05/16] png_loaders: fix the wrong premultiplying operations. It should not modify the alpha channel value while premultiplying that turned out with the wrong visual result. @Issue: https://github.com/Samsung/thorvg/issues/655 --- src/examples/PicturePng.cpp | 6 ++++++ src/loaders/external_png/tvgPngLoader.cpp | 8 ++++---- src/loaders/png/tvgPngLoader.cpp | 8 ++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/examples/PicturePng.cpp b/src/examples/PicturePng.cpp index 1cccf69..3798ab1 100644 --- a/src/examples/PicturePng.cpp +++ b/src/examples/PicturePng.cpp @@ -31,6 +31,12 @@ void tvgDrawCmds(tvg::Canvas* canvas) { if (!canvas) return; + //Background + auto bg = tvg::Shape::gen(); + bg->appendRect(0, 0, WIDTH, HEIGHT, 0, 0); //x, y, w, h, rx, ry + bg->fill(255, 255, 255, 255); //r, g, b, a + canvas->push(move(bg)); + //Load png file from path auto opacity = 51; diff --git a/src/loaders/external_png/tvgPngLoader.cpp b/src/loaders/external_png/tvgPngLoader.cpp index 316f51d..c3d2814 100644 --- a/src/loaders/external_png/tvgPngLoader.cpp +++ b/src/loaders/external_png/tvgPngLoader.cpp @@ -23,10 +23,10 @@ #include "tvgLoader.h" #include "tvgPngLoader.h" -static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a) +static inline uint32_t PREMULTIPLY(uint32_t c) { - return (((((c >> 8) & 0x00ff00ff) * a + 0x00ff00ff) & 0xff00ff00) + - ((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff)); + auto a = (c >> 24); + return (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); } @@ -36,7 +36,7 @@ static void _premultiply(uint32_t* data, uint32_t w, uint32_t h) for (uint32_t y = 0; y < h; ++y, buffer += w) { auto src = buffer; for (uint32_t x = 0; x < w; ++x, ++src) { - *src = ALPHA_BLEND(*src, (*src >> 24)); + *src = PREMULTIPLY(*src); } } } diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index b938893..c6d95be 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -29,10 +29,10 @@ /************************************************************************/ -static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a) +static inline uint32_t PREMULTIPLY(uint32_t c) { - return (((((c >> 8) & 0x00ff00ff) * a + 0x00ff00ff) & 0xff00ff00) + - ((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff)); + auto a = (c >> 24); + return (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); } @@ -42,7 +42,7 @@ static void _premultiply(uint32_t* data, uint32_t w, uint32_t h) for (uint32_t y = 0; y < h; ++y, buffer += w) { auto src = buffer; for (uint32_t x = 0; x < w; ++x, ++src) { - *src = ALPHA_BLEND(*src, (*src >> 24)); + *src = PREMULTIPLY(*src); } } } -- 2.7.4 From f4292f4a9918a5e2694079e30a03758e66f204b4 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 14 Dec 2021 20:19:14 -0800 Subject: [PATCH 06/16] sw_engine SwShape: Prevent null access strokeOutline returned strokeExportOutline() is the address of mpool->strokeOutline[idx]. Assuming this value is null, mpoolRetStrokeOutline on line 617 will access mpool->strokeOutline[idx]. Logically, the logic of the mpool* functions does not occur in this case. --- src/lib/sw_engine/tvgSwShape.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 29f5590..ca5548c 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -594,10 +594,6 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo } strokeOutline = strokeExportOutline(shape->stroke, mpool, tid); - if (!strokeOutline) { - ret = false; - goto fail; - } if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion, false)) { ret = false; -- 2.7.4 From c801447c6a971c8df943551e4214301d6b4fcea0 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 14 Dec 2021 20:29:01 -0800 Subject: [PATCH 07/16] sw_engine SwShape: Fix coding style --- src/lib/sw_engine/tvgSwShape.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index ca5548c..7b49c23 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -297,7 +297,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform) auto outlineCntrsCnt = 0; for (uint32_t i = 0; i < cmdCnt; ++i) { - switch(*(cmds + i)) { + switch (*(cmds + i)) { case PathCommand::Close: { ++outlinePtsCnt; break; @@ -326,7 +326,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform) _growOutlineContour(*dash.outline, outlineCntrsCnt * 20); while (cmdCnt-- > 0) { - switch(*cmds) { + switch (*cmds) { case PathCommand::Close: { _dashLineTo(dash, &dash.ptStart, transform); break; @@ -397,7 +397,7 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf auto closeCnt = 0; for (uint32_t i = 0; i < cmdCnt; ++i) { - switch(*(cmds + i)) { + switch (*(cmds + i)) { case PathCommand::Close: { ++outlinePtsCnt; ++closeCnt; @@ -440,7 +440,7 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf //Generate Outlines while (cmdCnt-- > 0) { - switch(*cmds) { + switch (*cmds) { case PathCommand::Close: { _outlineClose(*outline); break; -- 2.7.4 From 5ef121f7c70759f3e89940955f308a96a4107b09 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 21 Dec 2021 18:30:51 -0800 Subject: [PATCH 08/16] capi: rename tvg_paint_get_bounds Apply the changed code of 9db4a49 Change-Id: I101ec1b5ac3876a0cba76f4da97e953d0894e8f0 --- src/bindings/capi/thorvg_capi.h | 3 +-- src/bindings/capi/tvgCapi.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bindings/capi/thorvg_capi.h b/src/bindings/capi/thorvg_capi.h index 0f99966..404f1ff 100644 --- a/src/bindings/capi/thorvg_capi.h +++ b/src/bindings/capi/thorvg_capi.h @@ -855,8 +855,7 @@ TVG_EXPORT Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint); * * \note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object. */ -//TIZEN_ONLY: RENAME TO tvg_paint_get_bounds() AFTER DUPLICATED API IS REMOVED -TVG_EXPORT Tvg_Result _tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed); +TVG_EXPORT Tvg_Result tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed); /*! * \brief Sets the composition target object and the composition method. diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 4ae221e..7c2fd12 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -199,8 +199,7 @@ TVG_EXPORT Tvg_Result tvg_paint_get_opacity(const Tvg_Paint* paint, uint8_t* opa } -//TIZEN_ONLY: RENAME TO tvg_paint_get_bounds() AFTER DUPLICATED API IS REMOVED -TVG_EXPORT Tvg_Result _tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed) +TVG_EXPORT Tvg_Result tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed) { if (!paint) return TVG_RESULT_INVALID_ARGUMENT; return (Tvg_Result) reinterpret_cast(paint)->bounds(x, y, w, h, transformed); -- 2.7.4 From d8aa8aab516b602bbdb61a447eca49dc2a8f85ef Mon Sep 17 00:00:00 2001 From: jykeon Date: Mon, 27 Dec 2021 10:36:22 +0900 Subject: [PATCH 09/16] bump up 0.6.5 Change-Id: I8431f13558ce30db255650ab2f52f794729e7c57 Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 16eba8a..84db581 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.6.4 +Version: 0.6.5 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From eac74b661ad55c5eaf6c23b15ec205f99773bf39 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 4 Jan 2022 17:42:41 -0800 Subject: [PATCH 10/16] sw_engine SwRaster: Initialize uninitialized transform value Change-Id: I7aac462c6d6e481655c35a10b237970de7dbea76 --- src/lib/sw_engine/tvgSwRaster.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 28b1e59..6602998 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -907,7 +907,9 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity) { Matrix itransform; + if (transform && !mathInverse(transform, &itransform)) return false; + else mathIdentity(&itransform); auto halfScale = _halfScale(image->scale); @@ -1226,7 +1228,9 @@ static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, con static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity) { Matrix itransform; + if (transform && !mathInverse(transform, &itransform)) return false; + else mathIdentity(&itransform); auto halfScale = _halfScale(image->scale); -- 2.7.4 From 6e9c82d505f44b81c66691824e089ca86fdd3837 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 6 Jan 2022 12:32:16 +0900 Subject: [PATCH 11/16] sw_engine raster: fix a regression bug. Picture example were broken by 90fa26b7bb75cb938290170882e65da8d9fc5d9e the correct condition must be like this change. Change-Id: Ie3af07bca9d44872073b111874c60575fa4b38f4 --- src/lib/sw_engine/tvgSwRaster.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 6602998..07a8561 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -908,8 +908,9 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const { Matrix itransform; - if (transform && !mathInverse(transform, &itransform)) return false; - else mathIdentity(&itransform); + if (transform) { + if (!mathInverse(transform, &itransform)) return false; + } else mathIdentity(&itransform); auto halfScale = _halfScale(image->scale); @@ -1229,8 +1230,9 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat { Matrix itransform; - if (transform && !mathInverse(transform, &itransform)) return false; - else mathIdentity(&itransform); + if (transform) { + if (!mathInverse(transform, &itransform)) return false; + } else mathIdentity(&itransform); auto halfScale = _halfScale(image->scale); -- 2.7.4 From 5c959b1fb7362741143d781b55681a37d0783821 Mon Sep 17 00:00:00 2001 From: jykeon Date: Fri, 7 Jan 2022 10:41:57 +0900 Subject: [PATCH 12/16] bump up 0.6.6 Change-Id: I1106ae0d6d5623ca397232964f06bc99aeaadd42 Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 84db581..c13d829 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.6.5 +Version: 0.6.6 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From 758d8661f557c4db2beb8dacae7b7d8665e9652f Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Fri, 14 Jan 2022 14:06:39 +0100 Subject: [PATCH 13/16] sw_engine: fixed declaration of 'i' shadows a previous local Some gcc versions and configurations was giving an error: error: "declaration of 'i' shadows a previous local" This patch should fix these errors Change-Id: Ic33bc0095a7ddfd78dd530a7dd4712c000ddd2eb --- src/lib/sw_engine/tvgSwRaster.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 07a8561..7ef47b2 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -1530,12 +1530,12 @@ static bool _rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleD auto dst = &surface->buffer[span->y * surface->stride + span->x]; fillFetchLinear(fill, buffer, span->y, span->x, span->len); if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i, ++dst) { - *dst = buffer[i] + ALPHA_BLEND(*dst, _ialpha(buffer[i])); + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = buffer[x] + ALPHA_BLEND(*dst, _ialpha(buffer[x])); } } else { - for (uint32_t i = 0; i < span->len; ++i, ++dst) { - auto tmp = ALPHA_BLEND(buffer[i], span->coverage); + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + auto tmp = ALPHA_BLEND(buffer[x], span->coverage); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -1559,8 +1559,8 @@ static bool _rasterSolidLinearGradientRle(SwSurface* surface, const SwRleData* r } else { fillFetchLinear(fill, buf, span->y, span->x, span->len); auto dst = &surface->buffer[span->y * surface->stride + span->x]; - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = INTERPOLATE(span->coverage, buf[i], dst[i]); + for (uint32_t x = 0; x < span->len; ++x) { + dst[x] = INTERPOLATE(span->coverage, buf[x], dst[x]); } } } @@ -1719,12 +1719,12 @@ static bool _rasterTranslucentRadialGradientRle(SwSurface* surface, const SwRleD auto dst = &surface->buffer[span->y * surface->stride + span->x]; fillFetchRadial(fill, buffer, span->y, span->x, span->len); if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i, ++dst) { - *dst = buffer[i] + ALPHA_BLEND(*dst, _ialpha(buffer[i])); + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = buffer[x] + ALPHA_BLEND(*dst, _ialpha(buffer[x])); } } else { - for (uint32_t i = 0; i < span->len; ++i, ++dst) { - auto tmp = ALPHA_BLEND(buffer[i], span->coverage); + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + auto tmp = ALPHA_BLEND(buffer[x], span->coverage); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -1749,8 +1749,8 @@ static bool _rasterSolidRadialGradientRle(SwSurface* surface, const SwRleData* r } else { fillFetchRadial(fill, buf, span->y, span->x, span->len); auto ialpha = 255 - span->coverage; - for (uint32_t i = 0; i < span->len; ++i, ++dst) { - *dst = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(*dst, ialpha); + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = ALPHA_BLEND(buf[x], span->coverage) + ALPHA_BLEND(*dst, ialpha); } } } -- 2.7.4 From 35bff319244b0847febb9dc6c6e2ba757318834c Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Fri, 14 Jan 2022 14:19:55 +0100 Subject: [PATCH 14/16] sw_engine: fix comparison of integer expressions of different signedness Some gcc versions and configurations was giving an error: error: "comparison of integer expressions of different signedness: 'const SwCoord' {aka 'const long int'} and 'uint32_t' {aka 'unsigned int'} [-Werror=sign-compare]" This patch should fix the error Change-Id: Ie683f35220b130b3548d0059ffe130fa4fc53fdc --- src/lib/sw_engine/tvgSwRaster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 7ef47b2..9987aeb 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -1904,7 +1904,7 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity) { //Verify Boundary - if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= surface->w || bbox.min.y >= surface->h) return false; + if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast(surface->w) || bbox.min.y >= static_cast(surface->h)) return false; //TOOD: switch (image->format) //TODO: case: _rasterRGBImage() -- 2.7.4 From 32fabcb8e90c963fb7752e6caf111e4f6018de62 Mon Sep 17 00:00:00 2001 From: jykeon Date: Wed, 19 Jan 2022 17:16:29 +0900 Subject: [PATCH 15/16] bump up 0.6.7 Change-Id: Ib07f04d7c74b5f3be2ec6aaf6b76e3a88f2dbe2f Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index c13d829..b58cec2 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.6.6 +Version: 0.6.7 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From 2111930048843b2373907f4e9813f97a3b2d6206 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Mon, 22 Aug 2022 15:53:37 +0200 Subject: [PATCH 16/16] svg_loader: the preserveAspectRatio attrib handled The preserveAspectRatio attribute handled according to the svg standard. Change-Id: Ie7292ba47341994cf703b3634016c267292a22d2 --- src/lib/tvgLoadModule.h | 1 - src/loaders/svg/tvgSvgLoader.cpp | 80 ++++++++++++++++--------- src/loaders/svg/tvgSvgLoader.h | 2 + src/loaders/svg/tvgSvgLoaderCommon.h | 23 +++++++- src/loaders/svg/tvgSvgSceneBuilder.cpp | 104 ++++++++++++++++++++++++--------- src/loaders/svg/tvgSvgSceneBuilder.h | 2 +- 6 files changed, 154 insertions(+), 58 deletions(-) diff --git a/src/lib/tvgLoadModule.h b/src/lib/tvgLoadModule.h index 0c34ecb..a496b09 100644 --- a/src/lib/tvgLoadModule.h +++ b/src/lib/tvgLoadModule.h @@ -36,7 +36,6 @@ public: float vw = 0; float vh = 0; float w = 0, h = 0; //default image size - bool preserveAspect = true; //keep aspect ratio by default. virtual ~LoadModule() {} diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index def8ae1..050611f 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -116,6 +116,49 @@ static bool _parseNumber(const char** content, float* number) return true; } + +static constexpr struct +{ + AspectRatioAlign align; + const char* tag; +} alignTags[] = { + { AspectRatioAlign::XMinYMin, "xMinYMin" }, + { AspectRatioAlign::XMidYMin, "xMidYMin" }, + { AspectRatioAlign::XMaxYMin, "xMaxYMin" }, + { AspectRatioAlign::XMinYMid, "xMinYMid" }, + { AspectRatioAlign::XMidYMid, "xMidYMid" }, + { AspectRatioAlign::XMaxYMid, "xMaxYMid" }, + { AspectRatioAlign::XMinYMax, "xMinYMax" }, + { AspectRatioAlign::XMidYMax, "xMidYMax" }, + { AspectRatioAlign::XMaxYMax, "xMaxYMax" }, +}; + + +static void _parseAspectRatio(const char** content, AspectRatioAlign* align, AspectRatioMeetOrSlice* meetOrSlice) +{ + if (!strcmp(*content, "none")) { + *align = AspectRatioAlign::None; + return; + } + + for (unsigned int i = 0; i < sizeof(alignTags) / sizeof(alignTags[0]); i++) { + if (!strncmp(*content, alignTags[i].tag, 8)) { + *align = alignTags[i].align; + *content += 8; + *content = _skipSpace(*content, nullptr); + break; + } + } + + if (!strcmp(*content, "meet")) + *meetOrSlice = AspectRatioMeetOrSlice::Meet; + else if (!strcmp(*content, "slice")) + *meetOrSlice = AspectRatioMeetOrSlice::Slice; + + return; +} + + /** * According to https://www.w3.org/TR/SVG/coords.html#Units */ @@ -783,7 +826,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) } loader->svgParse->global.x = (int)doc->vx; } else if (!strcmp(key, "preserveAspectRatio")) { - if (!strcmp(value, "none")) doc->preserveAspect = false; + _parseAspectRatio(&value, &doc->align, &doc->meetOrSlice); } else if (!strcmp(key, "style")) { return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); } @@ -1150,7 +1193,9 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha loader->svgParse->global.w = 0; loader->svgParse->global.h = 0; - doc->preserveAspect = true; + doc->align = AspectRatioAlign::XMidYMid; + doc->meetOrSlice = AspectRatioMeetOrSlice::Meet; + simpleXmlParseAttributes(buf, bufLength, _attrParseSvgNode, loader); if (loader->svgParse->global.w == 0) { @@ -2846,7 +2891,7 @@ void SvgLoader::run(unsigned tid) if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes); } - root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath); + root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, align, meetOrSlice, svgPath); } @@ -2879,7 +2924,8 @@ bool SvgLoader::header() if (vh < FLT_EPSILON) vh = h; } - preserveAspect = loaderData.doc->node.doc.preserveAspect; + align = loaderData.doc->node.doc.align; + meetOrSlice = loaderData.doc->node.doc.meetOrSlice; } else { TVGLOG("SVG", "No SVG File. There is no "); return false; @@ -2934,31 +2980,9 @@ bool SvgLoader::resize(Paint* paint, float w, float h) auto sx = w / this->w; auto sy = h / this->h; + Matrix m = {sx, 0, 0, 0, sy, 0, 0, 0, 1}; + paint->transform(m); - if (preserveAspect) { - //Scale - auto scale = sx < sy ? sx : sy; - paint->scale(scale); - //Align - 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 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, -tx, 0, sy, -ty, 0, 0, 1}; - paint->transform(m); - } return true; } diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index 468f058..8c5b233 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -32,6 +32,8 @@ public: string svgPath = ""; const char* content = nullptr; uint32_t size = 0; + AspectRatioAlign align = AspectRatioAlign::XMidYMid; + AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet; SvgLoaderData loaderData; unique_ptr root; diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index cceef91..0a6f019 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -136,6 +136,26 @@ enum class SvgParserLengthType Other }; +enum class AspectRatioAlign +{ + None, + XMinYMin, + XMidYMin, + XMaxYMin, + XMinYMid, + XMidYMid, + XMaxYMid, + XMinYMax, + XMidYMax, + XMaxYMax +}; + +enum class AspectRatioMeetOrSlice +{ + Meet, + Slice +}; + struct SvgDocNode { float w; @@ -145,7 +165,8 @@ struct SvgDocNode float vw; float vh; SvgNode* defs; - bool preserveAspect; + AspectRatioAlign align; + AspectRatioMeetOrSlice meetOrSlice; }; struct SvgGNode diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index 8701fe3..243fe7b 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -595,11 +595,85 @@ static unique_ptr _sceneBuildHelper(const SvgNode* node, const Box& vBox, } +static Matrix _calculateAspectRatioMatrix(AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, float width, float height, const Box& box) +{ + auto sx = width / box.w; + auto sy = height / box.h; + auto tvx = box.x * sx; + auto tvy = box.y * sy; + + if (align == AspectRatioAlign::None) + return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; + + //Scale + if (meetOrSlice == AspectRatioMeetOrSlice::Meet) { + if (sx < sy) sy = sx; + else sx = sy; + } else { + if (sx < sy) sx = sy; + else sy = sx; + } + + //Align + tvx = box.x * sx; + tvy = box.y * sy; + auto tvw = box.w * sx; + auto tvh = box.h * sy; + + switch (align) { + case AspectRatioAlign::XMinYMin: { + break; + } + case AspectRatioAlign::XMidYMin: { + tvx -= (width - tvw) * 0.5f; + break; + } + case AspectRatioAlign::XMaxYMin: { + tvx -= width - tvw; + break; + } + case AspectRatioAlign::XMinYMid: { + tvy -= (height - tvh) * 0.5f; + break; + } + case AspectRatioAlign::XMidYMid: { + tvx -= (width - tvw) * 0.5f; + tvy -= (height - tvh) * 0.5f; + break; + } + case AspectRatioAlign::XMaxYMid: { + tvx -= width - tvw; + tvy -= (height - tvh) * 0.5f; + break; + } + case AspectRatioAlign::XMinYMax: { + tvy -= height - tvh; + break; + } + case AspectRatioAlign::XMidYMax: { + tvx -= (width - tvw) * 0.5f; + tvy -= height - tvh; + break; + } + case AspectRatioAlign::XMaxYMax: { + tvx -= width - tvw; + tvy -= height - tvh; + break; + } + default: { + break; + } + } + + return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; +} + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath) +unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath) { if (!node || (node->type != SvgNodeType::Doc)) return nullptr; @@ -607,32 +681,8 @@ unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo auto docNode = _sceneBuildHelper(node, vBox, svgPath, false); if (!mathEqual(w, vw) || !mathEqual(h, vh)) { - 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); - } + Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox); + docNode->transform(m); } else if (!mathZero(vx) || !mathZero(vy)) { docNode->translate(-vx, -vy); } diff --git a/src/loaders/svg/tvgSvgSceneBuilder.h b/src/loaders/svg/tvgSvgSceneBuilder.h index 4232aca..20b6b2b 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.h +++ b/src/loaders/svg/tvgSvgSceneBuilder.h @@ -25,6 +25,6 @@ #include "tvgCommon.h" -unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, bool preserveAspect, const string& svgPath); +unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath); #endif //_TVG_SVG_SCENE_BUILDER_H_ -- 2.7.4