From 018f4919da4cfcbd3df97c5da91054a8f31688e0 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 7 Jul 2020 17:46:29 +0900 Subject: [PATCH 01/16] svg_loader: allow deferred loading. don't push thread to work hard unless it's necessary. that might occur performance drop. Change-Id: Ib71fa0ae46461b10b7ed7ef356512fbf2a7aa0a8 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 928c754..2bfafdb 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -2295,7 +2295,7 @@ bool SvgLoader::read() return loader->builder.build(loader->loaderData.doc); }; - rootProgress = async(launch::async, asyncTask, this); + rootProgress = async((launch::async | launch::deferred), asyncTask, this); return true; } -- 2.7.4 From c0280e6d57ead75dd0304cb2cdbcf1efb36513c3 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 7 Jul 2020 17:52:16 +0900 Subject: [PATCH 02/16] svg_loader: code refactoring. initialize members in its own constructor. Change-Id: I6450971330dd3e3235b0f690a8d9b066cf374212 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 11 +---------- src/loaders/svg_loader/tvgSvgLoaderCommon.h | 14 +++++++------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 2bfafdb..cf91fb2 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -2226,16 +2226,7 @@ static void _freeSvgNode(SvgNode* node) /* External Class Implementation */ /************************************************************************/ - -SvgLoader::SvgLoader() : - loaderData {vector(), - nullptr, - nullptr, - vector(), - nullptr, - nullptr, - 0, - false} +SvgLoader::SvgLoader() { } diff --git a/src/loaders/svg_loader/tvgSvgLoaderCommon.h b/src/loaders/svg_loader/tvgSvgLoaderCommon.h index a909e54..b5ae7bb 100644 --- a/src/loaders/svg_loader/tvgSvgLoaderCommon.h +++ b/src/loaders/svg_loader/tvgSvgLoaderCommon.h @@ -325,13 +325,13 @@ struct SvgParser struct SvgLoaderData { vector stack; - SvgNode* doc; - SvgNode* def; + SvgNode* doc = nullptr; + SvgNode* def = nullptr; vector gradients; - SvgStyleGradient* latestGradient; //For stops - SvgParser* svgParse; - int level; - bool result; + SvgStyleGradient* latestGradient = nullptr; //For stops + SvgParser* svgParse = nullptr; + int level = 0; + bool result = false; }; -#endif +#endif \ No newline at end of file -- 2.7.4 From e2fc3538463a8e8b8370cb81ef6758df750a43cf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 8 Jul 2020 10:44:51 +0900 Subject: [PATCH 03/16] build: refactoriong meson script. move gl dependency to gl_engine part which is right position. Change-Id: I9d4935f94eff96ca1527762c92d07f9b216f19cd --- meson.build | 2 +- src/lib/gl_engine/meson.build | 7 ++++++- src/meson.build | 6 +----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/meson.build b/meson.build index b1cf7ac..66b907d 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('thorvg', 'cpp', - default_options : ['buildtype=debugoptimized', 'werror=false', 'cpp_std=c++14', 'optimization=s'], + default_options : ['buildtype=debugoptimized', 'werror=false', 'cpp_std=c++17', 'optimization=s'], version : '0.1.0', license : 'Apache-2.0') diff --git a/src/lib/gl_engine/meson.build b/src/lib/gl_engine/meson.build index 943fb06..6856f1d 100644 --- a/src/lib/gl_engine/meson.build +++ b/src/lib/gl_engine/meson.build @@ -14,7 +14,12 @@ source_file = [ 'tvgGlShaderSrc.cpp', ] +egl_dep = meson.get_compiler('cpp').find_library('EGL') +gles_dep = meson.get_compiler('cpp').find_library('GLESv2') +external_dep = [egl_dep, gles_dep] + glengine_dep = declare_dependency( + dependencies : external_dep, include_directories : include_directories('.'), - sources : source_file + sources : source_file, ) diff --git a/src/meson.build b/src/meson.build index 493497b..7320bb2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -4,12 +4,8 @@ subdir('lib') subdir('loaders') subdir('examples') -m_dep = meson.get_compiler('cpp').find_library('m') thread_dep = meson.get_compiler('cpp').find_library('pthread') -egl_dep = meson.get_compiler('cpp').find_library('EGL') -gles_dep = meson.get_compiler('cpp').find_library('GLESv2') - -thorvg_lib_dep = [ src_dep, swengine_dep, glengine_dep, m_dep, egl_dep, gles_dep, svgloader_dep, thread_dep] +thorvg_lib_dep = [ src_dep, swengine_dep, glengine_dep, svgloader_dep, thread_dep] thorvg_lib = library( -- 2.7.4 From 84af527a27b7e2cbe67717ee5fbb527ec903d35c Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 8 Jul 2020 10:51:34 +0900 Subject: [PATCH 04/16] build: refactoring meson script. move out engine/loader dependency to its immediate parent folders. Change-Id: I7f08433fc6d2a333951fceaffea81cbe2e5da9e3 --- meson.build | 2 +- src/lib/meson.build | 8 +++++--- src/loaders/meson.build | 5 +++++ src/meson.build | 3 +-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 66b907d..0142de0 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('thorvg', 'cpp', - default_options : ['buildtype=debugoptimized', 'werror=false', 'cpp_std=c++17', 'optimization=s'], + default_options : ['buildtype=debugoptimized', 'werror=false', 'optimization=s'], version : '0.1.0', license : 'Apache-2.0') diff --git a/src/lib/meson.build b/src/lib/meson.build index 53c9a19..9a7dc61 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -25,8 +25,10 @@ source_file = [ 'tvgSwCanvas.cpp', ] -src_dep = declare_dependency( +engine_dep = [swengine_dep, glengine_dep] + +common_dep = declare_dependency( + dependencies : engine_dep, include_directories : include_directories('.'), - sources : source_file + sources : source_file ) - diff --git a/src/loaders/meson.build b/src/loaders/meson.build index 53186dd..3abf0fd 100644 --- a/src/loaders/meson.build +++ b/src/loaders/meson.build @@ -1 +1,6 @@ subdir('svg_loader') + +loader_dep = declare_dependency( + dependencies : svgloader_dep, + include_directories : include_directories('.'), +) diff --git a/src/meson.build b/src/meson.build index 7320bb2..faff2b3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,8 +5,7 @@ subdir('loaders') subdir('examples') thread_dep = meson.get_compiler('cpp').find_library('pthread') -thorvg_lib_dep = [ src_dep, swengine_dep, glengine_dep, svgloader_dep, thread_dep] - +thorvg_lib_dep = [ common_dep, loader_dep, thread_dep] thorvg_lib = library( 'thorvg', -- 2.7.4 From 99428ee80a2f9ab8774fb151a6ef7dcbd60ad207 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 8 Jul 2020 13:08:28 +0900 Subject: [PATCH 05/16] build: support features toggling in meson option. Change-Id: Id1ebda70fe8380aaa913f79af26e5c39893a6df5 --- meson.build | 18 +++++++++++++--- meson_options.txt | 11 ++++++++++ src/lib/gl_engine/meson.build | 10 ++++----- src/lib/meson.build | 13 ++++++++---- src/lib/sw_engine/meson.build | 8 +++---- src/lib/tvgCommon.h | 2 ++ src/lib/tvgGlCanvas.cpp | 21 ++++++++++++++++++- src/lib/tvgInitializer.cpp | 39 +++++++++++++++++++++++++++------- src/lib/tvgLoaderMgr.cpp | 9 ++++++-- src/lib/tvgRender.h | 18 ++++++++-------- src/lib/tvgSwCanvas.cpp | 21 +++++++++++++++++-- src/loaders/meson.build | 8 +++++-- src/loaders/svg_loader/meson.build | 8 +++---- src/meson.build | 2 +- test/testAsync.cpp | 33 ++++++++++++++++------------- test/testBlending.cpp | 27 ++++++++++++++---------- test/testBoundary.cpp | 27 ++++++++++++++---------- test/testCustomTransform.cpp | 43 +++++++++++++++++++++----------------- test/testDirectUpdate.cpp | 41 ++++++++++++++++++++---------------- test/testGradientTransform.cpp | 9 ++++++-- test/testLinearGradient.cpp | 27 ++++++++++++++---------- test/testMultiShapes.cpp | 27 ++++++++++++++---------- test/testPath.cpp | 29 ++++++++++++++----------- test/testPathCopy.cpp | 27 ++++++++++++++---------- test/testRadialGradient.cpp | 29 ++++++++++++++----------- test/testScene.cpp | 29 ++++++++++++++----------- test/testSceneTransform.cpp | 43 +++++++++++++++++++++----------------- test/testShape.cpp | 29 ++++++++++++++----------- test/testStroke.cpp | 29 ++++++++++++++----------- test/testStrokeLine.cpp | 27 ++++++++++++++---------- test/testSvg.cpp | 29 ++++++++++++++----------- test/testTransform.cpp | 43 +++++++++++++++++++++----------------- test/testUpdate.cpp | 43 +++++++++++++++++++++----------------- 33 files changed, 487 insertions(+), 292 deletions(-) create mode 100644 meson_options.txt diff --git a/meson.build b/meson.build index 0142de0..c23bcb1 100644 --- a/meson.build +++ b/meson.build @@ -6,12 +6,24 @@ project('thorvg', config_h = configuration_data() +if get_option('engines').contains('sw') == true + config_h.set10('THORVG_SW_RASTER_SUPPORT', true) +endif + +if get_option('engines').contains('gl') == true + config_h.set10('THORVG_GL_RASTER_SUPPORT', true) +endif + +if get_option('loaders').contains('svg') == true + config_h.set10('THORVG_SVG_LOADER_SUPPORT', true) +endif + configure_file( - output: 'config.h', - configuration: config_h + output: 'config.h', + configuration: config_h ) -headers = [include_directories('inc')] +headers = [include_directories('inc'), include_directories('.')] subdir('inc') subdir('src') diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..daf3923 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,11 @@ +option('engines', + type: 'array', + choices: ['sw', 'gl'], + value: ['sw', 'gl'], + description: 'Enable Rasterizer Engine in thorvg') + +option('loaders', + type: 'array', + choices: ['svg'], + value: ['svg'], + description: 'Enable Vector File Loader in thorvg') diff --git a/src/lib/gl_engine/meson.build b/src/lib/gl_engine/meson.build index 6856f1d..63c7ee8 100644 --- a/src/lib/gl_engine/meson.build +++ b/src/lib/gl_engine/meson.build @@ -18,8 +18,8 @@ egl_dep = meson.get_compiler('cpp').find_library('EGL') gles_dep = meson.get_compiler('cpp').find_library('GLESv2') external_dep = [egl_dep, gles_dep] -glengine_dep = declare_dependency( - dependencies : external_dep, - include_directories : include_directories('.'), - sources : source_file, -) +engine_dep += [declare_dependency( + dependencies : external_dep, + include_directories : include_directories('.'), + sources : source_file, +)] diff --git a/src/lib/meson.build b/src/lib/meson.build index 9a7dc61..46d6a99 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -1,5 +1,12 @@ -subdir('sw_engine') -subdir('gl_engine') +engine_dep = [] + +if get_option('engines').contains('sw') == true + subdir('sw_engine') +endif + +if get_option('engines').contains('gl') == true + subdir('gl_engine') +endif source_file = [ 'tvgCanvasImpl.h', @@ -25,8 +32,6 @@ source_file = [ 'tvgSwCanvas.cpp', ] -engine_dep = [swengine_dep, glengine_dep] - common_dep = declare_dependency( dependencies : engine_dep, include_directories : include_directories('.'), diff --git a/src/lib/sw_engine/meson.build b/src/lib/sw_engine/meson.build index 8b06258..66b1e0d 100644 --- a/src/lib/sw_engine/meson.build +++ b/src/lib/sw_engine/meson.build @@ -10,7 +10,7 @@ source_file = [ 'tvgSwStroke.cpp', ] -swengine_dep = declare_dependency( - include_directories : include_directories('.'), - sources : source_file -) +engine_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 79f7c18..ac91f49 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -17,6 +17,8 @@ #ifndef _TVG_COMMON_H_ #define _TVG_COMMON_H_ +#include "config.h" + #include #include #include diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index 1af7eac..4502498 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -18,9 +18,17 @@ #define _TVG_GLCANVAS_CPP_ #include "tvgCommon.h" -#include "tvgGlRenderer.h" #include "tvgCanvasImpl.h" +#ifdef THORVG_GL_RASTER_SUPPORT + #include "tvgGlRenderer.h" +#else + class GlRenderer : public RenderMethod + { + //Non Supported. Dummy Class */ + }; +#endif + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -35,11 +43,16 @@ struct GlCanvas::Impl /* External Class Implementation */ /************************************************************************/ +#ifdef THORVG_GL_RASTER_SUPPORT GlCanvas::GlCanvas() : Canvas(GlRenderer::inst()), pImpl(make_unique()) +#else +GlCanvas::GlCanvas() : Canvas(nullptr), pImpl(make_unique()) +#endif { } + GlCanvas::~GlCanvas() { } @@ -47,6 +60,7 @@ GlCanvas::~GlCanvas() Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept { +#ifdef THORVG_GL_RASTER_SUPPORT //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl.get()->renderer); if (!renderer) return Result::MemoryCorruption; @@ -54,15 +68,20 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t if (!renderer->target(buffer, stride, w, h)) return Result::Unknown; return Result::Success; +#endif + return Result::NonSupport; } unique_ptr GlCanvas::gen() noexcept { +#ifdef THORVG_GL_RASTER_SUPPORT auto canvas = unique_ptr(new GlCanvas); assert(canvas); return canvas; +#endif + return unique_ptr(nullptr); } diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 857698d..468178e 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -18,10 +18,17 @@ #define _TVG_INITIALIZER_CPP_ #include "tvgCommon.h" -#include "tvgSwRenderer.h" -#include "tvgGlRenderer.h" #include "tvgLoaderMgr.h" +#ifdef THORVG_SW_RASTER_SUPPORT + #include "tvgSwRenderer.h" +#endif + +#ifdef THORVG_GL_RASTER_SUPPORT + #include "tvgGlRenderer.h" +#endif + + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -32,14 +39,24 @@ Result Initializer::init(CanvasEngine engine) noexcept { + auto nonSupport = true; + if (engine == CanvasEngine::Sw) { - if (!SwRenderer::init()) return Result::InsufficientCondition; + #ifdef THORVG_SW_RASTER_SUPPORT + if (!SwRenderer::init()) return Result::InsufficientCondition; + nonSupport = false; + #endif } else if (engine == CanvasEngine::Gl) { - if (!GlRenderer::init()) return Result::InsufficientCondition; + #ifdef THORVG_GL_RASTER_SUPPORT + if (!GlRenderer::init()) return Result::InsufficientCondition; + nonSupport = false; + #endif } else { return Result::InvalidArguments; } + if (nonSupport) return Result::NonSupport; + if (!LoaderMgr::init()) return Result::Unknown; return Result::Success; @@ -48,16 +65,24 @@ Result Initializer::init(CanvasEngine engine) noexcept Result Initializer::term(CanvasEngine engine) noexcept { - //TODO: deinitialize modules + auto nonSupport = true; if (engine == CanvasEngine::Sw) { - if (!SwRenderer::term()) return Result::InsufficientCondition; + #ifdef THORVG_SW_RASTER_SUPPORT + if (!SwRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif } else if (engine == CanvasEngine::Gl) { - if (!GlRenderer::term()) return Result::InsufficientCondition; + #ifdef THORVG_GL_RASTER_SUPPORT + if (!GlRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif } else { return Result::InvalidArguments; } + if (nonSupport) return Result::NonSupport; + if (!LoaderMgr::term()) return Result::Unknown; return Result::Success; diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index a99838b..ae65732 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -18,8 +18,10 @@ #define _TVG_LOADER_MGR_CPP_ #include "tvgCommon.h" -#include "tvgSvgLoader.h" +#ifdef THORVG_SVG_LOADER_SUPPORT + #include "tvgSvgLoader.h" +#endif static int initCnt = 0; @@ -45,8 +47,11 @@ bool LoaderMgr::term() unique_ptr LoaderMgr::loader(const char* path) { - //TODO: +#ifdef THORVG_SVG_LOADER_SUPPORT return unique_ptr(new SvgLoader); +#endif + cout << "Non supported format: " << path << endl; + return unique_ptr(nullptr); } #endif //_TVG_LOADER_MGR_CPP_ \ No newline at end of file diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index b0a3c84..e20271b 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -51,15 +51,15 @@ class RenderMethod { public: virtual ~RenderMethod() {} - virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) = 0; - virtual bool dispose(const Shape& shape, void *data) = 0; - virtual bool preRender() = 0; - virtual bool render(const Shape& shape, void *data) = 0; - virtual bool postRender() = 0; - virtual bool clear() = 0; - virtual bool flush() = 0; - virtual uint32_t ref() = 0; - virtual uint32_t unref() = 0; + virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) { return nullptr; } + virtual bool dispose(const Shape& shape, void *data) { return false; } + virtual bool preRender() { return false; } + virtual bool render(const Shape& shape, void *data) { return false; } + virtual bool postRender() { return false; } + virtual bool clear() { return false; } + virtual bool flush() { return false; } + virtual uint32_t ref() { return 0; } + virtual uint32_t unref() { return 0; } }; struct RenderInitializer diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index a0bfdd0..4c61eaa 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -18,9 +18,16 @@ #define _TVG_SWCANVAS_CPP_ #include "tvgCommon.h" -#include "tvgSwRenderer.h" #include "tvgCanvasImpl.h" +#ifdef THORVG_SW_RASTER_SUPPORT + #include "tvgSwRenderer.h" +#else + class SwRenderer : public RenderMethod + { + //Non Supported. Dummy Class */ + }; +#endif /************************************************************************/ /* Internal Class Implementation */ @@ -36,7 +43,11 @@ struct SwCanvas::Impl /* External Class Implementation */ /************************************************************************/ +#ifdef THORVG_SW_RASTER_SUPPORT SwCanvas::SwCanvas() : Canvas(SwRenderer::inst()), pImpl(make_unique()) +#else +SwCanvas::SwCanvas() : Canvas(nullptr), pImpl(make_unique()) +#endif { } @@ -48,6 +59,7 @@ SwCanvas::~SwCanvas() Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept { +#ifdef THORVG_SW_RASTER_SUPPORT //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl.get()->renderer); if (!renderer) return Result::MemoryCorruption; @@ -55,15 +67,20 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t if (!renderer->target(buffer, stride, w, h)) return Result::InvalidArguments; return Result::Success; +#endif + return Result::NonSupport; } unique_ptr SwCanvas::gen() noexcept { +#ifdef THORVG_SW_RASTER_SUPPORT auto canvas = unique_ptr(new SwCanvas); assert(canvas); - return canvas; + return canvas; +#endif + return unique_ptr(nullptr); } #endif /* _TVG_SWCANVAS_CPP_ */ diff --git a/src/loaders/meson.build b/src/loaders/meson.build index 3abf0fd..aaf1324 100644 --- a/src/loaders/meson.build +++ b/src/loaders/meson.build @@ -1,6 +1,10 @@ -subdir('svg_loader') +subloader_dep = [] + +if get_option('loaders').contains('svg') == true + subdir('svg_loader') +endif loader_dep = declare_dependency( - dependencies : svgloader_dep, + dependencies: subloader_dep, include_directories : include_directories('.'), ) diff --git a/src/loaders/svg_loader/meson.build b/src/loaders/svg_loader/meson.build index de7adf7..d62762c 100644 --- a/src/loaders/svg_loader/meson.build +++ b/src/loaders/svg_loader/meson.build @@ -10,7 +10,7 @@ source_file = [ 'tvgSvgSceneBuilder.cpp', ] -svgloader_dep = declare_dependency( - include_directories : include_directories('.'), - sources : source_file -) +subloader_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/meson.build b/src/meson.build index faff2b3..23c4ad5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,7 +5,7 @@ subdir('loaders') subdir('examples') thread_dep = meson.get_compiler('cpp').find_library('pthread') -thorvg_lib_dep = [ common_dep, loader_dep, thread_dep] +thorvg_lib_dep = [common_dep, loader_dep, thread_dep] thorvg_lib = library( 'thorvg', diff --git a/test/testAsync.cpp b/test/testAsync.cpp index bb890ab..df81020 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -156,22 +156,27 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - evas_object_image_pixels_get_callback_set(view, drawSwView, nullptr); - ecore_animator_add(animSwCb, view); - } else { - auto view = createGlView(); - ecore_animator_add(animGlCb, view); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + evas_object_image_pixels_get_callback_set(view, drawSwView, nullptr); + ecore_animator_add(animSwCb, view); + } else { + auto view = createGlView(); + ecore_animator_add(animGlCb, view); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 6f5f6e1..6765cb6 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -136,19 +136,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index b23b82e..71dd6a0 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -125,19 +125,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 08075d2..5945490 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -179,28 +179,33 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 437ad1f..67d0240 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -142,28 +142,33 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index fd5a563..1c1b820 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -207,7 +207,7 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { elm_init(argc, argv); @@ -231,4 +231,9 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index 45f38d7..826287b 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -154,19 +154,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index ec46f2f..8860135 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -114,19 +114,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } diff --git a/test/testPath.cpp b/test/testPath.cpp index d74b89d..a6656a8 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -131,19 +131,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index ebf900c..dd00827 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -168,19 +168,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } \ No newline at end of file diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index 71cfaae..054bf12 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -154,19 +154,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testScene.cpp b/test/testScene.cpp index bee2b54..b796a5b 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -161,19 +161,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index d5d538d..aeaf11e 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -203,28 +203,33 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testShape.cpp b/test/testShape.cpp index e5e4c57..391b55f 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -104,19 +104,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testStroke.cpp b/test/testStroke.cpp index f4f7c8c..f7c1a88 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -151,19 +151,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 1856453..bc3f960 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -188,19 +188,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; } \ No newline at end of file diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 04b9ab0..edb987b 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -128,19 +128,24 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - if (tvgEngine == tvg::CanvasEngine::Sw) { - createSwView(); - } else { - createGlView(); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvg::CanvasEngine::Sw); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvg::CanvasEngine::Sw); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 65492b1..da7c87c 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -170,28 +170,33 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 6bfbddc..c350435 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -131,28 +131,33 @@ int main(int argc, char **argv) } //Initialize ThorVG Engine - tvg::Initializer::init(tvgEngine); + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); -} + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file -- 2.7.4 From f6444436557600ebecd36e1fd7a2acf1270bf74a Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 9 Jul 2020 13:23:41 +0900 Subject: [PATCH 06/16] SvgLoader: Support to linear, radial gradient Change-Id: Ida3f6ccca5f0d6ed1922b7ce99d2d2f3203f5ba9 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 55 ++++--- src/loaders/svg_loader/tvgSvgLoaderCommon.h | 26 ++-- src/loaders/svg_loader/tvgSvgSceneBuilder.cpp | 209 ++++++++++++++++++++++++-- test/svgs/lineargrad1.svg | 20 +++ test/svgs/radialgrad1.svg | 19 +++ 5 files changed, 279 insertions(+), 50 deletions(-) create mode 100644 test/svgs/lineargrad1.svg create mode 100644 test/svgs/radialgrad1.svg diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index f4ed3be..f8f7c4e 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -1365,11 +1365,18 @@ static SvgNode* _findChildById(SvgNode* node, const char* id) } -static vector _cloneGradStops(vector src) +static void _cloneGradStops(vector *dst, vector src) { - vector dst; - copy(src.begin(), src.end(), dst.begin()); - return dst; + for(vector::iterator itrStop = src.begin(); itrStop != src.end(); itrStop++) { + Fill::ColorStop *stop = (Fill::ColorStop *)malloc(sizeof(Fill::ColorStop)); + stop->r = (*itrStop)->r; + stop->g = (*itrStop)->g; + stop->b = (*itrStop)->b; + stop->a = (*itrStop)->a; + stop->offset = (*itrStop)->offset; + dst->push_back(stop); + } + } @@ -1381,8 +1388,8 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from) grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient)); grad->type = from->type; - grad->id = _copyId(from->id->c_str()); - grad->ref = _copyId(from->ref->c_str()); + grad->id = from->id ? _copyId(from->id->c_str()) : nullptr; + grad->ref = from->ref ? _copyId(from->ref->c_str()) : nullptr; grad->spread = from->spread; grad->usePercentage = from->usePercentage; grad->userSpace = from->userSpace; @@ -1390,7 +1397,6 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from) grad->transform = (Matrix*)calloc(1, sizeof(Matrix)); memcpy(grad->transform, from->transform, sizeof(Matrix)); } - grad->stops = _cloneGradStops(from->stops); if (grad->type == SvgGradientType::Linear) { grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient)); memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient)); @@ -1399,6 +1405,7 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from) memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient)); } + _cloneGradStops(&(grad->stops), from->stops); return grad; } @@ -1562,14 +1569,14 @@ FIND_FACTORY(Group, groupTags); FIND_FACTORY(Graphics, graphicsTags); -SvgGradientSpread _parseSpreadValue(const char* value) +FillSpread _parseSpreadValue(const char* value) { - SvgGradientSpread spread = SvgGradientSpread::Pad; + FillSpread spread = FillSpread::Pad; if (!strcmp(value, "reflect")) { - spread = SvgGradientSpread::Reflect; + spread = FillSpread::Reflect; } else if (!strcmp(value, "repeat")) { - spread = SvgGradientSpread::Repeat; + spread = FillSpread::Repeat; } return spread; @@ -1730,7 +1737,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char static bool _attrParseStops(void* data, const char* key, const char* value) { SvgLoaderData* loader = (SvgLoaderData*)data; - SvgGradientStop* stop = loader->svgParse->gradStop; + Fill::ColorStop* stop = loader->svgParse->gradStop; if (!strcmp(key, "offset")) { stop->offset = _toOffset(value); @@ -2008,7 +2015,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, } loader->latestGradient = gradient; } else if (!strcmp(tagName, "stop")) { - SvgGradientStop* stop = (SvgGradientStop*)calloc(1, sizeof(SvgGradientStop)); + Fill::ColorStop* stop = (Fill::ColorStop*)calloc(1, sizeof(Fill::ColorStop)); loader->svgParse->gradStop = stop; /* default value for opacity */ stop->a = 255; @@ -2067,7 +2074,7 @@ static void _styleInherit(SvgStyleProperty* child, SvgStyleProperty* parent) child->fill.paint.b = parent->fill.paint.b; child->fill.paint.none = parent->fill.paint.none; child->fill.paint.curColor = parent->fill.paint.curColor; - child->fill.paint.url = parent->fill.paint.url ? _copyId(parent->fill.paint.url->c_str()) : nullptr; + if (parent->fill.paint.url) child->fill.paint.url = _copyId(parent->fill.paint.url->c_str()); } if (!((int)child->fill.flags & (int)SvgFillFlags::Opacity)) { child->fill.opacity = parent->fill.opacity; @@ -2109,12 +2116,12 @@ static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle) } -static SvgStyleGradient* _gradientDup(vector gradList, const char* id) +static SvgStyleGradient* _gradientDup(vector gradList, string* id) { SvgStyleGradient* result = nullptr; for (vector::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) { - if ((*itrGrad)->id->compare(string(id))) { + if (!((*itrGrad)->id->compare(*id))) { result = _cloneGradient(*itrGrad); break; } @@ -2122,9 +2129,9 @@ static SvgStyleGradient* _gradientDup(vector gradList, const if (result && result->ref) { for (vector::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) { - if ((*itrGrad)->id->compare(*result->ref)) { + if (!((*itrGrad)->id->compare(*result->ref))) { if (!result->stops.empty()) { - result->stops = _cloneGradStops((*itrGrad)->stops); + _cloneGradStops(&(result->stops), (*itrGrad)->stops); } //TODO: Properly inherit other property break; @@ -2138,15 +2145,15 @@ static SvgStyleGradient* _gradientDup(vector gradList, const static void _updateGradient(SvgNode* node, vector gradList) { - if (node->child.empty()) { + if (!node->child.empty()) { for (vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { _updateGradient(*itrChild, gradList); } } else { if (node->style->fill.paint.url) { - node->style->fill.paint.gradient = _gradientDup(gradList, node->style->fill.paint.url->c_str()); + node->style->fill.paint.gradient = _gradientDup(gradList, node->style->fill.paint.url); } else if (node->style->stroke.paint.url) { - node->style->stroke.paint.gradient = _gradientDup(gradList, node->style->stroke.paint.url->c_str()); + //node->style->stroke.paint.gradient = _gradientDup(gradList, node->style->stroke.paint.url); } } } @@ -2161,7 +2168,7 @@ static void _freeGradientStyle(SvgStyleGradient* grad) free(grad->linear); if (grad->transform) free(grad->transform); - for(vector::iterator itrStop = grad->stops.begin(); itrStop != grad->stops.end(); itrStop++) { + for(vector::iterator itrStop = grad->stops.begin(); itrStop != grad->stops.end(); itrStop++) { free(*itrStop); } free(grad); @@ -2284,7 +2291,9 @@ bool SvgLoader::read() else { if (!loader->loaderData.gradients.empty()) { vector gradientList; - std::copy(loader->loaderData.gradients.begin(), loader->loaderData.gradients.end(), gradientList.begin()); + for(vector::iterator itrGrad = loader->loaderData.gradients.begin(); itrGrad != loader->loaderData.gradients.end(); itrGrad++) { + gradientList.push_back(*itrGrad); + } _updateGradient(loader->loaderData.doc, gradientList); gradientList.clear(); } diff --git a/src/loaders/svg_loader/tvgSvgLoaderCommon.h b/src/loaders/svg_loader/tvgSvgLoaderCommon.h index b5ae7bb..2f1af74 100644 --- a/src/loaders/svg_loader/tvgSvgLoaderCommon.h +++ b/src/loaders/svg_loader/tvgSvgLoaderCommon.h @@ -97,14 +97,6 @@ enum class SvgStyleType CompOp }; -enum class SvgGradientSpread -{ - Pad = 0, - Reflect, - Repeat, - Last -}; - enum class SvgFillRule { Winding = 0, @@ -221,7 +213,7 @@ struct SvgGradientStop struct SvgPaint { SvgStyleGradient* gradient; - string* url; + string *url; uint8_t r; uint8_t g; uint8_t b; @@ -238,13 +230,13 @@ struct SvgDash struct _SvgStyleGradient { SvgGradientType type; - string* id; - string* ref; - SvgGradientSpread spread; - vector stops; + string *id; + string *ref; + FillSpread spread; SvgRadialGradient* radial; SvgLinearGradient* linear; Matrix* transform; + vector stops; bool userSpace; bool usePercentage; }; @@ -286,8 +278,8 @@ struct _SvgNode SvgNodeType type; SvgNode* parent; vector child; - string* id; - SvgStyleProperty* style; + string *id; + SvgStyleProperty *style; Matrix* transform; union { SvgGNode g; @@ -309,7 +301,7 @@ struct SvgParser { SvgNode* node; SvgStyleGradient* styleGrad; - SvgGradientStop* gradStop; + Fill::ColorStop* gradStop; struct { int x, y; @@ -334,4 +326,4 @@ struct SvgLoaderData bool result = false; }; -#endif \ No newline at end of file +#endif diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp index 69e4a0a..d7fcb82 100644 --- a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp @@ -40,7 +40,188 @@ static void _getTransformationData(Matrix* m, float* tx, float* ty, float* s, fl } -unique_ptr _applyProperty(SvgNode* node, unique_ptr vg) +unique_ptr _applyLinearGradientProperty(SvgStyleGradient* g, Shape* vg, float rx, float ry, float rw, float rh) +{ + Fill::ColorStop* stops; + int stopCount = 0; + float fillOpacity = 255.0f; + float gx, gy, gw, gh; + + auto fillGrad = LinearGradient::gen(); + + if (g->usePercentage) { + g->linear->x1 = g->linear->x1 * rw + rx; + g->linear->y1 = g->linear->y1 * rh + ry; + g->linear->x2 = g->linear->x2 * rw + rx; + g->linear->y2 = g->linear->y2 * rh + ry; + } + + //In case of objectBoundingBox it need proper scaling + if (!g->userSpace) { + float scaleX = 1.0, scaleReversedX = 1.0; + float scaleY = 1.0, scaleReversedY = 1.0; + + //Check the smallest size, find the scale value + if (rh > rw) { + scaleY = ((float)rw) / rh; + scaleReversedY = ((float)rh) / rw; + } else { + scaleX = ((float)rh) / rw; + scaleReversedX = ((float)rw) / rh; + } + + vg->bounds(&gx, &gy, &gw, &gh); + + float cy = ((float)gh) * 0.5 + gy; + float cy_scaled = (((float)gh) * 0.5) * scaleReversedY; + float cx = ((float)gw) * 0.5 + gx; + float cx_scaled = (((float)gw) * 0.5) * scaleReversedX; + + //= T(gx, gy) x S(scaleX, scaleY) x T(cx_scaled - cx, cy_scaled - cy) x (radial->x, radial->y) + g->linear->x1 = g->linear->x1 * scaleX + scaleX * (cx_scaled - cx) + gx; + g->linear->y1 = g->linear->y1 * scaleY + scaleY * (cy_scaled - cy) + gy; + g->linear->x2 = g->linear->x2 * scaleX + scaleX * (cx_scaled - cx) + gx; + g->linear->y2 = g->linear->y2 * scaleY + scaleY * (cy_scaled - cy) + gy; + } + + if (g->transform) { + float cy = ((float) rh) * 0.5 + ry; + float cx = ((float) rw) * 0.5 + rx; + + //Calc start point + //= T(x - cx, y - cy) x g->transform x T(cx, cy) + g->linear->x1 = cx * (g->transform->e11 + g->transform->e31 * (g->linear->x1 - cx)) + + cx * (g->transform->e12 + g->transform->e32 * (g->linear->x1 - cx)) + + cx * (g->transform->e13 + g->transform->e33 * (g->linear->x1 - cx)); + + g->linear->y1 = cy * (g->transform->e21 + g->transform->e31 * (g->linear->y1 - cy)) + + cy * (g->transform->e22 + g->transform->e32 * (g->linear->y1 - cy)) + + cy * (g->transform->e23 + g->transform->e33 * (g->linear->y1 - cy)); + + //Calc end point + g->linear->x2 = cx * (g->transform->e11 + g->transform->e31 * (g->linear->x2 - cx)) + + cx * (g->transform->e12 + g->transform->e32 * (g->linear->x2 - cx)) + + cx * (g->transform->e13 + g->transform->e33 * (g->linear->x2 - cx)); + + g->linear->y2 = cy * (g->transform->e21 + g->transform->e31 * (g->linear->y2 - cy)) + + cy * (g->transform->e22 + g->transform->e32 * (g->linear->y2 - cy)) + + cy * (g->transform->e23 + g->transform->e33 * (g->linear->y2 - cy)); + } + + fillGrad->linear(g->linear->x1, g->linear->y1, g->linear->x2, g->linear->y2); + fillGrad->spread(g->spread); + + //Update the stops + stopCount = g->stops.size(); + if (stopCount > 0) { + float opacity; + float fopacity = fillOpacity / 255.0f; //fill opacity if any exists. + int i = 0; + stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); + for (vector::iterator itrStop = g->stops.begin(); itrStop != g->stops.end(); itrStop++) { + //Use premultiplied color + opacity = ((float)(*itrStop)->a / 255) * fopacity; + stops[i].r = ((*itrStop)->r * opacity); + stops[i].g = ((*itrStop)->g * opacity); + stops[i].b = ((*itrStop)->b * opacity); + stops[i].a = ((*itrStop)->a * fopacity); + stops[i].offset = (*itrStop)->offset; + i++; + } + fillGrad->colorStops(stops, stopCount); + free(stops); + } + return move(fillGrad); +} + + +unique_ptr _applyRadialGradientProperty(SvgStyleGradient* g, Shape* vg, float rx, float ry, float rw, float rh) +{ + Fill::ColorStop *stops; + int stopCount = 0; + float gx, gy, gw, gh; + int radius; + float fillOpacity = 255.0f; + + auto fillGrad = RadialGradient::gen(); + + radius = sqrt(pow(rw, 2) + pow(rh, 2)) / sqrt(2.0); + if (!g->userSpace) { + //That is according to Units in here + //https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html + int min = (rh > rw) ? rw : rh; + radius = sqrt(pow(min, 2) + pow(min, 2)) / sqrt(2.0); + } + + if (g->usePercentage) { + g->radial->cx = g->radial->cx * rw + rx; + g->radial->cy = g->radial->cy * rh + ry; + g->radial->r = g->radial->r * radius; + g->radial->fx = g->radial->fx * rw + rx; + g->radial->fy = g->radial->fy * rh + ry; + } + + //In case of objectBoundingBox it need proper scaling + if (!g->userSpace) { + float scaleX = 1.0, scaleReversedX = 1.0; + float scaleY = 1.0, scaleReversedY = 1.0; + + //Check the smallest size, find the scale value + if (rh > rw) { + scaleY = ((float)rw) / rh; + scaleReversedY = ((float)rh) / rw; + } else { + scaleX = ((float)rh) / rw; + scaleReversedX = ((float)rw) / rh; + } + + vg->bounds(&gx, &gy, &gw, &gh); + + float cy = ((float)gh) * 0.5 + gy; + float cy_scaled = (((float)gh) * 0.5) * scaleReversedY; + float cx = ((float)gw) * 0.5 + gx; + float cx_scaled = (((float)gw) * 0.5) * scaleReversedX; + + //= T(gx, gy) x S(scaleX, scaleY) x T(cx_scaled - cx, cy_scaled - cy) x (radial->x, radial->y) + g->radial->cx = g->radial->cx * scaleX + scaleX * (cx_scaled - cx) + gx; + g->radial->cy = g->radial->cy * scaleY + scaleY * (cy_scaled - cy) + gy; + } + + //TODO: Radial gradient transformation is not yet supported. + //if (g->transform) {} + + //TODO: Tvg is not support to focal + //if (g->radial->fx != 0 && g->radial->fy != 0) { + // fillGrad->radial(g->radial->fx, g->radial->fy, g->radial->r); + //} + fillGrad->radial(g->radial->cx, g->radial->cy, g->radial->r); + fillGrad->spread(g->spread); + + //Update the stops + stopCount = g->stops.size(); + if (stopCount > 0) { + float opacity; + float fopacity = fillOpacity / 255.0f; //fill opacity if any exists. + int i = 0; + stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); + for (vector::iterator itrStop = g->stops.begin(); itrStop != g->stops.end(); itrStop++) { + //Use premultiplied color + opacity = ((float)(*itrStop)->a / 255) * fopacity; + stops[i].r = ((*itrStop)->r * opacity); + stops[i].g = ((*itrStop)->g * opacity); + stops[i].b = ((*itrStop)->b * opacity); + stops[i].a = ((*itrStop)->a * fopacity); + stops[i].offset = (*itrStop)->offset; + i++; + } + fillGrad->colorStops(stops, stopCount); + free(stops); + } + return move(fillGrad); +} + + +unique_ptr _applyProperty(SvgNode* node, unique_ptr vg, float vx, float vy, float vw, float vh) { SvgStyleProperty* style = node->style; @@ -59,7 +240,15 @@ unique_ptr _applyProperty(SvgNode* node, unique_ptr vg) if (style->fill.paint.none) { //Do nothing } else if (style->fill.paint.gradient) { - //TODO: Support gradient style + if (!style->fill.paint.gradient->userSpace) vg->bounds(&vx, &vy, &vw, &vh); + + if (style->fill.paint.gradient->type == SvgGradientType::Linear) { + auto linear = _applyLinearGradientProperty(style->fill.paint.gradient, vg.get(), vx, vy, vw, vh); + vg->fill(move(linear)); + } else if (style->fill.paint.gradient->type == SvgGradientType::Radial) { + auto radial = _applyRadialGradientProperty(style->fill.paint.gradient, vg.get(), vx, vy, vw, vh); + vg->fill(move(radial)); + } } else if (style->fill.paint.curColor) { //Apply the current style color float fa = ((float)style->fill.opacity / 255.0); @@ -113,9 +302,9 @@ unique_ptr _applyProperty(SvgNode* node, unique_ptr vg) } -unique_ptr _shapeBuildHelper(SvgNode* node) +unique_ptr _shapeBuildHelper(SvgNode* node, float vx, float vy, float vw, float vh) { - auto shape = tvg::Shape::gen(); + auto shape = Shape::gen(); switch (node->type) { case SvgNodeType::Path: { if (node->node.path.path) { @@ -162,15 +351,15 @@ unique_ptr _shapeBuildHelper(SvgNode* node) break; } } - shape = move(_applyProperty(node, move(shape))); + shape = move(_applyProperty(node, move(shape), vx, vy, vw, vh)); return shape; } -unique_ptr _sceneBuildHelper(SvgNode* node) +unique_ptr _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, float vh) { if (node->type == SvgNodeType::Doc || node->type == SvgNodeType::G) { - auto scene = tvg::Scene::gen(); + auto scene = Scene::gen(); if (node->transform) { float tx = 0, ty = 0, s = 0, z = 0; _getTransformationData(node->transform, &tx, &ty, &s, &z); @@ -180,8 +369,8 @@ unique_ptr _sceneBuildHelper(SvgNode* node) } for (vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { SvgNode* child = *itrChild; - if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild)); - else scene->push(_shapeBuildHelper(*itrChild)); + if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild, vx, vy, vw, vh)); + else scene->push(_shapeBuildHelper(*itrChild, vx, vy, vw, vh)); } return move(scene); } @@ -209,7 +398,7 @@ unique_ptr SvgSceneBuilder::build(SvgNode* node) viewBox.h = node->node.doc.vh; preserveAspect = node->node.doc.preserveAspect; staticViewBox = true; - return _sceneBuildHelper(node); + return _sceneBuildHelper(node, viewBox.x, viewBox.y, viewBox.w, viewBox.h); } diff --git a/test/svgs/lineargrad1.svg b/test/svgs/lineargrad1.svg new file mode 100644 index 0000000..343d161 --- /dev/null +++ b/test/svgs/lineargrad1.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/test/svgs/radialgrad1.svg b/test/svgs/radialgrad1.svg new file mode 100644 index 0000000..5cb6da8 --- /dev/null +++ b/test/svgs/radialgrad1.svg @@ -0,0 +1,19 @@ + + + + + + + + + -- 2.7.4 From 84df3439dee7f37d7336e5ad52d17e91eeb4793b Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 9 Jul 2020 13:37:12 +0900 Subject: [PATCH 07/16] SvgLoader: Inherit parent opacity Change-Id: If52c6581845e9918dc13c4627080ba84d270a07b --- src/loaders/svg_loader/tvgSvgSceneBuilder.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp index d7fcb82..4daf7d8 100644 --- a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp @@ -356,7 +356,7 @@ unique_ptr _shapeBuildHelper(SvgNode* node, float vx, float vy, float vw, } -unique_ptr _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, float vh) +unique_ptr _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, float vh, int parentOpacity) { if (node->type == SvgNodeType::Doc || node->type == SvgNodeType::G) { auto scene = Scene::gen(); @@ -367,9 +367,11 @@ unique_ptr _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw, if (!(fmod(fabsf(z), 360.0) <= FLT_EPSILON)) scene->rotate(fmod(z, 360.0)); if (!(fabsf(tx) <= FLT_EPSILON) && !(fabsf(ty) <= FLT_EPSILON)) scene->translate(tx, ty); } + node->style->opacity = (node->style->opacity * parentOpacity) / 255; for (vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { SvgNode* child = *itrChild; - if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild, vx, vy, vw, vh)); + child->style->opacity = (child->style->opacity * node->style->opacity) / 255; + if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(*itrChild, vx, vy, vw, vh, node->style->opacity)); else scene->push(_shapeBuildHelper(*itrChild, vx, vy, vw, vh)); } return move(scene); @@ -398,7 +400,7 @@ unique_ptr SvgSceneBuilder::build(SvgNode* node) viewBox.h = node->node.doc.vh; preserveAspect = node->node.doc.preserveAspect; staticViewBox = true; - return _sceneBuildHelper(node, viewBox.x, viewBox.y, viewBox.w, viewBox.h); + return _sceneBuildHelper(node, viewBox.x, viewBox.y, viewBox.w, viewBox.h, 255); } -- 2.7.4 From 581451ea8d593edecfd7d62a705d46110f11ac06 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 9 Jul 2020 15:40:21 +0900 Subject: [PATCH 08/16] SvgLoader: Fix typo (SCubic draw) Change-Id: Id54cf6a7ca66cdbc96cfb93143aacccab95de822 --- src/loaders/svg_loader/tvgSvgPath.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgPath.cpp b/src/loaders/svg_loader/tvgSvgPath.cpp index ba01ae7..bd43027 100644 --- a/src/loaders/svg_loader/tvgSvgPath.cpp +++ b/src/loaders/svg_loader/tvgSvgPath.cpp @@ -328,9 +328,9 @@ static void _processCommand(vector* cmds, vector* pts, char case 's': case 'S': { Point p[3], ctrl; - if ((cmds->size() > 1) && (cmds->at(cmds->size() - 2) == PathCommand::CubicTo)) { + if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo)) { ctrl.x = 2 * cur->x - curCtl->x; - ctrl.y = 2 * cur->x - curCtl->y; + ctrl.y = 2 * cur->y - curCtl->y; } else { ctrl = *cur; } -- 2.7.4 From e86d2ab686587280debc00080280ba87d82c1147 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 9 Jul 2020 16:36:30 +0900 Subject: [PATCH 09/16] SvgLoader/Parser: Fix typo Change-Id: Iced0f2196c52f7cc729d6f648f5df6affbda3357 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index f4ed3be..1ac2fd4 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -623,13 +623,13 @@ static Matrix* _parseTransformationMatrix(const char* value) tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); } else if (ptCount == 3) { - tmp = { 1, 0, points[0], 0, 1, points[1], 0, 0, 1 }; + 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[0], 0, 1, points[1], 0, 0, 1 }; + tmp = { 1, 0, -points[1], 0, 1, -points[2], 0, 0, 1 }; _matrixCompose(matrix, &tmp, matrix); } else { goto error; -- 2.7.4 From 9299c41a21379e7e7f447de6e67a84efd19d0d6e Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 10 Jul 2020 09:31:12 +0900 Subject: [PATCH 10/16] svg_loader: code refactoring. simpler code is better for readibility. Change-Id: I4bc18bb184aea6fea0179bb38b445da5e0acba43 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 7c0ff9d..130a60c 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -1367,16 +1367,11 @@ static SvgNode* _findChildById(SvgNode* node, const char* id) static void _cloneGradStops(vector *dst, vector src) { - for(vector::iterator itrStop = src.begin(); itrStop != src.end(); itrStop++) { - Fill::ColorStop *stop = (Fill::ColorStop *)malloc(sizeof(Fill::ColorStop)); - stop->r = (*itrStop)->r; - stop->g = (*itrStop)->g; - stop->b = (*itrStop)->b; - stop->a = (*itrStop)->a; - stop->offset = (*itrStop)->offset; + for (auto colorStop : src) { + auto stop = static_cast(malloc(sizeof(Fill::ColorStop))); + *stop = *colorStop; dst->push_back(stop); } - } @@ -1571,7 +1566,7 @@ FIND_FACTORY(Graphics, graphicsTags); FillSpread _parseSpreadValue(const char* value) { - FillSpread spread = FillSpread::Pad; + auto spread = FillSpread::Pad; if (!strcmp(value, "reflect")) { spread = FillSpread::Reflect; @@ -1737,7 +1732,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char static bool _attrParseStops(void* data, const char* key, const char* value) { SvgLoaderData* loader = (SvgLoaderData*)data; - Fill::ColorStop* stop = loader->svgParse->gradStop; + auto stop = loader->svgParse->gradStop; if (!strcmp(key, "offset")) { stop->offset = _toOffset(value); @@ -2015,7 +2010,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, } loader->latestGradient = gradient; } else if (!strcmp(tagName, "stop")) { - Fill::ColorStop* stop = (Fill::ColorStop*)calloc(1, sizeof(Fill::ColorStop)); + auto stop = static_cast(calloc(1, sizeof(Fill::ColorStop))); loader->svgParse->gradStop = stop; /* default value for opacity */ stop->a = 255; @@ -2168,9 +2163,8 @@ static void _freeGradientStyle(SvgStyleGradient* grad) free(grad->linear); if (grad->transform) free(grad->transform); - for(vector::iterator itrStop = grad->stops.begin(); itrStop != grad->stops.end(); itrStop++) { - free(*itrStop); - } + for (auto colorStop : grad->stops) free(colorStop); + free(grad); } @@ -2291,8 +2285,8 @@ bool SvgLoader::read() else { if (!loader->loaderData.gradients.empty()) { vector gradientList; - for(vector::iterator itrGrad = loader->loaderData.gradients.begin(); itrGrad != loader->loaderData.gradients.end(); itrGrad++) { - gradientList.push_back(*itrGrad); + for (auto gradient : loader->loaderData.gradients) { + gradientList.push_back(gradient); } _updateGradient(loader->loaderData.doc, gradientList); gradientList.clear(); -- 2.7.4 From 9e1ba8d2c0bd295513a18361e4c081d9802eba28 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 8 Jul 2020 16:05:58 +0900 Subject: [PATCH 11/16] sw_engine: introduce avx simd instruction avx is the cutting edge method for intel & amd cpus simd instruction. We are going to support this feature for the desktop environment (instead of sse) You can turn on this with configuration something like this: $meson . build -Dvectors=avx Current patch supports only for raster solid color Change-Id: I068ba30a1f63d480415e2762f8021fc8d6d28a39 --- meson.build | 4 ++++ meson_options.txt | 8 +++++++- src/lib/meson.build | 2 ++ src/lib/sw_engine/tvgSwCommon.h | 37 ++++++++++++++++++++++++++++++------- src/lib/sw_engine/tvgSwFill.cpp | 6 ++++-- src/lib/sw_engine/tvgSwRaster.cpp | 29 +++++++++++++---------------- src/loaders/meson.build | 1 + src/meson.build | 9 +++++++++ test/testPath.cpp | 2 +- 9 files changed, 71 insertions(+), 27 deletions(-) diff --git a/meson.build b/meson.build index c23bcb1..d1803a3 100644 --- a/meson.build +++ b/meson.build @@ -18,6 +18,10 @@ if get_option('loaders').contains('svg') == true config_h.set10('THORVG_SVG_LOADER_SUPPORT', true) endif +if get_option('vectors').contains('avx') == true + config_h.set10('THORVG_AVX_VECTOR_SUPPORT', true) +endif + configure_file( output: 'config.h', configuration: config_h diff --git a/meson_options.txt b/meson_options.txt index daf3923..5a440fa 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,6 +6,12 @@ option('engines', option('loaders', type: 'array', - choices: ['svg'], + choices: ['', 'svg'], value: ['svg'], description: 'Enable Vector File Loader in thorvg') + +option('vectors', + type: 'array', + choices: ['', 'avx'], + value: [''], + description: 'Enable CPU Vectorization(SIMD) in thorvg') diff --git a/src/lib/meson.build b/src/lib/meson.build index 46d6a99..ad02261 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -2,10 +2,12 @@ engine_dep = [] if get_option('engines').contains('sw') == true subdir('sw_engine') + message('Enable SW Raster Engine') endif if get_option('engines').contains('gl') == true subdir('gl_engine') + message('Enable GL Raster Engine') endif source_file = [ diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 8d90342..5e47483 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -19,6 +19,10 @@ #include "tvgCommon.h" +#ifdef THORVG_AVX_VECTOR_SUPPORT + #include +#endif + #if 0 #include static double timeStamp() @@ -242,12 +246,6 @@ static inline uint32_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t } -static inline void COLOR_SET(uint32_t *dst, uint32_t val, uint32_t len) -{ - while (len--) *dst++ = val; -} - - int64_t mathMultiply(int64_t a, int64_t b); int64_t mathDivide(int64_t a, int64_t b); int64_t mathMulDiv(int64_t a, int64_t b, int64_t c); @@ -283,7 +281,7 @@ void strokeFree(SwStroke* stroke); bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable); void fillReset(SwFill* fill); void fillFree(SwFill* fill); -void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len); +void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len); void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len); SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias); @@ -294,4 +292,29 @@ bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, ui bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterClear(Surface& surface); +inline void rasterARGB32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) +{ +#ifdef THORVG_AVX_VECTOR_SUPPORT + int32_t align = (8 - (offset % 8)) % 8; + //Vectorization + auto avxDst = (__m256i*)(dst + offset + align); + int32_t i = (len - align); + for (;i > 7; i -= 8, ++avxDst) { + *avxDst = _mm256_set1_epi32(val); + } + //Alignment + if (align > 0) { + if (align > len) align -= (align - len); + auto tmp = dst + offset; + for (; align > 0; --align, ++tmp) *tmp = val; + } + //Pack Leftovers + dst += offset + (len - i); + while (i-- > 0) *(dst++) = val; +#else + dst += offset; + while (len--) *dst++ = val; +#endif +} + #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 5992bca..1f72ee9 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -208,7 +208,7 @@ void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, } -void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len) +void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len) { if (fill->linear.len < FLT_EPSILON) return; @@ -220,10 +220,12 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, if (fabsf(inc) < FLT_EPSILON) { auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); - COLOR_SET(dst, color, len); + rasterARGB32(dst, color, offset, len); return; } + dst += offset; + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); auto vMin = -vMax; auto v = t + (inc * len); diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 5a14822..5819bb8 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -19,7 +19,6 @@ #include "tvgSwCommon.h" - /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -55,13 +54,12 @@ static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint3 static bool _rasterSolidRect(Surface& surface, const SwBBox& region, uint32_t color) { - auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; - auto h = static_cast(region.max.y - region.min.y); + auto buffer = surface.buffer + (region.min.y * surface.stride); auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface.stride]; - COLOR_SET(dst, color, w); + rasterARGB32(buffer + y * surface.stride, color, region.min.x, w); } return true; } @@ -95,10 +93,10 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) auto span = rle->spans; for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; if (span->coverage == 255) { - COLOR_SET(dst, color, span->len); + rasterARGB32(surface.buffer + span->y * surface.stride, color, span->x, span->len); } else { + auto dst = &surface.buffer[span->y * surface.stride + span->x]; auto src = COLOR_ALPHA_BLEND(color, span->coverage); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { @@ -127,7 +125,7 @@ static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, co for (uint32_t y = 0; y < h; ++y) { auto dst = &buffer[y * surface.stride]; - fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, w); + fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w); for (uint32_t x = 0; x < w; ++x) { dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x])); } @@ -135,8 +133,7 @@ static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, co //Opaque Gradient } else { for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface.stride]; - fillFetchLinear(fill, dst, region.min.y + y, region.min.x, w); + fillFetchLinear(fill, buffer + y * surface.stride, region.min.y + y, region.min.x, 0, w); } } return true; @@ -188,7 +185,7 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF if (fill->translucent) { for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface.buffer[span->y * surface.stride + span->x]; - fillFetchLinear(fill, buf, span->y, span->x, span->len); + fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); if (span->coverage == 255) { for (uint32_t i = 0; i < span->len; ++i) { dst[i] = buf[i] + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(buf[i])); @@ -204,11 +201,11 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF //Opaque Gradient } else { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; if (span->coverage == 255) { - fillFetchLinear(fill, dst, span->y, span->x, span->len); + fillFetchLinear(fill, surface.buffer + span->y * surface.stride, span->y, span->x, span->x, span->len); } else { - fillFetchLinear(fill, buf, span->y, span->x, span->len); + auto dst = &surface.buffer[span->y * surface.stride + span->x]; + fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { dst[i] = COLOR_ALPHA_BLEND(buf[i], span->coverage) + COLOR_ALPHA_BLEND(dst[i], ialpha); @@ -313,10 +310,10 @@ bool rasterClear(Surface& surface) if (!surface.buffer || surface.stride <= 0 || surface.w <= 0 || surface.h <= 0) return false; if (surface.w == surface.stride) { - COLOR_SET(surface.buffer, 0xff000000, surface.w * surface.h); + rasterARGB32(surface.buffer, 0x00000000, 0, surface.w * surface.h); } else { for (uint32_t i = 0; i < surface.h; i++) { - COLOR_SET(surface.buffer + surface.stride * i, 0xff000000, surface.w); + rasterARGB32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w); } } return true; diff --git a/src/loaders/meson.build b/src/loaders/meson.build index aaf1324..873cfa7 100644 --- a/src/loaders/meson.build +++ b/src/loaders/meson.build @@ -2,6 +2,7 @@ subloader_dep = [] if get_option('loaders').contains('svg') == true subdir('svg_loader') + message('Enable SVG Loader') endif loader_dep = declare_dependency( diff --git a/src/meson.build b/src/meson.build index 23c4ad5..6873870 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,14 @@ compiler_flags = ['-DTVG_BUILD'] +cc = meson.get_compiler('cpp') +if (cc.get_id() != 'msvc') + if get_option('vectors').contains('avx') + compiler_flags += ['-mavx'] + message('Enable Advanced Vector Extension') + endif +endif + + subdir('lib') subdir('loaders') subdir('examples') diff --git a/test/testPath.cpp b/test/testPath.cpp index a6656a8..bcd5ab7 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -151,4 +151,4 @@ int main(int argc, char **argv) cout << "engine is not supported" << endl; } return 0; -} \ No newline at end of file +} -- 2.7.4 From 9876d685cfbaefc1ba1e3b2f565f655b62326d93 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 13 Jul 2020 20:19:23 +0900 Subject: [PATCH 12/16] capi: support c interfaces this capi is under the beta, we quickly provide this working prototype for collaboration. Change-Id: Ie246abc306feb9a1305d1b593c4f3ef7f40ab5a9 --- .gitignore | 1 + inc/meson.build | 10 +- inc/thorvg_capi.h | 111 ++++++++++++++++++++++ meson.build | 4 + meson_options.txt | 6 ++ src/bindings/capi/meson.build | 8 ++ src/bindings/capi/tvgCapi.cpp | 214 ++++++++++++++++++++++++++++++++++++++++++ src/bindings/meson.build | 11 +++ src/meson.build | 3 +- test/makefile | 1 + test/testCapi.c | 73 ++++++++++++++ 11 files changed, 438 insertions(+), 4 deletions(-) create mode 100644 inc/thorvg_capi.h create mode 100644 src/bindings/capi/meson.build create mode 100644 src/bindings/capi/tvgCapi.cpp create mode 100644 src/bindings/meson.build create mode 100644 test/testCapi.c diff --git a/.gitignore b/.gitignore index 9a64520..b796b5e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ testRadialGradient testGradientTransform testSvg testAsync +testCapi diff --git a/inc/meson.build b/inc/meson.build index c598ee5..90e3fc4 100644 --- a/inc/meson.build +++ b/inc/meson.build @@ -1,3 +1,7 @@ -install_headers([ - 'thorvg.h', - ]) +header_files = ['thorvg.h'] + +if get_option('bindings').contains('capi') == true + header_files += ['thorvg_capi.h'] +endif + +install_headers(header_files) diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h new file mode 100644 index 0000000..d2f7f85 --- /dev/null +++ b/inc/thorvg_capi.h @@ -0,0 +1,111 @@ +#ifndef __THORVG_CAPI_H__ +#define __THORVG_CAPI_H__ + +#ifdef TVG_EXPORT + #undef TVG_EXPORT +#endif + +#ifdef TVG_BUILD + #define TVG_EXPORT __attribute__ ((visibility ("default"))) +#else + #define TVG_EXPORT +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _Tvg_Canvas Tvg_Canvas; +typedef struct _Tvg_Paint Tvg_Paint; + +#define TVG_ENGINE_SW (1 << 1) +#define TVG_ENGINE_GL (1 << 2) + +typedef enum { + TVG_RESULT_SUCCESS = 0, + TVG_RESULT_INVALID_ARGUMENT, + TVG_RESULT_INSUFFICIENT_CONDITION, + TVG_RESULT_FAILED_ALLOCATION, + TVG_RESULT_MEMORY_CORRUPTION, + TVG_RESULT_NOT_SUPPORTED, + TVG_RESULT_UNKNOWN +} Tvg_Result; + +typedef enum { + TVG_PATH_COMMAND_CLOSE = 0, + TVG_PATH_COMMAND_MOVE_TO, + TVG_PATH_COMMAND_LINE_TO, + TVG_PATH_COMMAND_CUBIC_TO +} Tvg_Path_Command; + +typedef enum { + TVG_STROKE_CAP_SQUARE = 0, + TVG_STROKE_CAP_ROUND, + TVG_STROKE_CAP_BUTT +} Tvg_Stroke_Cap; + +typedef enum { + TVG_STROKE_JOIN_BEVEL = 0, + TVG_STROKE_JOIN_ROUND, + TVG_STROKE_JOIN_MITER +} Tvg_Stroke_Join; + +typedef enum { + TVG_STROKE_FILL_PAD = 0, + TVG_STROKE_FILL_REFLECT, + TVG_STROKE_FILL_REPEAT +} Tvg_Stroke_Fill; + + +typedef struct +{ + float x, y; +} Tvg_Point; + +typedef struct +{ + float e11, e12, e13; + float e21, e22, e23; + float e31, e32, e33; +} Tvg_Matrix; + + + +TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method); +TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method); + +TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create(); +TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h); + +TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas); +TVG_EXPORT Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint); +TVG_EXPORT Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n); +TVG_EXPORT Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas); +TVG_EXPORT Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas); +TVG_EXPORT Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint); +TVG_EXPORT Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, unsigned char async); +TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas); + +TVG_EXPORT Tvg_Paint* tvg_shape_new(); +TVG_EXPORT Tvg_Result tvg_shape_del(Tvg_Paint* paint); +TVG_EXPORT Tvg_Result tvg_shape_reset(Tvg_Paint* paint); +TVG_EXPORT Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y); +TVG_EXPORT Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y); +TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y); +TVG_EXPORT Tvg_Result tvg_shape_close(Tvg_Paint* paint); +TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry); +TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry); +TVG_EXPORT Tvg_Result tvg_shape_append_path(Tvg_Paint* paint, const Tvg_Path_Command* cmds, uint32_t cmdCnt, const Tvg_Point* pts, uint32_t ptsCnt); +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width); +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt); +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap); +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join); +TVG_EXPORT Tvg_Result tvg_shape_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a); + +#ifdef __cplusplus +} +#endif + +#endif //_THORVG_CAPI_H_ diff --git a/meson.build b/meson.build index d1803a3..6da6d26 100644 --- a/meson.build +++ b/meson.build @@ -22,6 +22,10 @@ if get_option('vectors').contains('avx') == true config_h.set10('THORVG_AVX_VECTOR_SUPPORT', true) endif +if get_option('bindings').contains('capi') == true + config_h.set10('THORVG_CAPI_BINDING_SUPPORT', true) +endif + configure_file( output: 'config.h', configuration: config_h diff --git a/meson_options.txt b/meson_options.txt index 5a440fa..59d0130 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -15,3 +15,9 @@ option('vectors', choices: ['', 'avx'], value: [''], description: 'Enable CPU Vectorization(SIMD) in thorvg') + +option('bindings', + type: 'array', + choices: ['', 'capi'], + value: ['capi'], + description: 'Enable C API binding') diff --git a/src/bindings/capi/meson.build b/src/bindings/capi/meson.build new file mode 100644 index 0000000..919442a --- /dev/null +++ b/src/bindings/capi/meson.build @@ -0,0 +1,8 @@ +source_file = [ + 'tvgCapi.cpp', +] + +subbinding_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp new file mode 100644 index 0000000..37e01af --- /dev/null +++ b/src/bindings/capi/tvgCapi.cpp @@ -0,0 +1,214 @@ +#include +#include "thorvg_capi.h" + +using namespace std; +using namespace tvg; + +#ifdef __cplusplus +extern "C" { +#endif + +struct _Tvg_Canvas +{ + //Dummy for Direct Casting +}; + +struct _Tvg_Paint +{ + //Dummy for Direct Casting +}; + + +/************************************************************************/ +/* Engine API */ +/************************************************************************/ + +TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) { + Result ret = Result::Success; + + if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (ret != Result::Success) return (Tvg_Result) ret; + + if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl); + return (Tvg_Result) ret; +} + + +TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) { + Result ret = Result::Success; + + if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (ret != Result::Success) return (Tvg_Result) ret; + + if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl); + return (Tvg_Result) ret; +} + +/************************************************************************/ +/* Canvas API */ +/************************************************************************/ + +TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create() +{ + return (Tvg_Canvas*) SwCanvas::gen().release(); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas) +{ + delete(canvas); + return TVG_RESULT_SUCCESS; +} + + +TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) +{ + return (Tvg_Result) reinterpret_cast(canvas)->target(buffer, stride, w, h); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint) +{ + return (Tvg_Result) reinterpret_cast(canvas)->push(unique_ptr((Paint*)paint)); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n) +{ + return (Tvg_Result) reinterpret_cast(canvas)->reserve(n); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas) +{ + return (Tvg_Result) reinterpret_cast(canvas)->clear(); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas) +{ + return (Tvg_Result) reinterpret_cast(canvas)->update(); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint) +{ + return (Tvg_Result) reinterpret_cast(canvas)->update((Paint*) paint); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, unsigned char async) +{ + return (Tvg_Result) reinterpret_cast(canvas)->draw(async); +} + + +TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas) +{ + return (Tvg_Result) reinterpret_cast(canvas)->sync(); +} + + +/************************************************************************/ +/* Shape API */ +/************************************************************************/ + +TVG_EXPORT Tvg_Paint* tvg_shape_new() +{ + return (Tvg_Paint*) Shape::gen().release(); +} + + +TVG_EXPORT Tvg_Result tvg_shape_del(Tvg_Paint* paint) +{ + delete(paint); + return TVG_RESULT_SUCCESS; +} + + +TVG_EXPORT Tvg_Result tvg_shape_reset(Tvg_Paint* paint) +{ + return (Tvg_Result) reinterpret_cast(paint)->reset(); +} + + +TVG_EXPORT Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y) +{ + return (Tvg_Result) reinterpret_cast(paint)->moveTo(x, y); +} + + +TVG_EXPORT Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y) +{ + return (Tvg_Result) reinterpret_cast(paint)->lineTo(x, y); +} + + +TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y) +{ + return (Tvg_Result) reinterpret_cast(paint)->cubicTo(cx1, cy1, cx2, cy2, x, y); +} + + +TVG_EXPORT Tvg_Result tvg_shape_close(Tvg_Paint* paint) +{ + return (Tvg_Result) reinterpret_cast(paint)->close(); +} + + +TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry) +{ + return (Tvg_Result) reinterpret_cast(paint)->appendRect(x, y, w, h, rx, ry); +} + + +TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry) +{ + return (Tvg_Result) reinterpret_cast(paint)->appendCircle(cx, cy, rx, ry); +} + + +TVG_EXPORT Tvg_Result tvg_shape_append_path(Tvg_Paint* paint, const Tvg_Path_Command* cmds, uint32_t cmdCnt, const Tvg_Point* pts, uint32_t ptsCnt) +{ + return (Tvg_Result) reinterpret_cast(paint)->appendPath((PathCommand*)cmds, cmdCnt, (Point*)pts, ptsCnt); +} + + +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width) +{ + return (Tvg_Result) reinterpret_cast(paint)->stroke(width); +} + + +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (Tvg_Result) reinterpret_cast(paint)->stroke(r, g, b, a); +} + + +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt) +{ + return (Tvg_Result) reinterpret_cast(paint)->stroke(dashPattern, cnt); +} + + +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap) +{ + return (Tvg_Result) reinterpret_cast(paint)->stroke((StrokeCap)cap); +} + + +TVG_EXPORT Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join) +{ + return (Tvg_Result) reinterpret_cast(paint)->stroke((StrokeJoin)join); +} + + +TVG_EXPORT Tvg_Result tvg_shape_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (Tvg_Result) reinterpret_cast(paint)->fill(r, g, b, a); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/bindings/meson.build b/src/bindings/meson.build new file mode 100644 index 0000000..2b3a150 --- /dev/null +++ b/src/bindings/meson.build @@ -0,0 +1,11 @@ +subbinding_dep = [] + +if get_option('bindings').contains('capi') == true + subdir('capi') + message('Enable CAPI Bindings') +endif + +binding_dep = declare_dependency( + dependencies: subbinding_dep, + include_directories : include_directories('.'), +) diff --git a/src/meson.build b/src/meson.build index 6873870..ced59a5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,10 +11,11 @@ endif subdir('lib') subdir('loaders') +subdir('bindings') subdir('examples') thread_dep = meson.get_compiler('cpp').find_library('pthread') -thorvg_lib_dep = [common_dep, loader_dep, thread_dep] +thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep] thorvg_lib = library( 'thorvg', diff --git a/test/makefile b/test/makefile index 6455a0a..ef9e28a 100644 --- a/test/makefile +++ b/test/makefile @@ -18,3 +18,4 @@ all: gcc -o testGradientTransform testGradientTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` gcc -o testSvg testSvg.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` gcc -o testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` + gcc -o testCapi testCapi.c -g 'pkg-config --cflags --libs elementary thorvg` diff --git a/test/testCapi.c b/test/testCapi.c new file mode 100644 index 0000000..5b8b91b --- /dev/null +++ b/test/testCapi.c @@ -0,0 +1,73 @@ +#include +#include + +#define WIDTH 800 +#define HEIGHT 800 + + +/************************************************************************/ +/* Capi Test Code */ +/************************************************************************/ + +static uint32_t buffer[WIDTH * HEIGHT]; + +void testCapi() +{ + tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL); + + Tvg_Canvas* canvas = tvg_swcanvas_create(); + tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT); + + Tvg_Paint* shape = tvg_shape_new(); + tvg_shape_append_rect(shape, 0, 0, 200, 200, 0, 0); + tvg_shape_append_rect(shape, 100, 100, 300, 300, 100, 100); + tvg_shape_append_circle(shape, 400, 400, 100, 100); + tvg_shape_append_circle(shape, 400, 500, 170, 100); + tvg_shape_fill_color(shape, 255, 255, 0, 255); + tvg_canvas_push(canvas, shape); + + tvg_canvas_draw(canvas, 1); + tvg_canvas_sync(canvas); + + tvg_canvas_destroy(canvas); + + tvg_engine_term(TVG_ENGINE_SW | TVG_ENGINE_GL); +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + +void win_del(void *data, Evas_Object *o, void *ev) +{ + elm_exit(); +} + + +int main(int argc, char **argv) +{ + elm_init(argc, argv); + + Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test"); + evas_object_smart_callback_add(win, "delete,request", win_del, 0); + + Eo* view = evas_object_image_filled_add(evas_object_evas_get(win)); + evas_object_image_size_set(view, WIDTH, HEIGHT); + evas_object_image_data_set(view, buffer); + evas_object_image_pixels_dirty_set(view, EINA_TRUE); + evas_object_image_data_update_add(view, 0, 0, WIDTH, HEIGHT); + evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(view); + + elm_win_resize_object_add(win, view); + evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); + evas_object_show(win); + + testCapi(); + + elm_run(); + elm_shutdown(); + + return 0; +} -- 2.7.4 From 2501c50506da04fccf7dda3949b8313dc164c723 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 15 Jul 2020 16:18:55 +0900 Subject: [PATCH 13/16] capi: improve code template. Change-Id: Ia48a21fbd93103b371b41a13adf46d82b76803b1 --- inc/thorvg_capi.h | 39 ++++++++++++++++++++++++++++++++++++++- src/bindings/capi/tvgCapi.cpp | 17 +++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index d2f7f85..7c92184 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + #ifndef __THORVG_CAPI_H__ #define __THORVG_CAPI_H__ @@ -22,6 +39,7 @@ typedef struct _Tvg_Paint Tvg_Paint; #define TVG_ENGINE_SW (1 << 1) #define TVG_ENGINE_GL (1 << 2) + typedef enum { TVG_RESULT_SUCCESS = 0, TVG_RESULT_INVALID_ARGUMENT, @@ -32,6 +50,7 @@ typedef enum { TVG_RESULT_UNKNOWN } Tvg_Result; + typedef enum { TVG_PATH_COMMAND_CLOSE = 0, TVG_PATH_COMMAND_MOVE_TO, @@ -39,18 +58,21 @@ typedef enum { TVG_PATH_COMMAND_CUBIC_TO } Tvg_Path_Command; + typedef enum { TVG_STROKE_CAP_SQUARE = 0, TVG_STROKE_CAP_ROUND, TVG_STROKE_CAP_BUTT } Tvg_Stroke_Cap; + typedef enum { TVG_STROKE_JOIN_BEVEL = 0, TVG_STROKE_JOIN_ROUND, TVG_STROKE_JOIN_MITER } Tvg_Stroke_Join; + typedef enum { TVG_STROKE_FILL_PAD = 0, TVG_STROKE_FILL_REFLECT, @@ -63,6 +85,7 @@ typedef struct float x, y; } Tvg_Point; + typedef struct { float e11, e12, e13; @@ -71,13 +94,23 @@ typedef struct } Tvg_Matrix; - +/************************************************************************/ +/* Engine API */ +/************************************************************************/ TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method); TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method); + +/************************************************************************/ +/* SwCanvas API */ +/************************************************************************/ TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create(); TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h); + +/************************************************************************/ +/* Common Canvas API */ +/************************************************************************/ TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas); TVG_EXPORT Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint); TVG_EXPORT Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n); @@ -87,6 +120,10 @@ TVG_EXPORT Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* pai TVG_EXPORT Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, unsigned char async); TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas); + +/************************************************************************/ +/* Shape API */ +/************************************************************************/ TVG_EXPORT Tvg_Paint* tvg_shape_new(); TVG_EXPORT Tvg_Result tvg_shape_del(Tvg_Paint* paint); TVG_EXPORT Tvg_Result tvg_shape_reset(Tvg_Paint* paint); diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 37e01af..6ba0e6d 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + #include #include "thorvg_capi.h" -- 2.7.4 From 1b48bf10fe01e2026296c3eef6fe82e471889e56 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 9 Jul 2020 20:12:48 +0900 Subject: [PATCH 14/16] SvgLoader: Verify SVG resource Only tag is parsed first before data get in file open function. If the tag is found, the loaded file is valid and stores viewbox information. After that, the remaining content data is parsed in order with async. Change-Id: Idb934fbd5e190c7c523abe601a80745ccc767af1 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 87 +++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 9 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 130a60c..9d58792 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -1982,6 +1982,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, node = method(loader, nullptr, attrs, attrsLength); loader->doc = node; } else { + if (!strcmp(tagName, "svg")) return; //Already loadded (SvgNodeType::Doc) tag if (loader->stack.size() > 0) parent = loader->stack.at(loader->stack.size() - 1); node = method(loader, parent, attrs, attrsLength); } @@ -2223,6 +2224,64 @@ static void _freeSvgNode(SvgNode* node) } +static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const char* content, unsigned int length) +{ + const char* attrs = nullptr; + int sz = length; + char tagName[20] = ""; + FactoryMethod method; + SvgNode *node = nullptr; + int attrsLength = 0; + loader->level++; + attrs = simpleXmlFindAttributesTag(content, length); + + if (!attrs) { + //Parse the empty tag + attrs = content; + while ((attrs != nullptr) && *attrs != '>') attrs++; + } + + if (attrs) { + sz = attrs - content; + attrsLength = length - sz; + while ((sz > 0) && (isspace(content[sz - 1]))) sz--; + strncpy(tagName, content, sz); + tagName[sz] = '\0'; + } + + if ((method = _findGroupFactory(tagName))) { + if (!loader->doc) { + if (strcmp(tagName, "svg")) return true; //Not a valid svg document + node = method(loader, nullptr, attrs, attrsLength); + loader->doc = node; + loader->stack.push_back(node); + return false; + } + } + return true; +} + + +static bool _svgLoaderParserForValidCheck(void* data, SimpleXMLType type, const char* content, unsigned int offset, unsigned int length) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + bool res = true;; + + switch (type) { + case SimpleXMLType::Open: + case SimpleXMLType::OpenEmpty: { + //If 'res' is false, it means tag is found. + res = _svgLoaderParserForValidCheckXmlOpen(loader, content, length); + break; + } + default: { + break; + } + } + + return res; +} + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -2254,12 +2313,25 @@ bool SvgLoader::open(const char* path) if (content.empty()) return false; } - //FIXME: Verify this resource is normal SVG, otherwise return false - //Also, return the brief resource info such as viewbox: - //this->vx = ? - //this->vy = ? - //this->vw = ? - //this->vh = ? + //For valid check, only tag is parsed first. + //If the tag is found, the loaded file is valid and stores viewbox information. + //After that, the remaining content data is parsed in order with async. + loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); + if (!loaderData.svgParse) return false; + + simpleXmlParse(content.c_str(), content.size(), true, _svgLoaderParserForValidCheck, &(loaderData)); + + if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) { + //Return the brief resource info such as viewbox: + this->vx = loaderData.doc->node.doc.vx; + this->vy = loaderData.doc->node.doc.vy; + this->vw = loaderData.doc->node.doc.vw; + this->vh = loaderData.doc->node.doc.vh; + + } else { + cout << "ERROR : No SVG File. There is no " <loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); - bool res = simpleXmlParse(loader->content.c_str(), loader->content.size(), true, _svgLoaderParser, &(loader->loaderData)); if (!res) return unique_ptr(nullptr); -- 2.7.4 From a6344daa66ef53a74d1a72876aaead934e629c3a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 16 Jul 2020 13:45:27 +0900 Subject: [PATCH 15/16] sw_engine: fix wrong gradient fill transform. it missed the offset when transformed gradient positions. now it's fixed. Change-Id: I916bd88b40bc29ca57d31411b92e10fe357d720e --- src/lib/sw_engine/tvgSwFill.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 1f72ee9..fd857f9 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -100,12 +100,12 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr auto cy = (y2 - y1) * 0.5f + y1; auto dx = x1 - cx; auto dy = y1 - cy; - x1 = dx * transform->e11 + dy * transform->e12 + transform->e31; - y1 = dx * transform->e21 + dy * transform->e22 + transform->e32; + x1 = dx * transform->e11 + dy * transform->e12 + transform->e31 + cx; + y1 = dx * transform->e21 + dy * transform->e22 + transform->e32 + cy; dx = x2 - cx; dy = y2 - cy; - x2 = dx * transform->e11 + dy * transform->e12 + transform->e31; - y2 = dx * transform->e21 + dy * transform->e22 + transform->e32; + x2 = dx * transform->e11 + dy * transform->e12 + transform->e31 + cx; + y2 = dx * transform->e21 + dy * transform->e22 + transform->e32 + cy; } fill->linear.dx = x2 - x1; -- 2.7.4 From e3218a8a9aeac1123a9fcfcefe9df1083ec1fa28 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 16 Jul 2020 14:58:35 +0900 Subject: [PATCH 16/16] test: Fix typo in makefile ' -> ` Change-Id: Iafacfb78d8f788ef302e5ad7f1a1d9cfbd380ffb --- test/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/makefile b/test/makefile index ef9e28a..e1a8afb 100644 --- a/test/makefile +++ b/test/makefile @@ -18,4 +18,4 @@ all: gcc -o testGradientTransform testGradientTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` gcc -o testSvg testSvg.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` gcc -o testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` - gcc -o testCapi testCapi.c -g 'pkg-config --cflags --libs elementary thorvg` + gcc -o testCapi testCapi.c -g `pkg-config --cflags --libs elementary thorvg` -- 2.7.4