From 400587a18d05877078874855d0d4e373b796b19a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 13 Apr 2021 17:05:08 +0900 Subject: [PATCH 01/16] loaders svg: code refactoring. keep it clean & neat within tvg coding convention. --- src/loaders/svg/tvgSvgLoader.cpp | 66 ++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 1114413..a8a863f 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -37,15 +37,16 @@ typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const static char* _skipSpace(const char* str, const char* end) { - while (((end != nullptr && str < end) || (end == nullptr && *str != '\0')) && isspace(*str)) + while (((end && str < end) || (!end && *str != '\0')) && isspace(*str)) { ++str; - return (char*)str; + } + return (char*) str; } static string* _copyId(const char* str) { - if (str == nullptr) return nullptr; + if (!str) return nullptr; return new string(str); } @@ -554,23 +555,19 @@ static constexpr struct }; -static void _matrixCompose(const Matrix* m1, - const Matrix* m2, - Matrix* dst) +static void _matrixCompose(const Matrix* m1, const Matrix* m2, Matrix* dst) { - float a11, a12, a13, a21, a22, a23, a31, a32, a33; - - a11 = (m1->e11 * m2->e11) + (m1->e12 * m2->e21) + (m1->e13 * m2->e31); - a12 = (m1->e11 * m2->e12) + (m1->e12 * m2->e22) + (m1->e13 * m2->e32); - a13 = (m1->e11 * m2->e13) + (m1->e12 * m2->e23) + (m1->e13 * m2->e33); + auto a11 = (m1->e11 * m2->e11) + (m1->e12 * m2->e21) + (m1->e13 * m2->e31); + auto a12 = (m1->e11 * m2->e12) + (m1->e12 * m2->e22) + (m1->e13 * m2->e32); + auto a13 = (m1->e11 * m2->e13) + (m1->e12 * m2->e23) + (m1->e13 * m2->e33); - a21 = (m1->e21 * m2->e11) + (m1->e22 * m2->e21) + (m1->e23 * m2->e31); - a22 = (m1->e21 * m2->e12) + (m1->e22 * m2->e22) + (m1->e23 * m2->e32); - a23 = (m1->e21 * m2->e13) + (m1->e22 * m2->e23) + (m1->e23 * m2->e33); + auto a21 = (m1->e21 * m2->e11) + (m1->e22 * m2->e21) + (m1->e23 * m2->e31); + auto a22 = (m1->e21 * m2->e12) + (m1->e22 * m2->e22) + (m1->e23 * m2->e32); + auto a23 = (m1->e21 * m2->e13) + (m1->e22 * m2->e23) + (m1->e23 * m2->e33); - a31 = (m1->e31 * m2->e11) + (m1->e32 * m2->e21) + (m1->e33 * m2->e31); - a32 = (m1->e31 * m2->e12) + (m1->e32 * m2->e22) + (m1->e33 * m2->e32); - a33 = (m1->e31 * m2->e13) + (m1->e32 * m2->e23) + (m1->e33 * m2->e33); + auto a31 = (m1->e31 * m2->e11) + (m1->e32 * m2->e21) + (m1->e33 * m2->e31); + auto a32 = (m1->e31 * m2->e12) + (m1->e32 * m2->e22) + (m1->e33 * m2->e32); + auto a33 = (m1->e31 * m2->e13) + (m1->e32 * m2->e23) + (m1->e33 * m2->e33); dst->e11 = a11; dst->e12 = a12; @@ -589,16 +586,17 @@ static void _matrixCompose(const Matrix* m1, */ static Matrix* _parseTransformationMatrix(const char* value) { + auto matrix = (Matrix*)malloc(sizeof(Matrix)); + if (!matrix) return nullptr; + *matrix = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; + float points[8]; int ptCount = 0; float sx, sy; MatrixState state = MatrixState::Unknown; - Matrix* matrix = (Matrix*)calloc(1, sizeof(Matrix)); char* str = (char*)value; char* end = str + strlen(str); - if (!matrix) return nullptr; - *matrix = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; while (str < end) { if (isspace(*str) || (*str == ',')) { ++str; @@ -620,54 +618,42 @@ static Matrix* _parseTransformationMatrix(const char* value) ++str; if (state == MatrixState::Matrix) { - Matrix tmp; - if (ptCount != 6) goto error; - - tmp = { points[0], points[2], points[4], points[1], points[3], points[5], 0, 0, 1 }; + Matrix tmp = {points[0], points[2], points[4], points[1], points[3], points[5], 0, 0, 1}; _matrixCompose(matrix, &tmp, matrix); } else if (state == MatrixState::Translate) { - Matrix tmp; - if (ptCount == 1) { - tmp = { 1, 0, points[0], 0, 1, 0, 0, 0, 1 }; + Matrix tmp = {1, 0, points[0], 0, 1, 0, 0, 0, 1}; _matrixCompose(matrix, &tmp, matrix); } else if (ptCount == 2) { - tmp = { 1, 0, points[0], 0, 1, points[1], 0, 0, 1 }; + Matrix tmp = {1, 0, points[0], 0, 1, points[1], 0, 0, 1}; _matrixCompose(matrix, &tmp, matrix); } else goto error; } else if (state == MatrixState::Rotate) { - Matrix tmp; - float c, s; //Transform to signed. points[0] = fmod(points[0], 360); if (points[0] < 0) points[0] += 360; - - c = cosf(points[0] * (M_PI / 180.0)); - s = sinf(points[0] * (M_PI / 180.0)); + auto c = cosf(points[0] * (M_PI / 180.0)); + auto s = sinf(points[0] * (M_PI / 180.0)); if (ptCount == 1) { - tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; + Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); } else if (ptCount == 3) { - tmp = { 1, 0, points[1], 0, 1, points[2], 0, 0, 1 }; + Matrix tmp = { 1, 0, points[1], 0, 1, points[2], 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); - tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); - tmp = { 1, 0, -points[1], 0, 1, -points[2], 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); } else { goto error; } } else if (state == MatrixState::Scale) { - Matrix tmp; if (ptCount < 1 || ptCount > 2) goto error; - sx = points[0]; sy = sx; if (ptCount == 2) sy = points[1]; - tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; + Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); } } -- 2.7.4 From 5e3b67a3c77bee785e9163f1b4af2e4bbd775d80 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 13 Apr 2021 17:17:13 +0900 Subject: [PATCH 02/16] loaders svg: fix a wrongly handles the corner case. Stop the internel loop quick as possible, and state must be reset. --- src/loaders/svg/tvgSvgLoader.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index a8a863f..acb6bba 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -588,16 +588,17 @@ static Matrix* _parseTransformationMatrix(const char* value) { auto matrix = (Matrix*)malloc(sizeof(Matrix)); if (!matrix) return nullptr; - *matrix = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; + *matrix = {1, 0, 0, 0, 1, 0, 0, 0, 1}; float points[8]; int ptCount = 0; - float sx, sy; - MatrixState state = MatrixState::Unknown; char* str = (char*)value; char* end = str + strlen(str); while (str < end) { + + auto state = MatrixState::Unknown; + if (isspace(*str) || (*str == ',')) { ++str; continue; @@ -606,6 +607,7 @@ static Matrix* _parseTransformationMatrix(const char* value) if (!strncmp(matrixTags[i].tag, str, matrixTags[i].sz - 1)) { state = matrixTags[i].state; str += (matrixTags[i].sz - 1); + break; } } if (state == MatrixState::Unknown) goto error; @@ -650,8 +652,8 @@ static Matrix* _parseTransformationMatrix(const char* value) } } else if (state == MatrixState::Scale) { if (ptCount < 1 || ptCount > 2) goto error; - sx = points[0]; - sy = sx; + auto sx = points[0]; + auto sy = sx; if (ptCount == 2) sy = points[1]; Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); -- 2.7.4 From 800acd1b2f49bfe9f68750ec5c7d9665ffd420f3 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 13 Apr 2021 18:30:04 +0900 Subject: [PATCH 03/16] loader SvgLoader: return null if transform attribute invalid In transform matrix parsing, null is returned if any of the matrices are invalid. --- src/loaders/svg/tvgSvgLoader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index acb6bba..2f6f5df 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -659,8 +659,10 @@ static Matrix* _parseTransformationMatrix(const char* value) _matrixCompose(matrix, &tmp, matrix); } } -error: return matrix; +error: + if (matrix) free(matrix); + return nullptr; } -- 2.7.4 From a7a1bbc7da189d62b18da6af1af0a7c750544db3 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 13 Apr 2021 18:34:14 +0900 Subject: [PATCH 04/16] loader SvgLoader: Fix for coding convention Change-Id: I0c6852eef9d19a8a58d1912ff54084a9c2b2c13d --- src/loaders/svg/tvgSvgLoader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 2f6f5df..f359855 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -596,7 +596,6 @@ static Matrix* _parseTransformationMatrix(const char* value) char* end = str + strlen(str); while (str < end) { - auto state = MatrixState::Unknown; if (isspace(*str) || (*str == ',')) { @@ -735,7 +734,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); } #ifdef THORVG_LOG_ENABLED - else if (!strcmp(key, "xmlns") || !strcmp(key, "xmlns:xlink") || !strcmp (key, "xmlns:svg")) { + else if (!strcmp(key, "xmlns") || !strcmp(key, "xmlns:xlink") || !strcmp(key, "xmlns:svg")) { //No action } #endif -- 2.7.4 From 9996be4c047b5b3b9ced9fabe3c4b888ed795cff Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 14 Apr 2021 11:50:09 +0900 Subject: [PATCH 05/16] ** Temporary patch for diagnosing some hideous bugs in Tizen ** This patch puts some prints for analizing a crash issue, it must be reverted after fixing it. Change-Id: Iac2db25da27aa85dcfef19d05ced887d821584de --- packaging/thorvg.spec | 2 ++ src/lib/tvgCanvas.cpp | 8 ++++++++ src/lib/tvgCanvasImpl.h | 8 ++++++++ src/lib/tvgCommon.h | 3 +++ src/lib/tvgInitializer.cpp | 11 ++++++++++- src/lib/tvgPaint.cpp | 6 +++++- src/lib/tvgSceneImpl.h | 11 +++++++++++ src/lib/tvgTaskScheduler.cpp | 5 ++++- src/loaders/svg/tvgSvgLoader.cpp | 14 ++++++++++++++ src/loaders/svg/tvgSvgSceneBuilder.cpp | 5 +++++ src/meson.build | 3 ++- 11 files changed, 72 insertions(+), 4 deletions(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index e0657bc..b24fec5 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -9,6 +9,8 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: pkgconfig BuildRequires: pkgconfig(glesv2) +BuildRequires: pkgconfig(dlog) + BuildRequires: meson BuildRequires: ninja Requires(post): /sbin/ldconfig diff --git a/src/lib/tvgCanvas.cpp b/src/lib/tvgCanvas.cpp index 309e205..f886c74 100644 --- a/src/lib/tvgCanvas.cpp +++ b/src/lib/tvgCanvas.cpp @@ -51,24 +51,32 @@ Result Canvas::push(unique_ptr paint) noexcept Result Canvas::clear(bool free) noexcept { +dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Clear", this); + return pImpl->clear(free); } Result Canvas::draw() noexcept { +dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Draw", this); + return pImpl->draw(); } Result Canvas::update(Paint* paint) noexcept { +dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Update", this); + return pImpl->update(paint, false); } Result Canvas::sync() noexcept { +dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Sync", this); + if (pImpl->renderer->sync()) return Result::Success; return Result::InsufficientCondition; diff --git a/src/lib/tvgCanvasImpl.h b/src/lib/tvgCanvasImpl.h index 2772a23..b5c22c8 100644 --- a/src/lib/tvgCanvasImpl.h +++ b/src/lib/tvgCanvasImpl.h @@ -86,9 +86,11 @@ struct Canvas::Impl //Update single paint node if (paint) { + dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update a paint(%p)", this, paint); paint->pImpl->update(*renderer, nullptr, 255, clips, flag); //Update all retained paint nodes } else { + dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update paints count(%d)", this, paints.count); for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { (*paint)->pImpl->update(*renderer, nullptr, 255, clips, flag); } @@ -96,6 +98,8 @@ struct Canvas::Impl refresh = false; + dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update finished", this); + return Result::Success; } @@ -103,12 +107,16 @@ struct Canvas::Impl { if (!renderer || !renderer->preRender()) return Result::InsufficientCondition; + dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) draw paints count(%d)", this, paints.count); + for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { if (!(*paint)->pImpl->render(*renderer)) return Result::InsufficientCondition; } if (!renderer->postRender()) return Result::InsufficientCondition; + dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) draw finished", this); + return Result::Success; } }; diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index f5d4a6d..8fcb681 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -22,6 +22,7 @@ #ifndef _TVG_COMMON_H_ #define _TVG_COMMON_H_ +#include #include "config.h" #include "thorvg.h" @@ -31,6 +32,8 @@ using namespace tvg; #define FILL_ID_LINEAR 0 #define FILL_ID_RADIAL 1 +#define LOG_TAG "thorvg" + #define TVG_UNUSED __attribute__ ((__unused__)) #endif //_TVG_COMMON_H_ diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index c91e13e..e144fb6 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -45,6 +45,8 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept { auto nonSupport = true; +dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized!"); + if (static_cast(engine) & static_cast(CanvasEngine::Sw)) { #ifdef THORVG_SW_RASTER_SUPPORT if (!SwRenderer::init(threads)) return Result::InsufficientCondition; @@ -65,12 +67,17 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept TaskScheduler::init(threads); +dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized! - Success"); + return Result::Success; } Result Initializer::term(CanvasEngine engine) noexcept { + +dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated!"); + auto nonSupport = true; if (static_cast(engine) & static_cast(CanvasEngine::Sw)) { @@ -93,5 +100,7 @@ Result Initializer::term(CanvasEngine engine) noexcept if (!LoaderMgr::term()) return Result::Unknown; +dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated! - Success"); + return Result::Success; -} \ No newline at end of file +} diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index aca756f..5e20587 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -164,6 +164,8 @@ bool Paint::Impl::render(RenderMethod& renderer) { Compositor* cmp = nullptr; +dlog_print(DLOG_ERROR, LOG_TAG, "render paint (%p) type(%d)", this, (int) this->type); + /* Note: only ClipPath is processed in update() step. Create a composition image. */ if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) { @@ -194,6 +196,8 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } } +dlog_print(DLOG_ERROR, LOG_TAG, "update paint (%p) type(%d)", this, (int) this->type); + /* 1. Composition Pre Processing */ void *cmpData = nullptr; RenderRegion viewport; @@ -316,4 +320,4 @@ Result Paint::opacity(uint8_t o) noexcept uint8_t Paint::opacity() const noexcept { return pImpl->opacity; -} \ No newline at end of file +} diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 40f1e58..1ea5447 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -58,22 +58,31 @@ struct Scene::Impl void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flag) { +dlog_print(DLOG_ERROR, LOG_TAG, "====> Update Scene(%p), paints count(%d)", this, paints.count); + /* Overriding opacity value. If this scene is half-translucent, It must do intermeidate composition with that opacity value. */ this->opacity = static_cast(opacity); if (needComposition(opacity)) opacity = 255; + for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { (*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast(flag)); } /* FXIME: it requires to return list of children engine data This is necessary for scene composition */ + +dlog_print(DLOG_ERROR, LOG_TAG, "<==== Update Scene(%p), paints count(%d)", this, paints.count); + return nullptr; } bool render(RenderMethod& renderer) { + +dlog_print(DLOG_ERROR, LOG_TAG, "====> Render Scene(%p), paints count(%d)", this, paints.count); + Compositor* cmp = nullptr; if (needComposition(opacity)) { @@ -87,6 +96,8 @@ struct Scene::Impl if (cmp) renderer.endComposite(cmp); +dlog_print(DLOG_ERROR, LOG_TAG, "<==== Render Scene(%p), paints count(%d)", this, paints.count); + return true; } diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp index 63ac4de..97eb16b 100644 --- a/src/lib/tvgTaskScheduler.cpp +++ b/src/lib/tvgTaskScheduler.cpp @@ -167,6 +167,9 @@ static TaskSchedulerImpl* inst = nullptr; void TaskScheduler::init(unsigned threads) { if (inst) return; + +dlog_print(DLOG_ERROR, LOG_TAG, "Init TaskScheduler threads = %d", threads); + inst = new TaskSchedulerImpl(threads); } @@ -189,4 +192,4 @@ unsigned TaskScheduler::threads() { if (inst) return inst->threadCnt; return 0; -} \ No newline at end of file +} diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index f359855..af0cc33 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -595,6 +595,8 @@ static Matrix* _parseTransformationMatrix(const char* value) char* str = (char*)value; char* end = str + strlen(str); + dlog_print(DLOG_ERROR, LOG_TAG, "_parseTransformationMatrix() - begin"); + while (str < end) { auto state = MatrixState::Unknown; @@ -658,9 +660,15 @@ static Matrix* _parseTransformationMatrix(const char* value) _matrixCompose(matrix, &tmp, matrix); } } + +dlog_print(DLOG_ERROR, LOG_TAG, "_parseTransformationMatrix() - end"); + return matrix; error: if (matrix) free(matrix); + +dlog_print(DLOG_ERROR, LOG_TAG, "_parseTransformationMatrix() - error"); + return nullptr; } @@ -2644,6 +2652,8 @@ bool SvgLoader::open(const string& path) this->size = filePath.size(); } + dlog_print(DLOG_ERROR, LOG_TAG, "SvgLoader open(%p) - %s", this, path.c_str()); + return header(); } @@ -2652,8 +2662,12 @@ bool SvgLoader::read() { if (!content || size == 0) return false; + dlog_print(DLOG_ERROR, LOG_TAG, "SvgLoader read(%p) - before", this); + TaskScheduler::request(this); + dlog_print(DLOG_ERROR, LOG_TAG, "SvgLoader read(%p) - after", this); + return true; } diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index b2be859..a5ddb75 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -402,6 +402,8 @@ unique_ptr svgSceneBuild(SvgNode* node) { if (!node || (node->type != SvgNodeType::Doc)) return nullptr; +dlog_print(DLOG_ERROR, LOG_TAG, "svgSceneBuild() node(%p) - begin", node); + auto vx = node->node.doc.vx; auto vy = node->node.doc.vy; auto vw = node->node.doc.vw; @@ -427,5 +429,8 @@ unique_ptr svgSceneBuild(SvgNode* node) } else { root = move(docNode); } + +dlog_print(DLOG_ERROR, LOG_TAG, "svgSceneBuild() - end"); + return root; } diff --git a/src/meson.build b/src/meson.build index 7e19d03..d386e13 100644 --- a/src/meson.build +++ b/src/meson.build @@ -17,7 +17,8 @@ subdir('loaders') subdir('bindings') thread_dep = meson.get_compiler('cpp').find_library('pthread') -thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep] +dlog_dep = dependency('dlog', required: false) +thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep, dlog_dep] thorvg_lib = library( 'thorvg', -- 2.7.4 From bec160da93cac292e30c4afdea986816b6db6867 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Tue, 13 Apr 2021 13:12:53 +0200 Subject: [PATCH 06/16] examples: ignoring pictures other than svgs in Stress.cpp The picture->size() function does not work for raw/png pictures. As a consequence enabling both, the svg and png file loaders, resulted in the unintended behavior of the example. --- src/examples/Stress.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/examples/Stress.cpp b/src/examples/Stress.cpp index 862b6af..9085731 100644 --- a/src/examples/Stress.cpp +++ b/src/examples/Stress.cpp @@ -38,6 +38,10 @@ static double t1, t2, t3, t4; void svgDirCallback(const char* name, const char* path, void* data) { + //ignore if not svgs. + const char *ext = name + strlen(name) - 3; + if (strcmp(ext, "svg")) return; + auto picture = tvg::Picture::gen(); char buf[PATH_MAX]; -- 2.7.4 From fc933487b40fba7b766a4058aa2ea6b8264aeb64 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 14 Apr 2021 20:16:19 +0900 Subject: [PATCH 07/16] common initializer: counting engine init count properly. Manage the reference count in common so that all common resources can be initialized/terminated identically. Change-Id: Ica05c031774d212c068bb055aa8f74123d9915dc --- src/lib/tvgInitializer.cpp | 11 ++++++++++- src/lib/tvgLoaderMgr.cpp | 9 --------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index e144fb6..2d971ec 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -36,6 +36,8 @@ /* Internal Class Implementation */ /************************************************************************/ +static int _initCnt = 0; + /************************************************************************/ /* External Class Implementation */ @@ -63,6 +65,9 @@ dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized!"); if (nonSupport) return Result::NonSupport; + if (_initCnt > 0) return Result::Success; + ++_initCnt; + if (!LoaderMgr::init()) return Result::Unknown; TaskScheduler::init(threads); @@ -75,8 +80,9 @@ dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized! - Success"); Result Initializer::term(CanvasEngine engine) noexcept { + dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated!"); -dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated!"); + if (_initCnt == 0) return Result::InsufficientCondition; auto nonSupport = true; @@ -96,6 +102,9 @@ dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated!"); if (nonSupport) return Result::NonSupport; + --_initCnt; + if (_initCnt > 0) return Result::Success; + TaskScheduler::term(); if (!LoaderMgr::term()) return Result::Unknown; diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index 31649ca..f7feb82 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -35,9 +35,6 @@ /* Internal Class Implementation */ /************************************************************************/ -static int initCnt = 0; - - static Loader* _find(FileType type) { switch(type) { @@ -104,9 +101,6 @@ static Loader* _find(const string& path) bool LoaderMgr::init() { - if (initCnt > 0) return true; - ++initCnt; - //TODO: return true; @@ -115,9 +109,6 @@ bool LoaderMgr::init() bool LoaderMgr::term() { - --initCnt; - if (initCnt > 0) return true; - //TODO: return true; -- 2.7.4 From b77a0c6c63fb2c42693895dbfb81270ede0e923d Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Wed, 14 Apr 2021 14:45:52 +0200 Subject: [PATCH 08/16] sw_engine: adding a check before stroke fill dereference The crash was observed for empty shapes. Change-Id: Ie1a38ebae6a6877caaf307bddcf93dd4ee07bd8d --- meson.build | 2 +- packaging/thorvg.spec | 2 +- src/lib/sw_engine/tvgSwRaster.cpp | 2 +- src/lib/tvgCanvas.cpp | 7 +++++++ src/lib/tvgPicture.cpp | 7 ++++++- src/lib/tvgShapeImpl.h | 3 +++ 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/meson.build b/meson.build index 98d5a0d..b337baf 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('thorvg', 'cpp', - default_options : ['buildtype=debugoptimized', 'werror=false', 'optimization=s'], + default_options : ['buildtype=debug', 'werror=false', 'optimization=0'], version : '0.1.0', license : 'MIT') diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index b24fec5..60a0125 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.1.0 +Version: 0.1.1 Release: 1 Group: Graphics System/Rendering Engine License: MIT diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index b117412..f5cb6c9 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -1033,7 +1033,7 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id) { - if (!shape->stroke->fill || !shape->strokeRle) return false; + if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false; if (id == FILL_ID_LINEAR) { if (shape->stroke->fill->translucent) return _rasterTranslucentLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill); diff --git a/src/lib/tvgCanvas.cpp b/src/lib/tvgCanvas.cpp index f886c74..a74580d 100644 --- a/src/lib/tvgCanvas.cpp +++ b/src/lib/tvgCanvas.cpp @@ -45,6 +45,7 @@ Result Canvas::reserve(uint32_t n) noexcept Result Canvas::push(unique_ptr paint) noexcept { + return Result::Success; return pImpl->push(move(paint)); } @@ -61,6 +62,8 @@ Result Canvas::draw() noexcept { dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Draw", this); + return Result::Success; + return pImpl->draw(); } @@ -69,6 +72,8 @@ Result Canvas::update(Paint* paint) noexcept { dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Update", this); + return Result::Success; + return pImpl->update(paint, false); } @@ -77,6 +82,8 @@ Result Canvas::sync() noexcept { dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Sync", this); + return Result::Success; + if (pImpl->renderer->sync()) return Result::Success; return Result::InsufficientCondition; diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 306de0d..637b19e 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -47,6 +47,7 @@ unique_ptr Picture::gen() noexcept Result Picture::load(const std::string& path) noexcept { + return Result::Success; if (path.empty()) return Result::InvalidArguments; return pImpl->load(path); @@ -55,6 +56,8 @@ Result Picture::load(const std::string& path) noexcept Result Picture::load(const char* data, uint32_t size) noexcept { + return Result::Success; + if (!data || size <= 0) return Result::InvalidArguments; return pImpl->load(data, size); @@ -63,6 +66,8 @@ Result Picture::load(const char* data, uint32_t size) noexcept Result Picture::load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept { + return Result::Success; + if (!data || w <= 0 || h <= 0) return Result::InvalidArguments; return pImpl->load(data, w, h, copy); @@ -97,4 +102,4 @@ const uint32_t* Picture::data() const noexcept if (pImpl->loader) return pImpl->loader->pixels(); return pImpl->pixels; -} \ No newline at end of file +} diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index b978221..e36e969 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -219,6 +219,7 @@ struct Shape::Impl bool dispose(RenderMethod& renderer) { + return true; auto ret = renderer.dispose(rdata); rdata = nullptr; return ret; @@ -226,11 +227,13 @@ struct Shape::Impl bool render(RenderMethod& renderer) { + return true; return renderer.renderShape(rdata); } void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) { + return nullptr; this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast(pFlag | flag)); flag = RenderUpdateFlag::None; return this->rdata; -- 2.7.4 From 16607a20099af82df71775ac8b194039e74443d4 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 15 Apr 2021 18:26:11 +0900 Subject: [PATCH 09/16] common: code refactoring. renamed internal function, no logical changes. Change-Id: Iea738826315a2f02f6d4f9d56b81a55379c09738 --- src/lib/tvgPaint.cpp | 2 +- src/lib/tvgRender.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 5e20587..7d73ceb 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -210,7 +210,7 @@ dlog_print(DLOG_ERROR, LOG_TAG, "update paint (%p) type(%d)", this, (int) this-> RenderRegion viewport2; if ((cmpFastTrack = _clipPathFastTrack(cmpTarget, pTransform, cmpTarget->pImpl->rTransform, viewport2))) { viewport = renderer.viewport(); - viewport2.merge(viewport); + viewport2.intersect(viewport); renderer.viewport(viewport2); } } diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 16da972..b45405a 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -49,7 +49,7 @@ struct Compositor { struct RenderRegion { uint32_t x, y, w, h; - void merge(const RenderRegion& rhs) + void intersect(const RenderRegion& rhs) { auto x1 = x + w; auto y1 = y + h; -- 2.7.4 From bb472459c99847e9742a8cf7bc1a14a6b58a444e Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Wed, 14 Apr 2021 01:19:33 +0200 Subject: [PATCH 10/16] loader svg: displaying SVG images without the specified viewBox attribute If no viewBox attribute is given, the height and width attributes are used to establish the viewBox size. However, this information was not available inside the scene builder, even though it was needed. Change-Id: Icf5a74936d26de5f10c3a3eb428c7800749c1e9d --- src/loaders/svg/tvgSvgLoader.cpp | 2 +- src/loaders/svg/tvgSvgSceneBuilder.cpp | 9 ++------- src/loaders/svg/tvgSvgSceneBuilder.h | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index af0cc33..e16ba83 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -2583,7 +2583,7 @@ void SvgLoader::run(unsigned tid) _updateComposite(loaderData.doc, loaderData.doc); if (defs) _updateComposite(loaderData.doc, defs); } - root = svgSceneBuild(loaderData.doc); + root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh); }; diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index a5ddb75..0648e2f 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -398,16 +398,11 @@ static unique_ptr _sceneBuildHelper(const SvgNode* node, float vx, float /* External Class Implementation */ /************************************************************************/ -unique_ptr svgSceneBuild(SvgNode* node) +unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh) { if (!node || (node->type != SvgNodeType::Doc)) return nullptr; -dlog_print(DLOG_ERROR, LOG_TAG, "svgSceneBuild() node(%p) - begin", node); - - auto vx = node->node.doc.vx; - auto vy = node->node.doc.vy; - auto vw = node->node.doc.vw; - auto vh = node->node.doc.vh; + dlog_print(DLOG_ERROR, LOG_TAG, "svgSceneBuild() node(%p) - begin", node); unique_ptr root; auto docNode = _sceneBuildHelper(node, vx, vy, vw, vh); diff --git a/src/loaders/svg/tvgSvgSceneBuilder.h b/src/loaders/svg/tvgSvgSceneBuilder.h index d1b8f8c..63b6b88 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); +unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh); #endif //_TVG_SVG_SCENE_BUILDER_H_ -- 2.7.4 From 05090488efc1fea4d1cd315adfca1df36e631b24 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 19 Apr 2021 10:48:56 +0900 Subject: [PATCH 11/16] bump up v0.1.2 Change-Id: Ia3f1dddf6c27fbe3894df637f15d8d9b55f7710c --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 60a0125..d3e1083 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.1.1 +Version: 0.1.2 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From a85e4c2855ca1b84d01667a0a021252921f6865a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 19 Apr 2021 11:45:14 +0900 Subject: [PATCH 12/16] resolve some unpexpected code involving while upstream code sync. Change-Id: Ie818f1db73e997bf6d7eaae24cf55303c55eceba --- meson.build | 2 +- packaging/thorvg.spec | 2 +- src/lib/tvgCanvas.cpp | 7 ------- src/lib/tvgPicture.cpp | 5 ----- src/lib/tvgShapeImpl.h | 3 --- 5 files changed, 2 insertions(+), 17 deletions(-) diff --git a/meson.build b/meson.build index b337baf..98d5a0d 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('thorvg', 'cpp', - default_options : ['buildtype=debug', 'werror=false', 'optimization=0'], + default_options : ['buildtype=debugoptimized', 'werror=false', 'optimization=s'], version : '0.1.0', license : 'MIT') diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index d3e1083..60a0125 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.1.2 +Version: 0.1.1 Release: 1 Group: Graphics System/Rendering Engine License: MIT diff --git a/src/lib/tvgCanvas.cpp b/src/lib/tvgCanvas.cpp index a74580d..f886c74 100644 --- a/src/lib/tvgCanvas.cpp +++ b/src/lib/tvgCanvas.cpp @@ -45,7 +45,6 @@ Result Canvas::reserve(uint32_t n) noexcept Result Canvas::push(unique_ptr paint) noexcept { - return Result::Success; return pImpl->push(move(paint)); } @@ -62,8 +61,6 @@ Result Canvas::draw() noexcept { dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Draw", this); - return Result::Success; - return pImpl->draw(); } @@ -72,8 +69,6 @@ Result Canvas::update(Paint* paint) noexcept { dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Update", this); - return Result::Success; - return pImpl->update(paint, false); } @@ -82,8 +77,6 @@ Result Canvas::sync() noexcept { dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Sync", this); - return Result::Success; - if (pImpl->renderer->sync()) return Result::Success; return Result::InsufficientCondition; diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 637b19e..ddbd3c0 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -47,7 +47,6 @@ unique_ptr Picture::gen() noexcept Result Picture::load(const std::string& path) noexcept { - return Result::Success; if (path.empty()) return Result::InvalidArguments; return pImpl->load(path); @@ -56,8 +55,6 @@ Result Picture::load(const std::string& path) noexcept Result Picture::load(const char* data, uint32_t size) noexcept { - return Result::Success; - if (!data || size <= 0) return Result::InvalidArguments; return pImpl->load(data, size); @@ -66,8 +63,6 @@ Result Picture::load(const char* data, uint32_t size) noexcept Result Picture::load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept { - return Result::Success; - if (!data || w <= 0 || h <= 0) return Result::InvalidArguments; return pImpl->load(data, w, h, copy); diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index e36e969..b978221 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -219,7 +219,6 @@ struct Shape::Impl bool dispose(RenderMethod& renderer) { - return true; auto ret = renderer.dispose(rdata); rdata = nullptr; return ret; @@ -227,13 +226,11 @@ struct Shape::Impl bool render(RenderMethod& renderer) { - return true; return renderer.renderShape(rdata); } void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) { - return nullptr; this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast(pFlag | flag)); flag = RenderUpdateFlag::None; return this->rdata; -- 2.7.4 From 84d7116108381768a193161fefd0f9506a41ac18 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 20 Apr 2021 17:43:16 +0900 Subject: [PATCH 13/16] loaders svg: ++safety prevent buffer overflow just in case. Change-Id: I58e079d00b4840437632716c3cdd0deea144c5c6 --- src/loaders/svg/tvgSvgLoader.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index e16ba83..83e738c 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -504,13 +504,13 @@ static void _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, string } -static char* _parseNumbersArray(char* str, float* points, int* ptCount) +static char* _parseNumbersArray(char* str, float* points, int* ptCount, int len) { int count = 0; char* end = nullptr; str = _skipSpace(str, nullptr); - while (isdigit(*str) || *str == '-' || *str == '+' || *str == '.') { + while ((count < len) && (isdigit(*str) || *str == '-' || *str == '+' || *str == '.')) { points[count++] = strtof(str, &end); str = end; str = _skipSpace(str, nullptr); @@ -586,11 +586,13 @@ static void _matrixCompose(const Matrix* m1, const Matrix* m2, Matrix* dst) */ static Matrix* _parseTransformationMatrix(const char* value) { + const int POINT_CNT = 8; + auto matrix = (Matrix*)malloc(sizeof(Matrix)); if (!matrix) return nullptr; *matrix = {1, 0, 0, 0, 1, 0, 0, 0, 1}; - float points[8]; + float points[POINT_CNT]; int ptCount = 0; char* str = (char*)value; char* end = str + strlen(str); @@ -616,7 +618,7 @@ static Matrix* _parseTransformationMatrix(const char* value) str = _skipSpace(str, end); if (*str != '(') goto error; ++str; - str = _parseNumbersArray(str, points, &ptCount); + str = _parseNumbersArray(str, points, &ptCount, POINT_CNT); if (*str != ')') goto error; ++str; -- 2.7.4 From 538f13b6af437bb3d3c119e01f3a7d415c2a5a13 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 20 Apr 2021 17:55:18 +0900 Subject: [PATCH 14/16] bump up v0.1.2 Change-Id: Ia351fa777c21654308ae0d717feddbcfa24592ab --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 60a0125..d3e1083 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.1.1 +Version: 0.1.2 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From af7bc1a346ea2d02353210b4bd6be992286b678f Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 20 Apr 2021 18:01:04 +0900 Subject: [PATCH 15/16] loader SvgLoader: add locale-independent strtof function strtof's behavior is changed by system locale. https://linux.die.net/man/3/strtof Because of this, strtof(10.0000) returns 0.0 in some locales. When a given value string is locale-independent, strtof has to be replaced to custom function. Change-Id: I0166c434990ef8b692f0007d24112aa61c6ef679 --- src/loaders/svg/tvgSvgLoader.cpp | 220 +++++++++++++++++++++++++++++++++-- src/loaders/svg/tvgSvgLoaderCommon.h | 14 +++ src/loaders/svg/tvgSvgPath.cpp | 2 +- 3 files changed, 226 insertions(+), 10 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 83e738c..cec4b7b 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -35,6 +35,208 @@ typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength); +/* + * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtof-l-wcstof-wcstof-l?view=msvc-160 + * + * src should be one of the following form : + * + * [whitespace] [sign] {digits [radix digits] | radix digits} [{e | E} [sign] digits] + * [whitespace] [sign] {INF | INFINITY} + * [whitespace] [sign] NAN [sequence] + * + * No hexadecimal form supported + * no sequence supported after NAN + */ +static bool floatExact(float a, float b) +{ + return memcmp(&a, &b, sizeof (float)) == 0; +} + + +float customStrtof(const char *nPtr, char **endPtr) +{ + const char *iter; + const char *a; + float val; + unsigned long long integerPart; + int minus; + + if (endPtr) *endPtr = (char*)nPtr; + if (!nPtr) return 0.0f; + + a = iter = nPtr; + + //ignore leading whitespaces + while (isspace(*iter)) iter++; + + //signed or not + minus = 1; + if (*iter == '-') + { + minus = -1; + iter++; + } + else if (*iter == '+') iter++; + + if (tolower(*iter) == 'i') + { + if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'f')) + { + iter += 3; + } + else goto on_error; + + if (tolower(*(iter + 3)) == 'i') + { + if ((tolower(*(iter + 4)) == 'n') && + (tolower(*(iter + 5)) == 'i') && + (tolower(*(iter + 6)) == 't') && + (tolower(*(iter + 7)) == 'y')) + { + iter += 5; + } + else goto on_error; + } + if (endPtr) *endPtr = (char *)iter; + return (minus == -1) ? -INFINITY : INFINITY; + } + + if (tolower(*iter) == 'n') + { + if ((tolower(*(iter + 1)) == 'a') && (tolower(*(iter + 2)) == 'n')) iter += 3; + else goto on_error; + + if (endPtr) *endPtr = (char *)iter; + return (minus == -1) ? -NAN : NAN; + } + + integerPart = 0; + + //(optional) integer part before dot + if (isdigit(*iter)) + { + for (; isdigit(*iter); iter++) integerPart = integerPart * 10ULL + (unsigned long long)(*iter - '0'); + + a = iter; + } + else if (*iter != '.') + { + val = 0.0; + goto on_success; + } + + val = (float)integerPart; + + //(optional) decimal part after dot + if (*iter == '.') + { + unsigned long long decimalPart; + unsigned long long pow10; + int count; + + iter++; + + decimalPart = 0; + count = 0; + pow10 = 1; + + if (isdigit(*iter)) + { + for (; isdigit(*iter); iter++, count++) + { + if (count < 19) + { + decimalPart = decimalPart * 10ULL + + (unsigned long long)(*iter - '0'); + pow10 *= 10ULL; + } + } + } + val += (float)decimalPart / (float)pow10; + a = iter; + } + + //(optional) exponent + if ((*iter == 'e') || (*iter == 'E')) + { + float scale = 1.0f; + unsigned int expo_part; + int minus_e; + + iter++; + + //signed or not + minus_e = 1; + if (*iter == '-') + { + minus_e = -1; + iter++; + } + else if (*iter == '+') iter++; + + //exponential part + expo_part = 0; + if (isdigit(*iter)) + { + while (*iter == 0) iter++; + + for (; isdigit(*iter); iter++) + { + expo_part = expo_part * 10U + (unsigned int)(*iter - '0'); + } + } + else if (!isdigit(*(a - 1))) + { + a = nPtr; + goto on_success; + } + else if (*iter == 0) goto on_success; + + if ((floatExact(val, 2.2250738585072011)) && ((minus_e * (int)expo_part) == -308)) + { + val *= 1.0e-308; + a = iter; + errno = ERANGE; + goto on_success; + } + + if ((floatExact(val, 2.2250738585072012)) && ((minus_e * (int)expo_part) <= -308)) + { + val *= 1.0e-308; + a = iter; + goto on_success; + } + + a = iter; + + while (expo_part >= 8U) + { + scale *= 1E8; + expo_part -= 8U; + } + while (expo_part > 0U) + { + scale *= 10.0f; + expo_part--; + } + + val = (minus_e == -1) ? (val / scale) : (val * scale); + } + else if ((iter > nPtr) && !isdigit(*(iter - 1))) + { + a = nPtr; + goto on_success; + } + +on_success: + if (endPtr) *endPtr = (char *)a; + return minus * val; + +on_error: + if (endPtr) *endPtr = (char *)nPtr; + return 0.0f; +} + + static char* _skipSpace(const char* str, const char* end) { while (((end && str < end) || (!end && *str != '\0')) && isspace(*str)) { @@ -64,7 +266,7 @@ static bool _parseNumber(const char** content, float* number) { char* end = nullptr; - *number = strtof(*content, &end); + *number = customStrtof(*content, &end); //If the start of string is not number if ((*content) == end) return false; //Skip comma if any @@ -81,7 +283,7 @@ static bool _parseNumber(const char** content, float* number) */ static float _toFloat(const SvgParser* svgParse, const char* str, SvgParserLengthType type) { - float parsedValue = strtof(str, nullptr); + float parsedValue = customStrtof(str, nullptr); if (strstr(str, "cm")) parsedValue = parsedValue * 35.43307; else if (strstr(str, "mm")) parsedValue = parsedValue * 3.543307; @@ -110,7 +312,7 @@ static float _gradientToFloat(const SvgParser* svgParse, const char* str, SvgPar { char* end = nullptr; - float parsedValue = strtof(str, &end); + float parsedValue = customStrtof(str, &end); float max = 1; /** @@ -141,7 +343,7 @@ static float _toOffset(const char* str) { char* end = nullptr; - float parsedValue = strtof(str, &end); + float parsedValue = customStrtof(str, &end); if (strstr(str, "%")) parsedValue = parsedValue / 100.0; @@ -153,7 +355,7 @@ static int _toOpacity(const char* str) { char* end = nullptr; int a = 0; - float opacity = strtof(str, &end); + float opacity = customStrtof(str, &end); if (end && (*end == '\0')) a = lrint(opacity * 255); return a; @@ -240,7 +442,7 @@ _parseDashArray(const char *str, SvgDash* dash) while (*str) { // skip white space, comma str = _skipComma(str); - (*dash).array.push(strtof(str, &end)); + (*dash).array.push(customStrtof(str, &end)); str = _skipComma(end); } //If dash array size is 1, it means that dash and gap size are the same. @@ -274,7 +476,7 @@ static unsigned char _parserColor(const char* value, char** end) { float r; - r = strtof(value + 4, end); + r = customStrtof(value + 4, end); *end = _skipSpace(*end, nullptr); if (**end == '%') r = 255 * r / 100; *end = _skipSpace(*end, nullptr); @@ -511,7 +713,7 @@ static char* _parseNumbersArray(char* str, float* points, int* ptCount, int len) str = _skipSpace(str, nullptr); while ((count < len) && (isdigit(*str) || *str == '-' || *str == '+' || *str == '.')) { - points[count++] = strtof(str, &end); + points[count++] = customStrtof(str, &end); str = end; str = _skipSpace(str, nullptr); if (*str == ',') ++str; @@ -706,7 +908,7 @@ static float _parseLength(const char* str, SvgLengthType* type) for (unsigned int i = 0; i < sizeof(lengthTags) / sizeof(lengthTags[0]); i++) { if (lengthTags[i].sz - 1 == sz && !strncmp(lengthTags[i].tag, str, sz)) *type = lengthTags[i].type; } - value = strtof(str, nullptr); + value = customStrtof(str, nullptr); return value; } diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index b639efe..bc44167 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -343,4 +343,18 @@ struct SvgLoaderData bool result = false; }; +/* + * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtod-l-wcstod-wcstod-l?view=vs-2017 + * + * src should be one of the following form : + * + * [whitespace] [sign] {digits [radix digits] | radix digits} [{e | E} [sign] digits] + * [whitespace] [sign] {INF | INFINITY} + * [whitespace] [sign] NAN [sequence] + * + * No hexadecimal form supported + * no sequence supported after NAN + */ +float customStrtof(const char *nptr, char **endptr); + #endif diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index 08a3a54..331a833 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -42,7 +42,7 @@ static char* _skipComma(const char* content) static bool _parseNumber(char** content, float* number) { char* end = NULL; - *number = strtof(*content, &end); + *number = customStrtof(*content, &end); //If the start of string is not number if ((*content) == end) return false; //Skip comma if any -- 2.7.4 From dd76d8f9d3f78f250ce35617d48fefbe1a163b78 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 20 Apr 2021 20:12:05 +0900 Subject: [PATCH 16/16] Revert "** Temporary patch for diagnosing some hideous bugs in Tizen **" This reverts commit 9996be4c047b5b3b9ced9fabe3c4b888ed795cff. Change-Id: Ib5f0ee8c5d63012863d22e3ba051278be6e99982 --- packaging/thorvg.spec | 2 -- src/lib/tvgCanvas.cpp | 8 -------- src/lib/tvgCanvasImpl.h | 8 -------- src/lib/tvgCommon.h | 3 --- src/lib/tvgInitializer.cpp | 8 -------- src/lib/tvgPaint.cpp | 6 +----- src/lib/tvgSceneImpl.h | 11 ----------- src/lib/tvgTaskScheduler.cpp | 5 +---- src/loaders/svg/tvgSvgLoader.cpp | 14 -------------- src/loaders/svg/tvgSvgSceneBuilder.cpp | 5 ----- src/meson.build | 3 +-- 11 files changed, 3 insertions(+), 70 deletions(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index d3e1083..171cbec 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -9,8 +9,6 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: pkgconfig BuildRequires: pkgconfig(glesv2) -BuildRequires: pkgconfig(dlog) - BuildRequires: meson BuildRequires: ninja Requires(post): /sbin/ldconfig diff --git a/src/lib/tvgCanvas.cpp b/src/lib/tvgCanvas.cpp index f886c74..309e205 100644 --- a/src/lib/tvgCanvas.cpp +++ b/src/lib/tvgCanvas.cpp @@ -51,32 +51,24 @@ Result Canvas::push(unique_ptr paint) noexcept Result Canvas::clear(bool free) noexcept { -dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Clear", this); - return pImpl->clear(free); } Result Canvas::draw() noexcept { -dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Draw", this); - return pImpl->draw(); } Result Canvas::update(Paint* paint) noexcept { -dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Update", this); - return pImpl->update(paint, false); } Result Canvas::sync() noexcept { -dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) Sync", this); - if (pImpl->renderer->sync()) return Result::Success; return Result::InsufficientCondition; diff --git a/src/lib/tvgCanvasImpl.h b/src/lib/tvgCanvasImpl.h index b5c22c8..2772a23 100644 --- a/src/lib/tvgCanvasImpl.h +++ b/src/lib/tvgCanvasImpl.h @@ -86,11 +86,9 @@ struct Canvas::Impl //Update single paint node if (paint) { - dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update a paint(%p)", this, paint); paint->pImpl->update(*renderer, nullptr, 255, clips, flag); //Update all retained paint nodes } else { - dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update paints count(%d)", this, paints.count); for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { (*paint)->pImpl->update(*renderer, nullptr, 255, clips, flag); } @@ -98,8 +96,6 @@ struct Canvas::Impl refresh = false; - dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) update finished", this); - return Result::Success; } @@ -107,16 +103,12 @@ struct Canvas::Impl { if (!renderer || !renderer->preRender()) return Result::InsufficientCondition; - dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) draw paints count(%d)", this, paints.count); - for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { if (!(*paint)->pImpl->render(*renderer)) return Result::InsufficientCondition; } if (!renderer->postRender()) return Result::InsufficientCondition; - dlog_print(DLOG_ERROR, LOG_TAG, "Canvas(%p) draw finished", this); - return Result::Success; } }; diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 8fcb681..f5d4a6d 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -22,7 +22,6 @@ #ifndef _TVG_COMMON_H_ #define _TVG_COMMON_H_ -#include #include "config.h" #include "thorvg.h" @@ -32,8 +31,6 @@ using namespace tvg; #define FILL_ID_LINEAR 0 #define FILL_ID_RADIAL 1 -#define LOG_TAG "thorvg" - #define TVG_UNUSED __attribute__ ((__unused__)) #endif //_TVG_COMMON_H_ diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 2d971ec..039048a 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -47,8 +47,6 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept { auto nonSupport = true; -dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized!"); - if (static_cast(engine) & static_cast(CanvasEngine::Sw)) { #ifdef THORVG_SW_RASTER_SUPPORT if (!SwRenderer::init(threads)) return Result::InsufficientCondition; @@ -72,16 +70,12 @@ dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized!"); TaskScheduler::init(threads); -dlog_print(DLOG_ERROR, LOG_TAG, "Inititlized! - Success"); - return Result::Success; } Result Initializer::term(CanvasEngine engine) noexcept { - dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated!"); - if (_initCnt == 0) return Result::InsufficientCondition; auto nonSupport = true; @@ -109,7 +103,5 @@ Result Initializer::term(CanvasEngine engine) noexcept if (!LoaderMgr::term()) return Result::Unknown; -dlog_print(DLOG_ERROR, LOG_TAG, "Terminiated! - Success"); - return Result::Success; } diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 7d73ceb..9b0aba7 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -164,8 +164,6 @@ bool Paint::Impl::render(RenderMethod& renderer) { Compositor* cmp = nullptr; -dlog_print(DLOG_ERROR, LOG_TAG, "render paint (%p) type(%d)", this, (int) this->type); - /* Note: only ClipPath is processed in update() step. Create a composition image. */ if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) { @@ -196,8 +194,6 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } } -dlog_print(DLOG_ERROR, LOG_TAG, "update paint (%p) type(%d)", this, (int) this->type); - /* 1. Composition Pre Processing */ void *cmpData = nullptr; RenderRegion viewport; @@ -320,4 +316,4 @@ Result Paint::opacity(uint8_t o) noexcept uint8_t Paint::opacity() const noexcept { return pImpl->opacity; -} +} \ No newline at end of file diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 1ea5447..40f1e58 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -58,31 +58,22 @@ struct Scene::Impl void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flag) { -dlog_print(DLOG_ERROR, LOG_TAG, "====> Update Scene(%p), paints count(%d)", this, paints.count); - /* Overriding opacity value. If this scene is half-translucent, It must do intermeidate composition with that opacity value. */ this->opacity = static_cast(opacity); if (needComposition(opacity)) opacity = 255; - for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { (*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast(flag)); } /* FXIME: it requires to return list of children engine data This is necessary for scene composition */ - -dlog_print(DLOG_ERROR, LOG_TAG, "<==== Update Scene(%p), paints count(%d)", this, paints.count); - return nullptr; } bool render(RenderMethod& renderer) { - -dlog_print(DLOG_ERROR, LOG_TAG, "====> Render Scene(%p), paints count(%d)", this, paints.count); - Compositor* cmp = nullptr; if (needComposition(opacity)) { @@ -96,8 +87,6 @@ dlog_print(DLOG_ERROR, LOG_TAG, "====> Render Scene(%p), paints count(%d)", this if (cmp) renderer.endComposite(cmp); -dlog_print(DLOG_ERROR, LOG_TAG, "<==== Render Scene(%p), paints count(%d)", this, paints.count); - return true; } diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp index 97eb16b..63ac4de 100644 --- a/src/lib/tvgTaskScheduler.cpp +++ b/src/lib/tvgTaskScheduler.cpp @@ -167,9 +167,6 @@ static TaskSchedulerImpl* inst = nullptr; void TaskScheduler::init(unsigned threads) { if (inst) return; - -dlog_print(DLOG_ERROR, LOG_TAG, "Init TaskScheduler threads = %d", threads); - inst = new TaskSchedulerImpl(threads); } @@ -192,4 +189,4 @@ unsigned TaskScheduler::threads() { if (inst) return inst->threadCnt; return 0; -} +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index cec4b7b..c842120 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -799,8 +799,6 @@ static Matrix* _parseTransformationMatrix(const char* value) char* str = (char*)value; char* end = str + strlen(str); - dlog_print(DLOG_ERROR, LOG_TAG, "_parseTransformationMatrix() - begin"); - while (str < end) { auto state = MatrixState::Unknown; @@ -864,15 +862,9 @@ static Matrix* _parseTransformationMatrix(const char* value) _matrixCompose(matrix, &tmp, matrix); } } - -dlog_print(DLOG_ERROR, LOG_TAG, "_parseTransformationMatrix() - end"); - return matrix; error: if (matrix) free(matrix); - -dlog_print(DLOG_ERROR, LOG_TAG, "_parseTransformationMatrix() - error"); - return nullptr; } @@ -2856,8 +2848,6 @@ bool SvgLoader::open(const string& path) this->size = filePath.size(); } - dlog_print(DLOG_ERROR, LOG_TAG, "SvgLoader open(%p) - %s", this, path.c_str()); - return header(); } @@ -2866,12 +2856,8 @@ bool SvgLoader::read() { if (!content || size == 0) return false; - dlog_print(DLOG_ERROR, LOG_TAG, "SvgLoader read(%p) - before", this); - TaskScheduler::request(this); - dlog_print(DLOG_ERROR, LOG_TAG, "SvgLoader read(%p) - after", this); - return true; } diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index 0648e2f..df73370 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -402,8 +402,6 @@ unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo { if (!node || (node->type != SvgNodeType::Doc)) return nullptr; - dlog_print(DLOG_ERROR, LOG_TAG, "svgSceneBuild() node(%p) - begin", node); - unique_ptr root; auto docNode = _sceneBuildHelper(node, vx, vy, vw, vh); float x, y, w, h; @@ -424,8 +422,5 @@ unique_ptr svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo } else { root = move(docNode); } - -dlog_print(DLOG_ERROR, LOG_TAG, "svgSceneBuild() - end"); - return root; } diff --git a/src/meson.build b/src/meson.build index d386e13..7e19d03 100644 --- a/src/meson.build +++ b/src/meson.build @@ -17,8 +17,7 @@ subdir('loaders') subdir('bindings') thread_dep = meson.get_compiler('cpp').find_library('pthread') -dlog_dep = dependency('dlog', required: false) -thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep, dlog_dep] +thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep] thorvg_lib = library( 'thorvg', -- 2.7.4