From 02081d8cdcacbd43424899b4353e0ca84ebc7c38 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 28 Jul 2021 20:55:10 +0900 Subject: [PATCH] common picture: correct non-working size() behavior. Pixel-based image picture doesn't work at size() method. Obvisouly, we missed to implement it properly. This patch corrects it. @Issue: https://github.com/Samsung/thorvg/issues/656 --- inc/thorvg.h | 2 +- src/examples/PictureJpg.cpp | 2 +- src/examples/PicturePng.cpp | 2 +- src/lib/sw_engine/tvgSwCommon.h | 6 +++--- src/lib/sw_engine/tvgSwImage.cpp | 15 ++++++--------- src/lib/sw_engine/tvgSwRenderer.cpp | 9 ++++++--- src/lib/tvgPicture.cpp | 11 +++++++++-- src/lib/tvgPictureImpl.h | 25 ++++++++++++++++++++----- src/savers/tvg/tvgTvgSaver.cpp | 8 ++------ 9 files changed, 49 insertions(+), 31 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 25ecff06..12199634 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1048,7 +1048,7 @@ public: * * @BETA_API */ - const uint32_t* data() const noexcept; + const uint32_t* data(uint32_t* w, uint32_t* h) const noexcept; /** * Must remove it! diff --git a/src/examples/PictureJpg.cpp b/src/examples/PictureJpg.cpp index ed51904d..84d53e24 100644 --- a/src/examples/PictureJpg.cpp +++ b/src/examples/PictureJpg.cpp @@ -40,7 +40,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) } picture->translate(i* 150, i * 150); picture->rotate(30 * i); - picture->scale(0.25); + picture->size(200, 200); if (canvas->push(move(picture)) != tvg::Result::Success) return; } diff --git a/src/examples/PicturePng.cpp b/src/examples/PicturePng.cpp index 9dd6a037..4e7ba8b0 100644 --- a/src/examples/PicturePng.cpp +++ b/src/examples/PicturePng.cpp @@ -38,7 +38,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) } picture->translate(i* 150, i * 150); picture->rotate(30 * i); - picture->scale(0.25); + picture->size(200, 200); if (canvas->push(move(picture)) != tvg::Result::Success) return; } } diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 6327523a..a0d18ddd 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -266,7 +266,7 @@ struct SwMpool static inline SwCoord TO_SWCOORD(float val) { - return SwCoord(val * 64); + return SwCoord(val * 64.0f); } static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a) @@ -289,7 +289,7 @@ static inline uint32_t ALPHA_MULTIPLY(uint32_t c, uint32_t a) static inline SwCoord HALF_STROKE(float width) { - return TO_SWCOORD(width * 0.5); + return TO_SWCOORD(width * 0.5f); } int64_t mathMultiply(int64_t a, int64_t b); @@ -329,7 +329,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid); void strokeFree(SwStroke* stroke); -bool imagePrepare(SwImage* image, const Picture* pdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); +bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); bool imagePrepared(const SwImage* image); bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwBBox& renderRegion, bool antiAlias); void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid); diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp index b8775912..0de743db 100644 --- a/src/lib/sw_engine/tvgSwImage.cpp +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -26,12 +26,8 @@ /* Internal Class Implementation */ /************************************************************************/ -static bool _genOutline(SwImage* image, const Picture* pdata, const Matrix* transform, SwMpool* mpool, unsigned tid) +static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, unsigned tid) { - float w, h; - pdata->size(&w, &h); - if (w == 0 || h == 0) return false; - image->outline = mpoolReqOutline(mpool, tid); auto outline = image->outline; @@ -42,6 +38,9 @@ static bool _genOutline(SwImage* image, const Picture* pdata, const Matrix* tran outline->reservedCntrsCnt = 1; outline->cntrs = static_cast(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t))); + auto w = static_cast(image->w); + auto h = static_cast(image->h); + Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}}; for (int i = 0; i < 4; i++) { outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform); @@ -59,8 +58,6 @@ static bool _genOutline(SwImage* image, const Picture* pdata, const Matrix* tran outline->opened = false; image->outline = outline; - image->w = w; - image->h = h; return true; } @@ -71,9 +68,9 @@ static bool _genOutline(SwImage* image, const Picture* pdata, const Matrix* tran /************************************************************************/ -bool imagePrepare(SwImage* image, const Picture* pdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) +bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) { - if (!_genOutline(image, pdata, transform, mpool, tid)) return false; + if (!_genOutline(image, transform, mpool, tid)) return false; return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion); } diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 817f5472..ee85c101 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -181,7 +181,11 @@ struct SwImageTask : SwTask if (prepareImage) { imageReset(&image); - if (!imagePrepare(&image, pdata, transform, clipRegion, bbox, mpool, tid)) goto end; + + image.data = const_cast(pdata->data(&image.w, &image.h)); + if (!image.data || image.w == 0 || image.h == 0) goto end; + + if (!imagePrepare(&image, transform, clipRegion, bbox, mpool, tid)) goto end; //Clip Path? if (clips.count > 0) { @@ -194,8 +198,7 @@ struct SwImageTask : SwTask } } } - } - image.data = const_cast(pdata->data()); + } end: imageDelOutline(&image, mpool, tid); } diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index ed4d227d..db0ee6ed 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -85,11 +85,18 @@ Result Picture::size(float* w, float* h) const noexcept } -const uint32_t* Picture::data() const noexcept +const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept { //Try it, If not loaded yet. - if (pImpl->loader) return pImpl->loader->pixels(); + pImpl->reload(); + if (pImpl->loader) { + if (w) *w = static_cast(pImpl->loader->w); + if (h) *h = static_cast(pImpl->loader->h); + } else { + if (w) *w = 0; + if (h) *h = 0; + } return pImpl->pixels; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 88f93402..ff9d1e9a 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -76,7 +76,6 @@ struct Picture::Impl return ret; } - uint32_t reload() { if (loader) { @@ -100,17 +99,33 @@ struct Picture::Impl return RenderUpdateFlag::None; } - void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) + RenderTransform resizeTransform(const RenderTransform* pTransform) + { + //Overriding Transformation by the desired image size + auto sx = w / loader->w; + auto sy = h / loader->h; + auto scale = sx < sy ? sx : sy; + + RenderTransform tmp; + tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1}; + + if (!pTransform) return tmp; + else return RenderTransform(pTransform, &tmp); + } + + void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) { auto flag = reload(); - if (pixels) rdata = renderer.prepare(*picture, rdata, transform, opacity, clips, static_cast(pFlag | flag)); - else if (paint) { + if (pixels) { + auto transform = resizeTransform(pTransform); + rdata = renderer.prepare(*picture, rdata, &transform, opacity, clips, static_cast(pFlag | flag)); + } else if (paint) { if (resizing) { loader->resize(paint, w, h); resizing = false; } - rdata = paint->pImpl->update(renderer, transform, opacity, clips, static_cast(pFlag | flag)); + rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast(pFlag | flag)); } return rdata; } diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index a63c46e6..82ea37f1 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -319,13 +319,9 @@ TvgBinCounter TvgSaver::serializePicture(const Picture* picture) TvgBinCounter cnt = 0; //Bitmap Image - if (auto pixels = picture->data()) { - //TODO: Loader expects uints - float fw, fh; - picture->size(&fw, &fh); + uint32_t w, h; - auto w = static_cast(fw); - auto h = static_cast(fh); + if (auto pixels = picture->data(&w, &h)) { TvgBinCounter sizeCnt = sizeof(w); TvgBinCounter imgSize = w * h * sizeof(pixels[0]);