From ec6e5618e234c4fd88b3c1d79e4c6686321d4cba Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 30 Jul 2020 16:50:29 +0900 Subject: [PATCH 01/16] common picture: introduce picture feature which is for vector file extensions. Now Scene is only specialized for composition of Paint objects. Change-Id: I16426913f029c89e9f9ac4d5e0afed11d1a228d0 --- inc/thorvg.h | 24 ++++++- src/lib/meson.build | 2 + src/lib/tvgCommon.h | 5 -- src/lib/tvgPicture.cpp | 57 +++++++++++++++ src/lib/tvgPictureImpl.h | 179 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib/tvgScene.cpp | 10 +-- src/lib/tvgSceneImpl.h | 75 ++++++-------------- src/lib/tvgShape.cpp | 1 - src/lib/tvgShapeImpl.h | 1 + test/testSvg.cpp | 8 +-- 10 files changed, 290 insertions(+), 72 deletions(-) create mode 100644 src/lib/tvgPicture.cpp create mode 100644 src/lib/tvgPictureImpl.h diff --git a/inc/thorvg.h b/inc/thorvg.h index 36fed95..7c725bc 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -268,6 +268,28 @@ public: /** + * @class Picture + * + * @ingroup ThorVG + * + * @brief description... + * + */ +class TVG_EXPORT Picture final : public Paint +{ +public: + ~Picture(); + + Result load(const std::string& path) noexcept; + Result size(float* w, float* h) const noexcept; + + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(Picture); +}; + + +/** * @class Scene * * @ingroup ThorVG @@ -282,11 +304,11 @@ public: Result push(std::unique_ptr paint) noexcept; Result reserve(uint32_t size) noexcept; - Result load(const std::string& path) noexcept; static std::unique_ptr gen() noexcept; _TVG_DECLARE_PRIVATE(Scene); + _TVG_DECLARE_ACCESSOR(Picture); }; diff --git a/src/lib/meson.build b/src/lib/meson.build index 64cedbd..631016d 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -16,6 +16,7 @@ source_file = [ 'tvgBezier.h', 'tvgLoader.h', 'tvgLoaderMgr.h', + 'tvgPictureImpl.h', 'tvgRender.h', 'tvgSceneImpl.h', 'tvgShapePath.h', @@ -28,6 +29,7 @@ source_file = [ 'tvgLinearGradient.cpp', 'tvgLoaderMgr.cpp', 'tvgPaint.cpp', + 'tvgPicture.cpp', 'tvgRadialGradient.cpp', 'tvgRender.cpp', 'tvgScene.cpp', diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 4cec18f..dddac62 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -31,8 +31,6 @@ using namespace std; using namespace tvg; #define IMPL pImpl.get() -#define SCENE_IMPL scene->pImpl.get() -#define SHAPE_IMPL shape->pImpl.get() #define FILL_ID_LINEAR 0 #define FILL_ID_RADIAL 1 @@ -42,8 +40,5 @@ using namespace tvg; #include "tvgLoaderMgr.h" #include "tvgRender.h" #include "tvgPaint.h" -#include "tvgShapePath.h" -#include "tvgShapeImpl.h" -#include "tvgSceneImpl.h" #endif //_TVG_COMMON_H_ diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp new file mode 100644 index 0000000..6d6ae47 --- /dev/null +++ b/src/lib/tvgPicture.cpp @@ -0,0 +1,57 @@ +/* + * 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 _TVG_PICTURE_CPP_ +#define _TVG_PICTURE_CPP_ + +#include "tvgPictureImpl.h" + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Picture::Picture() : pImpl(make_unique()) +{ + Paint::IMPL->method(new PaintMethod(IMPL)); +} + + +Picture::~Picture() +{ +} + + +unique_ptr Picture::gen() noexcept +{ + return unique_ptr(new Picture); +} + + +Result Picture::load(const std::string& path) noexcept +{ + if (path.empty()) return Result::InvalidArguments; + + return IMPL->load(path); +} + + +Result Picture::size(float* w, float* h) const noexcept +{ + if (IMPL->size(w, h)) return Result::Success; + return Result::InsufficientCondition; +} + +#endif /* _TVG_PICTURE_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h new file mode 100644 index 0000000..b72c556 --- /dev/null +++ b/src/lib/tvgPictureImpl.h @@ -0,0 +1,179 @@ +/* + * 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 _TVG_PICTURE_IMPL_H_ +#define _TVG_PICTURE_IMPL_H_ + +#include "tvgCommon.h" +#include "tvgSceneImpl.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Picture::Impl +{ + unique_ptr loader = nullptr; + Scene* scene = nullptr; + RenderTransform *rTransform = nullptr; + uint32_t flag = RenderUpdateFlag::None; + + ~Impl() + { + if (rTransform) delete(rTransform); + } + + bool dispose(RenderMethod& renderer) + { + if (!scene) return false; + + scene->IMPL->dispose(renderer); + delete(scene); + + return true; + } + + bool update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t pFlag) + { + if (loader) { + auto scene = loader->data(); + if (scene) { + this->scene = scene.release(); + if (!this->scene) return false; + loader->close(); + } + } + + if (!scene) return false; + + if (flag & RenderUpdateFlag::Transform) { + if (!rTransform) return false; + if (!rTransform->update()) { + delete(rTransform); + rTransform = nullptr; + } + } + + auto ret = true; + + if (rTransform && pTransform) { + RenderTransform outTransform(pTransform, rTransform); + ret = scene->IMPL->update(renderer, &outTransform, flag); + } else { + auto outTransform = pTransform ? pTransform : rTransform; + ret = scene->IMPL->update(renderer, outTransform, flag); + } + + flag = RenderUpdateFlag::None; + + return ret; + } + + bool render(RenderMethod &renderer) + { + if (!scene) return false; + return scene->IMPL->render(renderer); + } + + + bool size(float* w, float* h) + { + if (loader) { + if (w) *w = loader->vw; + if (h) *h = loader->vh; + return true; + } + + return false; + } + + bool bounds(float* x, float* y, float* w, float* h) + { + if (!scene) return false; + return scene->IMPL->bounds(x, y, w, h); + } + + bool scale(float factor) + { + if (rTransform) { + if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true; + } else { + if (fabsf(factor) <= FLT_EPSILON) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->scale = factor; + flag |= RenderUpdateFlag::Transform; + + return true; + } + + bool rotate(float degree) + { + if (rTransform) { + if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true; + } else { + if (fabsf(degree) <= FLT_EPSILON) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->degree = degree; + flag |= RenderUpdateFlag::Transform; + + return true; + } + + bool translate(float x, float y) + { + if (rTransform) { + if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true; + } else { + if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->x = x; + rTransform->y = y; + flag |= RenderUpdateFlag::Transform; + + return true; + } + + + bool transform(const Matrix& m) + { + if (!rTransform) { + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->override(m); + flag |= RenderUpdateFlag::Transform; + + return true; + } + + + Result load(const string& path) + { + if (loader) loader->close(); + loader = LoaderMgr::loader(path.c_str()); + if (!loader || !loader->open(path.c_str())) return Result::NonSupport; + if (!loader->read()) return Result::Unknown; + return Result::Success; + } +}; + +#endif //_TVG_PICTURE_IMPL_H_ \ No newline at end of file diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index d34d57a..ff3aca8 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -17,7 +17,7 @@ #ifndef _TVG_SCENE_CPP_ #define _TVG_SCENE_CPP_ -#include "tvgCommon.h" +#include "tvgSceneImpl.h" /************************************************************************/ /* External Class Implementation */ @@ -57,12 +57,4 @@ Result Scene::reserve(uint32_t size) noexcept return Result::Success; } - -Result Scene::load(const std::string& path) noexcept -{ - if (path.empty()) return Result::InvalidArguments; - - return IMPL->load(path); -} - #endif /* _TVG_SCENE_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 0ba1f1f..84bdd7e 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -28,12 +28,9 @@ struct Scene::Impl vector paints; RenderTransform *rTransform = nullptr; uint32_t flag = RenderUpdateFlag::None; - unique_ptr loader = nullptr; ~Impl() { - //Are you sure clear() prior to this? - assert(paints.empty()); if (rTransform) delete(rTransform); } @@ -58,16 +55,6 @@ struct Scene::Impl bool update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t pFlag) { - if (loader) { - auto scene = loader->data(); - if (scene) { - auto p = scene.release(); - if (!p) return false; - paints.push_back(p); - loader->close(); - } - } - if (flag & RenderUpdateFlag::Transform) { if (!rTransform) return false; if (!rTransform->update()) { @@ -101,37 +88,31 @@ struct Scene::Impl bool bounds(float* px, float* py, float* pw, float* ph) { - if (loader) { - if (px) *px = loader->vx; - if (py) *py = loader->vy; - if (pw) *pw = loader->vw; - if (ph) *ph = loader->vh; - } else { - auto x = FLT_MAX; - auto y = FLT_MAX; - auto w = 0.0f; - auto h = 0.0f; - - for(auto paint: paints) { - auto x2 = FLT_MAX; - auto y2 = FLT_MAX; - auto w2 = 0.0f; - auto h2 = 0.0f; - - if (paint->IMPL->method()->bounds(&x2, &y2, &w2, &h2)) return false; - - //Merge regions - if (x2 < x) x = x2; - if (x + w < x2 + w2) w = (x2 + w2) - x; - if (y2 < y) y = x2; - if (y + h < y2 + h2) h = (y2 + h2) - y; - } + auto x = FLT_MAX; + auto y = FLT_MAX; + auto w = 0.0f; + auto h = 0.0f; - if (px) *px = x; - if (py) *py = y; - if (pw) *pw = w; - if (ph) *ph = h; + for(auto paint: paints) { + auto x2 = FLT_MAX; + auto y2 = FLT_MAX; + auto w2 = 0.0f; + auto h2 = 0.0f; + + if (paint->IMPL->method()->bounds(&x2, &y2, &w2, &h2)) return false; + + //Merge regions + if (x2 < x) x = x2; + if (x + w < x2 + w2) w = (x2 + w2) - x; + if (y2 < y) y = x2; + if (y + h < y2 + h2) h = (y2 + h2) - y; } + + if (px) *px = x; + if (py) *py = y; + if (pw) *pw = w; + if (ph) *ph = h; + return true; } @@ -193,16 +174,6 @@ struct Scene::Impl return true; } - - - Result load(const string& path) - { - if (loader) loader->close(); - loader = LoaderMgr::loader(path.c_str()); - if (!loader || !loader->open(path.c_str())) return Result::NonSupport; - if (!loader->read()) return Result::Unknown; - return Result::Success; - } }; #endif //_TVG_SCENE_IMPL_H_ \ No newline at end of file diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 7d26614..59718d8 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -17,7 +17,6 @@ #ifndef _TVG_SHAPE_CPP_ #define _TVG_SHAPE_CPP_ -#include "tvgCommon.h" #include "tvgShapeImpl.h" /************************************************************************/ diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index a7755da..2a7005e 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -18,6 +18,7 @@ #define _TVG_SHAPE_IMPL_H_ #include "tvgCommon.h" +#include "tvgShapePath.h" /************************************************************************/ /* Internal Class Implementation */ diff --git a/test/testSvg.cpp b/test/testSvg.cpp index b8eb2ba..5f05370 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -14,15 +14,15 @@ void svgDirCallback(const char* name, const char* path, void* data) { tvg::Canvas* canvas = static_cast(data); - auto scene = tvg::Scene::gen(); + auto picture = tvg::Picture::gen(); char buf[PATH_MAX]; sprintf(buf,"%s/%s", path, name); - if (scene->load(buf) != tvg::Result::Success) return; + if (picture->load(buf) != tvg::Result::Success) return; - scene->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); - canvas->push(move(scene)); + picture->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); + canvas->push(move(picture)); count++; -- 2.7.4 From e9a4e2ccb6d85c39145901f0097177d7ff516509 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 30 Jul 2020 19:17:55 +0900 Subject: [PATCH 02/16] common: code refactoring remove duplicated code among the Paint types. Change-Id: Ia7c09f29531e6aef73d2ba1f951f8dfdf488deb8 --- inc/thorvg.h | 12 ++--- src/lib/tvgCanvasImpl.h | 8 +-- src/lib/tvgPaint.cpp | 10 ++-- src/lib/tvgPaint.h | 119 ++++++++++++++++++++++++++++++++++---------- src/lib/tvgPictureImpl.h | 126 +++++++---------------------------------------- src/lib/tvgSceneImpl.h | 101 ++----------------------------------- src/lib/tvgShapeImpl.h | 83 ++----------------------------- 7 files changed, 133 insertions(+), 326 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 7c725bc..622c302 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -48,8 +48,10 @@ protected: \ A() = delete; \ ~A() = delete -#define _TVG_DECLARE_ACCESSOR(A) \ - friend A +#define _TVG_DECLARE_ACCESSOR() \ + friend Canvas; \ + friend Scene; \ + friend Picture #define _TVG_DECALRE_IDENTIFIER() \ auto id() const { return _id; } \ @@ -61,6 +63,7 @@ namespace tvg class RenderMethod; class Scene; +class Picture; class Canvas; @@ -105,9 +108,8 @@ public: Result transform(const Matrix& m) noexcept; Result bounds(float* x, float* y, float* w, float* h) const noexcept; + _TVG_DECLARE_ACCESSOR(); _TVG_DECLARE_PRIVATE(Paint); - _TVG_DECLARE_ACCESSOR(Canvas); - _TVG_DECLARE_ACCESSOR(Scene); }; @@ -166,7 +168,6 @@ public: }; - /** * @class LinearGradient * @@ -308,7 +309,6 @@ public: static std::unique_ptr gen() noexcept; _TVG_DECLARE_PRIVATE(Scene); - _TVG_DECLARE_ACCESSOR(Picture); }; diff --git a/src/lib/tvgCanvasImpl.h b/src/lib/tvgCanvasImpl.h index 2776735..adcd472 100644 --- a/src/lib/tvgCanvasImpl.h +++ b/src/lib/tvgCanvasImpl.h @@ -56,7 +56,7 @@ struct Canvas::Impl if (!renderer->clear()) return Result::InsufficientCondition; for (auto paint : paints) { - paint->IMPL->method()->dispose(*renderer); + paint->IMPL->dispose(*renderer); delete(paint); } paints.clear(); @@ -70,13 +70,13 @@ struct Canvas::Impl //Update single paint node if (paint) { - if (!paint->IMPL->method()->update(*renderer, nullptr, RenderUpdateFlag::None)) { + if (!paint->IMPL->update(*renderer, nullptr, RenderUpdateFlag::None)) { return Result::InsufficientCondition; } //Update retained all paint nodes } else { for(auto paint: paints) { - if (!paint->IMPL->method()->update(*renderer, nullptr, RenderUpdateFlag::None)) { + if (!paint->IMPL->update(*renderer, nullptr, RenderUpdateFlag::None)) { return Result::InsufficientCondition; } } @@ -91,7 +91,7 @@ struct Canvas::Impl if (!renderer->preRender()) return Result::InsufficientCondition; for(auto paint: paints) { - if(!paint->IMPL->method()->render(*renderer)) return Result::InsufficientCondition; + if(!paint->IMPL->render(*renderer)) return Result::InsufficientCondition; } if (!renderer->postRender()) return Result::InsufficientCondition; diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 8aa62d2..dacbffb 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -39,35 +39,35 @@ Paint :: ~Paint() Result Paint::rotate(float degree) noexcept { - if (IMPL->method()->rotate(degree)) return Result::Success; + if (IMPL->rotate(degree)) return Result::Success; return Result::FailedAllocation; } Result Paint::scale(float factor) noexcept { - if (IMPL->method()->scale(factor)) return Result::Success; + if (IMPL->scale(factor)) return Result::Success; return Result::FailedAllocation; } Result Paint::translate(float x, float y) noexcept { - if (IMPL->method()->translate(x, y)) return Result::Success; + if (IMPL->translate(x, y)) return Result::Success; return Result::FailedAllocation; } Result Paint::transform(const Matrix& m) noexcept { - if (IMPL->method()->transform(m)) return Result::Success; + if (IMPL->transform(m)) return Result::Success; return Result::FailedAllocation; } Result Paint::bounds(float* x, float* y, float* w, float* h) const noexcept { - if (IMPL->method()->bounds(x, y, w, h)) return Result::Success; + if (IMPL->bounds(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; } diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index 45e4c01..7d43df0 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -24,23 +24,20 @@ namespace tvg virtual ~StrategyMethod(){} virtual bool dispose(RenderMethod& renderer) = 0; - virtual bool update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t pFlag) = 0; + virtual bool update(RenderMethod& renderer, const RenderTransform* transform, RenderUpdateFlag pFlag) = 0; virtual bool render(RenderMethod& renderer) = 0; - - virtual bool rotate(float degree) = 0; - virtual bool scale(float factor) = 0; - virtual bool translate(float x, float y) = 0; - virtual bool transform(const Matrix& m) = 0; virtual bool bounds(float* x, float* y, float* w, float* h) const = 0; - }; struct Paint::Impl { StrategyMethod* smethod = nullptr; + RenderTransform *rTransform = nullptr; + uint32_t flag = RenderUpdateFlag::None; ~Impl() { if (smethod) delete(smethod); + if (rTransform) delete(rTransform); } void method(StrategyMethod* method) @@ -48,40 +45,110 @@ namespace tvg smethod = method; } - StrategyMethod* method() + bool rotate(float degree) { - return smethod; + if (rTransform) { + if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true; + } else { + if (fabsf(degree) <= FLT_EPSILON) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->degree = degree; + if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform; + + return true; } - }; + bool scale(float factor) + { + if (rTransform) { + if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true; + } else { + if (fabsf(factor) <= FLT_EPSILON) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->scale = factor; + if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform; + + return true; + } - template - struct PaintMethod : StrategyMethod - { - T* inst = nullptr; + bool translate(float x, float y) + { + if (rTransform) { + if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true; + } else { + if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->x = x; + rTransform->y = y; + if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform; + + return true; + } - PaintMethod(T* _inst) : inst(_inst) {} - ~PaintMethod(){} + bool transform(const Matrix& m) + { + if (!rTransform) { + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->override(m); + flag |= RenderUpdateFlag::Transform; + + return true; + } - bool rotate(float degree) override + bool bounds(float* x, float* y, float* w, float* h) const { - return inst->rotate(degree); + return smethod->bounds(x, y, w, h); } - bool scale(float factor) override + bool dispose(RenderMethod& renderer) { - return inst->scale(factor); + return smethod->dispose(renderer); } - bool translate(float x, float y) override + bool update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t pFlag) { - return inst->translate(x, y); + if (flag & RenderUpdateFlag::Transform) { + if (!rTransform) return false; + if (!rTransform->update()) { + delete(rTransform); + rTransform = nullptr; + } + } + + auto newFlag = static_cast(pFlag | flag); + flag = RenderUpdateFlag::None; + + if (rTransform && pTransform) { + RenderTransform outTransform(pTransform, rTransform); + return smethod->update(renderer, &outTransform, newFlag); + } else { + auto outTransform = pTransform ? pTransform : rTransform; + return smethod->update(renderer, outTransform, newFlag); + } } - bool transform(const Matrix& m) override + bool render(RenderMethod& renderer) { - return inst->transform(m); + return smethod->render(renderer); } + }; + + + template + struct PaintMethod : StrategyMethod + { + T* inst = nullptr; + + PaintMethod(T* _inst) : inst(_inst) {} + ~PaintMethod(){} bool bounds(float* x, float* y, float* w, float* h) const override { @@ -93,9 +160,9 @@ namespace tvg return inst->dispose(renderer); } - bool update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t pFlag) + bool update(RenderMethod& renderer, const RenderTransform* transform, RenderUpdateFlag flag) { - return inst->update(renderer, pTransform, pFlag); + return inst->update(renderer, transform, flag); } bool render(RenderMethod& renderer) diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index b72c556..098176d 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -18,7 +18,6 @@ #define _TVG_PICTURE_IMPL_H_ #include "tvgCommon.h" -#include "tvgSceneImpl.h" /************************************************************************/ /* Internal Class Implementation */ @@ -27,145 +26,54 @@ struct Picture::Impl { unique_ptr loader = nullptr; - Scene* scene = nullptr; - RenderTransform *rTransform = nullptr; - uint32_t flag = RenderUpdateFlag::None; - - ~Impl() - { - if (rTransform) delete(rTransform); - } + Paint* paint = nullptr; bool dispose(RenderMethod& renderer) { - if (!scene) return false; + if (!paint) return false; - scene->IMPL->dispose(renderer); - delete(scene); + paint->IMPL->dispose(renderer); + delete(paint); return true; } - bool update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t pFlag) + bool update(RenderMethod &renderer, const RenderTransform* transform, RenderUpdateFlag flag) { if (loader) { auto scene = loader->data(); if (scene) { - this->scene = scene.release(); - if (!this->scene) return false; + this->paint = scene.release(); + if (!this->paint) return false; loader->close(); } } - if (!scene) return false; - - if (flag & RenderUpdateFlag::Transform) { - if (!rTransform) return false; - if (!rTransform->update()) { - delete(rTransform); - rTransform = nullptr; - } - } + if (!paint) return false; - auto ret = true; - - if (rTransform && pTransform) { - RenderTransform outTransform(pTransform, rTransform); - ret = scene->IMPL->update(renderer, &outTransform, flag); - } else { - auto outTransform = pTransform ? pTransform : rTransform; - ret = scene->IMPL->update(renderer, outTransform, flag); - } - - flag = RenderUpdateFlag::None; - - return ret; + return paint->IMPL->update(renderer, transform, flag); } bool render(RenderMethod &renderer) { - if (!scene) return false; - return scene->IMPL->render(renderer); + if (!paint) return false; + return paint->IMPL->render(renderer); } - bool size(float* w, float* h) { - if (loader) { - if (w) *w = loader->vw; - if (h) *h = loader->vh; - return true; - } - - return false; - } - - bool bounds(float* x, float* y, float* w, float* h) - { - if (!scene) return false; - return scene->IMPL->bounds(x, y, w, h); - } - - bool scale(float factor) - { - if (rTransform) { - if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true; - } else { - if (fabsf(factor) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->scale = factor; - flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool rotate(float degree) - { - if (rTransform) { - if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true; - } else { - if (fabsf(degree) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->degree = degree; - flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool translate(float x, float y) - { - if (rTransform) { - if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true; - } else { - if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->x = x; - rTransform->y = y; - flag |= RenderUpdateFlag::Transform; - + if (!loader) return false; + if (w) *w = loader->vw; + if (h) *h = loader->vh; return true; } - - bool transform(const Matrix& m) + bool bounds(float* x, float* y, float* w, float* h) { - if (!rTransform) { - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->override(m); - flag |= RenderUpdateFlag::Transform; - - return true; + if (!paint) return false; + return paint->IMPL->bounds(x, y, w, h); } - Result load(const string& path) { if (loader) loader->close(); diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 84bdd7e..c4cbb23 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -26,18 +26,11 @@ struct Scene::Impl { vector paints; - RenderTransform *rTransform = nullptr; - uint32_t flag = RenderUpdateFlag::None; - - ~Impl() - { - if (rTransform) delete(rTransform); - } bool dispose(RenderMethod& renderer) { for (auto paint : paints) { - paint->IMPL->method()->dispose(renderer); + paint->IMPL->dispose(renderer); delete(paint); } paints.clear(); @@ -45,43 +38,18 @@ struct Scene::Impl return true; } - bool updateInternal(RenderMethod &renderer, const RenderTransform* transform, uint32_t flag) + bool update(RenderMethod &renderer, const RenderTransform* transform, RenderUpdateFlag flag) { for(auto paint: paints) { - if (!paint->IMPL->method()->update(renderer, transform, flag)) return false; + if (!paint->IMPL->update(renderer, transform, static_cast(flag))) return false; } return true; } - bool update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t pFlag) - { - if (flag & RenderUpdateFlag::Transform) { - if (!rTransform) return false; - if (!rTransform->update()) { - delete(rTransform); - rTransform = nullptr; - } - } - - auto ret = true; - - if (rTransform && pTransform) { - RenderTransform outTransform(pTransform, rTransform); - ret = updateInternal(renderer, &outTransform, pFlag | flag); - } else { - auto outTransform = pTransform ? pTransform : rTransform; - ret = updateInternal(renderer, outTransform, pFlag | flag); - } - - flag = RenderUpdateFlag::None; - - return ret; - } - bool render(RenderMethod &renderer) { for(auto paint: paints) { - if(!paint->IMPL->method()->render(renderer)) return false; + if(!paint->IMPL->render(renderer)) return false; } return true; } @@ -99,7 +67,7 @@ struct Scene::Impl auto w2 = 0.0f; auto h2 = 0.0f; - if (paint->IMPL->method()->bounds(&x2, &y2, &w2, &h2)) return false; + if (paint->IMPL->bounds(&x2, &y2, &w2, &h2)) return false; //Merge regions if (x2 < x) x = x2; @@ -115,65 +83,6 @@ struct Scene::Impl return true; } - - bool scale(float factor) - { - if (rTransform) { - if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true; - } else { - if (fabsf(factor) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->scale = factor; - flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool rotate(float degree) - { - if (rTransform) { - if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true; - } else { - if (fabsf(degree) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->degree = degree; - flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool translate(float x, float y) - { - if (rTransform) { - if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true; - } else { - if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->x = x; - rTransform->y = y; - flag |= RenderUpdateFlag::Transform; - - return true; - } - - - bool transform(const Matrix& m) - { - if (!rTransform) { - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->override(m); - flag |= RenderUpdateFlag::Transform; - - return true; - } }; #endif //_TVG_SCENE_IMPL_H_ \ No newline at end of file diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 2a7005e..ab11db0 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -45,12 +45,10 @@ struct Shape::Impl ShapePath *path = nullptr; Fill *fill = nullptr; ShapeStroke *stroke = nullptr; - RenderTransform *rTransform = nullptr; uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a - uint32_t flag = RenderUpdateFlag::None; void *edata = nullptr; //engine data Shape *shape = nullptr; - + uint32_t flag = RenderUpdateFlag::None; Impl(Shape* s) : path(new ShapePath), shape(s) { @@ -61,7 +59,6 @@ struct Shape::Impl if (path) delete(path); if (fill) delete(fill); if (stroke) delete(stroke); - if (rTransform) delete(rTransform); } bool dispose(RenderMethod& renderer) @@ -74,23 +71,9 @@ struct Shape::Impl return renderer.render(*shape, edata); } - bool update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t pFlag) + bool update(RenderMethod& renderer, const RenderTransform* transform, RenderUpdateFlag pFlag) { - if (flag & RenderUpdateFlag::Transform) { - if (!rTransform) return false; - if (!rTransform->update()) { - delete(rTransform); - rTransform = nullptr; - } - } - - if (rTransform && pTransform) { - RenderTransform outTransform(pTransform, rTransform); - edata = renderer.prepare(*shape, edata, &outTransform, static_cast(pFlag | flag)); - } else { - auto outTransform = pTransform ? pTransform : rTransform; - edata = renderer.prepare(*shape, edata, outTransform, static_cast(pFlag | flag)); - } + edata = renderer.prepare(*shape, edata, transform, static_cast(pFlag | flag)); flag = RenderUpdateFlag::None; @@ -104,66 +87,6 @@ struct Shape::Impl return path->bounds(x, y, w, h); } - bool scale(float factor) - { - if (rTransform) { - if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true; - } else { - if (fabsf(factor) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->scale = factor; - if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool rotate(float degree) - { - if (rTransform) { - if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true; - } else { - if (fabsf(degree) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->degree = degree; - if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool translate(float x, float y) - { - if (rTransform) { - if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true; - } else { - if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true; - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->x = x; - rTransform->y = y; - if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform; - - return true; - } - - - bool transform(const Matrix& m) - { - if (!rTransform) { - rTransform = new RenderTransform(); - if (!rTransform) return false; - } - rTransform->override(m); - flag |= RenderUpdateFlag::Transform; - - return true; - } - - bool strokeWidth(float width) { //TODO: Size Exception? -- 2.7.4 From f15aefa5dc1e48d97cea1316cb38dd3888a021de Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 30 Jul 2020 20:40:12 +0900 Subject: [PATCH 03/16] test: updated svg sample also revise size() method of Picture for proper aligning. Change-Id: I58a0886968f6058e65a062477e2a873224d8ea8f --- inc/thorvg.h | 2 +- src/lib/tvgPicture.cpp | 4 +- src/lib/tvgPictureImpl.h | 4 +- test/svgs/batman1.svg | 3 + test/svgs/eee.svg | 4 + test/svgs/favorite_on.svg | 11 + test/svgs/google.svg | 4 + test/svgs/ibm.svg | 44 +++ test/svgs/scion.svg | 9 + test/svgs/tiger.svg | 829 ++++++++++++++++++++++++++++++++++++++++++++++ test/svgs/wikimedia.svg | 5 - test/svgs/yadis.svg | 16 + test/testSvg.cpp | 32 +- 13 files changed, 951 insertions(+), 16 deletions(-) create mode 100644 test/svgs/batman1.svg create mode 100644 test/svgs/eee.svg create mode 100644 test/svgs/favorite_on.svg create mode 100644 test/svgs/google.svg create mode 100644 test/svgs/ibm.svg create mode 100644 test/svgs/scion.svg create mode 100644 test/svgs/tiger.svg delete mode 100644 test/svgs/wikimedia.svg create mode 100644 test/svgs/yadis.svg diff --git a/inc/thorvg.h b/inc/thorvg.h index 622c302..c738a0e 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -282,7 +282,7 @@ public: ~Picture(); Result load(const std::string& path) noexcept; - Result size(float* w, float* h) const noexcept; + Result viewbox(float* x, float* y, float* w, float* h) const noexcept; static std::unique_ptr gen() noexcept; diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 6d6ae47..0370163 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -48,9 +48,9 @@ Result Picture::load(const std::string& path) noexcept } -Result Picture::size(float* w, float* h) const noexcept +Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept { - if (IMPL->size(w, h)) return Result::Success; + if (IMPL->viewbox(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 098176d..ed1c678 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -60,9 +60,11 @@ struct Picture::Impl return paint->IMPL->render(renderer); } - bool size(float* w, float* h) + bool viewbox(float* x, float* y, float* w, float* h) { if (!loader) return false; + if (x) *x = loader->vx; + if (y) *y = loader->vy; if (w) *w = loader->vw; if (h) *h = loader->vh; return true; diff --git a/test/svgs/batman1.svg b/test/svgs/batman1.svg new file mode 100644 index 0000000..7a9d229 --- /dev/null +++ b/test/svgs/batman1.svg @@ -0,0 +1,3 @@ + + + diff --git a/test/svgs/eee.svg b/test/svgs/eee.svg new file mode 100644 index 0000000..c23875e --- /dev/null +++ b/test/svgs/eee.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/test/svgs/favorite_on.svg b/test/svgs/favorite_on.svg new file mode 100644 index 0000000..c34b320 --- /dev/null +++ b/test/svgs/favorite_on.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/test/svgs/google.svg b/test/svgs/google.svg new file mode 100644 index 0000000..3e51a42 --- /dev/null +++ b/test/svgs/google.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/test/svgs/ibm.svg b/test/svgs/ibm.svg new file mode 100644 index 0000000..c87ad11 --- /dev/null +++ b/test/svgs/ibm.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/svgs/scion.svg b/test/svgs/scion.svg new file mode 100644 index 0000000..24fa109 --- /dev/null +++ b/test/svgs/scion.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/svgs/tiger.svg b/test/svgs/tiger.svg new file mode 100644 index 0000000..a59da8d --- /dev/null +++ b/test/svgs/tiger.svg @@ -0,0 +1,829 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/svgs/wikimedia.svg b/test/svgs/wikimedia.svg deleted file mode 100644 index ad2c211..0000000 --- a/test/svgs/wikimedia.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/test/svgs/yadis.svg b/test/svgs/yadis.svg new file mode 100644 index 0000000..7bcbad8 --- /dev/null +++ b/test/svgs/yadis.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 5f05370..e16f19b 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -4,11 +4,10 @@ /* Drawing Commands */ /************************************************************************/ -#define NUM_PER_LINE 3 +#define NUM_PER_LINE 4 +#define SIZE 200 -int x = 30; -int y = 30; -int count = 0; +static int count = 0; void svgDirCallback(const char* name, const char* path, void* data) { @@ -21,12 +20,31 @@ void svgDirCallback(const char* name, const char* path, void* data) if (picture->load(buf) != tvg::Result::Success) return; - picture->translate(((WIDTH - (x * 2)) / NUM_PER_LINE) * (count % NUM_PER_LINE) + x, ((HEIGHT - (y * 2))/ NUM_PER_LINE) * (int)((float)count / (float)NUM_PER_LINE) + y); - canvas->push(move(picture)); + float x, y, w, h; + picture->viewbox(&x, &y, &w, &h); - count++; + float rate = (SIZE/(w > h ? w : h)); + picture->scale(rate); + + x *= rate; + y *= rate; + w *= rate; + h *= rate; + + //Center Align ? + if (w > h) { + y -= (SIZE - h) * 0.5f; + } else { + x -= (SIZE - w) * 0.5f; + } + + picture->translate((count % NUM_PER_LINE) * SIZE - x, SIZE * (count / NUM_PER_LINE) - y); + + canvas->push(move(picture)); cout << "SVG: " << buf << endl; + + count++; } void tvgDrawCmds(tvg::Canvas* canvas) -- 2.7.4 From 7b9c7de1e5eca8e9fe300e17407ada28dc117802 Mon Sep 17 00:00:00 2001 From: Mateusz Palkowski Date: Fri, 31 Jul 2020 11:34:49 +0200 Subject: [PATCH 04/16] capi: Added C wrappers for gradient func Change-Id: If41dab9b06f6cec2831ea1361f30b50a193e99c4 --- inc/thorvg_capi.h | 20 +++++++++++++++++ src/bindings/capi/tvgCapi.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++ test/testCapi.c | 31 +++++++++++++++++++++++--- 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 9fa4d59..037730f 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -35,6 +35,7 @@ extern "C" { typedef struct _Tvg_Canvas Tvg_Canvas; typedef struct _Tvg_Paint Tvg_Paint; +typedef struct _Tvg_Gradient Tvg_Gradient; #define TVG_ENGINE_SW (1 << 1) #define TVG_ENGINE_GL (1 << 2) @@ -93,6 +94,11 @@ typedef struct float e31, e32, e33; } Tvg_Matrix; +typedef struct +{ + float offset; + uint8_t r, g, b, a; +} Tvg_Color_Stop; /************************************************************************/ /* Engine API */ @@ -144,6 +150,20 @@ TVG_EXPORT Tvg_Result tvg_shape_scale(Tvg_Paint* paint, float factor); TVG_EXPORT Tvg_Result tvg_shape_rotate(Tvg_Paint* paint, float degree); TVG_EXPORT Tvg_Result tvg_shape_translate(Tvg_Paint* paint, float x, float y); TVG_EXPORT Tvg_Result tvg_shape_transform(Tvg_Paint* paint, const Tvg_Matrix* m); +TVG_EXPORT Tvg_Result tvg_shape_linear_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad); +TVG_EXPORT Tvg_Result tvg_shape_radial_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad); + + +/************************************************************************/ +/* Gradient API */ +/************************************************************************/ +TVG_EXPORT Tvg_Gradient* tvg_linear_gradient_new(); +TVG_EXPORT Tvg_Gradient* tvg_radial_gradient_new(); +TVG_EXPORT Tvg_Result tvg_gradient_del(Tvg_Gradient* grad); +TVG_EXPORT Tvg_Result tvg_linear_gradient_set(Tvg_Gradient* grad, float x1, float y1, float x2, float y2); +TVG_EXPORT Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, float cy, float radius); +TVG_EXPORT Tvg_Result tvg_gradient_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt); + #ifdef __cplusplus } diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 9ceb113..5df6b5a 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -35,6 +35,11 @@ struct _Tvg_Paint //Dummy for Direct Casting }; +struct _Tvg_Gradient +{ + //Dummy for Direct Casting +}; + /************************************************************************/ /* Engine API */ @@ -246,6 +251,52 @@ TVG_EXPORT Tvg_Result tvg_shape_transform(Tvg_Paint* paint, const Tvg_Matrix* m) return (Tvg_Result) reinterpret_cast(paint)->transform(*(reinterpret_cast(m))); } +TVG_EXPORT Tvg_Result tvg_shape_linear_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad) +{ + return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((LinearGradient*)(grad))); +} + +TVG_EXPORT Tvg_Result tvg_shape_radial_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad) +{ + return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((RadialGradient*)(grad))); +} + + +/************************************************************************/ +/* Gradient API */ +/************************************************************************/ +TVG_EXPORT Tvg_Gradient* tvg_linear_gradient_new() +{ + return (Tvg_Gradient*)LinearGradient::gen().release(); +} + +TVG_EXPORT Tvg_Gradient* tvg_radial_gradient_new() +{ + return (Tvg_Gradient*)RadialGradient::gen().release(); + +} + +TVG_EXPORT Tvg_Result tvg_gradient_del(Tvg_Gradient* grad) +{ + delete(grad); + return TVG_RESULT_SUCCESS; +} + +TVG_EXPORT Tvg_Result tvg_linear_gradient_set(Tvg_Gradient* grad, float x1, float y1, float x2, float y2) +{ + return (Tvg_Result) reinterpret_cast(grad)->linear(x1, y1, x2, y2); +} + +TVG_EXPORT Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, float cy, float radius) +{ + return (Tvg_Result) reinterpret_cast(grad)->radial(cx, cy, radius); +} + +TVG_EXPORT Tvg_Result tvg_gradient_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt) +{ + return (Tvg_Result) reinterpret_cast(grad)->colorStops(reinterpret_cast(color_stop), cnt); +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/test/testCapi.c b/test/testCapi.c index 6a46e97..3a307ab 100644 --- a/test/testCapi.c +++ b/test/testCapi.c @@ -20,11 +20,36 @@ void testCapi() Tvg_Paint* shape = tvg_shape_new(); tvg_shape_append_rect(shape, 0, 0, 200, 200, 0, 0); + tvg_shape_append_circle(shape, 200, 200, 100, 100); 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_Gradient* grad = tvg_linear_gradient_new(); + tvg_linear_gradient_set(grad, 0, 0, 300, 300); + Tvg_Color_Stop color_stops[4] = + { + {.offset=0.0, .r=0, .g=0, .b=0, .a=255}, + {.offset=0.25, .r=255, .g=0, .b=0, .a=255}, + {.offset=0.5, .r=0, .g=255, .b=0, .a=255}, + {.offset=1.0, .r=0, .g=0, .b=255, .a=255} + }; + + Tvg_Paint *shape1 = tvg_shape_new(); + tvg_shape_append_rect(shape1, 500, 500, 100, 100, 30, 30); + Tvg_Gradient* grad1 = tvg_radial_gradient_new(); + tvg_radial_gradient_set(grad1, 550, 550, 50); + Tvg_Color_Stop color_stops1[3] = + { + {.offset=0.0, .r=0, .g=0, .b=0, .a=255}, + {.offset=0.6, .r=255, .g=0, .b=0, .a=255}, + {.offset=1.0, .r=0, .g=255, .b=255, .a=255} + }; + + tvg_gradient_color_stops(grad, color_stops, 4); + tvg_gradient_color_stops(grad1, color_stops1, 3); + tvg_shape_linear_gradient_set(shape, grad); + tvg_shape_radial_gradient_set(shape1, grad1); + tvg_canvas_push(canvas, shape); + tvg_canvas_push(canvas, shape1); tvg_canvas_draw(canvas); tvg_canvas_sync(canvas); -- 2.7.4 From 180aab13fba7b83282f6cb9dfebe2440735f1e5a Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 16 Jul 2020 13:15:58 +0900 Subject: [PATCH 05/16] spec: Add spec for rpm packaging Change-Id: I33a7d7e03549860c122eb56534f492a48784533e --- packaging/thorvg.manifest | 5 ++++ packaging/thorvg.spec | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 packaging/thorvg.manifest create mode 100644 packaging/thorvg.spec diff --git a/packaging/thorvg.manifest b/packaging/thorvg.manifest new file mode 100644 index 0000000..017d22d --- /dev/null +++ b/packaging/thorvg.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec new file mode 100644 index 0000000..e4b3736 --- /dev/null +++ b/packaging/thorvg.spec @@ -0,0 +1,64 @@ +Name: thorvg +Summary: Thor Vector Graphics Library +Version: 0.0.1 +Release: 1 +Group: Graphics System/Rendering Engine +License: Apache-2.0 +URL: https://github.com/samsung/thorvg +Source0: %{name}-%{version}.tar.gz + +BuildRequires: pkgconfig +BuildRequires: pkgconfig(glesv2) + +BuildRequires: meson +BuildRequires: ninja +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description +Thor Vector Graphics Library + + +%package devel +Summary: Thor Vector Graphics Library (devel) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + + +%description devel +Thor Vector Graphics Library (devel) + + +%prep +%setup -q + + +%build + +export DESTDIR=%{buildroot} + +meson setup \ + --prefix /usr \ + --libdir %{_libdir} \ + builddir 2>&1 +ninja \ + -C builddir \ + -j %(echo "`/usr/bin/getconf _NPROCESSORS_ONLN`") + +%install + +export DESTDIR=%{buildroot} + +ninja -C builddir install + +%files +%defattr(-,root,root,-) +%{_libdir}/libthorvg.so.* +%manifest packaging/thorvg.manifest + +%files devel +%defattr(-,root,root,-) +%{_includedir}/*.h +%{_libdir}/libthorvg.so + +%{_libdir}/pkgconfig/thorvg.pc -- 2.7.4 From 214072babeac7ea2fe514739852c1e052716c619 Mon Sep 17 00:00:00 2001 From: Michal Szczecinski Date: Fri, 31 Jul 2020 11:07:53 +0200 Subject: [PATCH 06/16] common shape: added arc implementation Change-Id: Ib483e24d8e358b2860ca8d46e8b88d58d12bdb62 --- .gitignore | 1 + inc/thorvg.h | 1 + inc/thorvg_capi.h | 1 + src/bindings/capi/tvgCapi.cpp | 6 +- src/lib/tvgShape.cpp | 72 +++++++++++++++++++++ test/makefile | 1 + test/testArc.cpp | 142 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 test/testArc.cpp diff --git a/.gitignore b/.gitignore index b796b5e..7f4d09b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ testGradientTransform testSvg testAsync testCapi +testArc diff --git a/inc/thorvg.h b/inc/thorvg.h index c738a0e..50b03fd 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -237,6 +237,7 @@ public: //Shape Result appendRect(float x, float y, float w, float h, float rx, float ry) noexcept; Result appendCircle(float cx, float cy, float rx, float ry) noexcept; + Result appendArc(float x, float y, float w, float h, float startAngle, float sweep) noexcept; Result appendPath(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) noexcept; //Stroke diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 9fa4d59..695b994 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -133,6 +133,7 @@ TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, 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_arc(Tvg_Paint* paint, float x, float y, float w, float h, float startAngle, float sweep); 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); diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 9ceb113..8ddbc07 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -178,6 +178,10 @@ TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, return (Tvg_Result) reinterpret_cast(paint)->appendRect(x, y, w, h, rx, ry); } +TVG_EXPORT Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float x, float y, float w, float h, float startAngle, float sweep) +{ + return (Tvg_Result) reinterpret_cast(paint)->appendArc(x, y, w ,h, startAngle, sweep); +} TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry) { @@ -248,4 +252,4 @@ TVG_EXPORT Tvg_Result tvg_shape_transform(Tvg_Paint* paint, const Tvg_Matrix* m) #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 59718d8..57c097a 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -17,6 +17,8 @@ #ifndef _TVG_SHAPE_CPP_ #define _TVG_SHAPE_CPP_ +#include + #include "tvgShapeImpl.h" /************************************************************************/ @@ -148,6 +150,76 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept return Result::Success; } +Result Shape::appendArc(float x, float y, float w, float h, float startAngle, float sweep) noexcept +{ + const float M_PI_HALF = M_PI / 2.0; + const float radius = w / 2; + + Point center = {x + radius, y + radius}; + + auto impl = pImpl.get(); + + startAngle = (startAngle * M_PI) / 180; + sweep = sweep * M_PI / 180; + + auto nCurves = ceil(sweep / M_PI_HALF); + auto fract = fmod(sweep, M_PI_HALF); + fract = (fract < std::numeric_limits::epsilon()) ? M_PI_HALF : fract; + + for (int i = 0; i < nCurves; ++i) { + //bezier parameters + Point start = {0, 0}; + Point end = {0, 0}; + Point bControl1 = {0, 0}; + Point bControl2 = {0, 0}; + + //variables needed to calculate bezier control points + auto ax = 0.0f, ay = 0.0f, bx = 0.0f, by = 0.0f, q1 = 0.0f, q2 = 0.0f, k2 = 0.0f; + auto endAngle = startAngle + ((i != nCurves - 1) ? M_PI_HALF : fract); + + //get bezier start and end point + start.x = radius * cos(startAngle); + start.y = radius * sin(startAngle); + end.x = radius * cos(endAngle); + end.y = radius * sin(endAngle); + + //get bezier control points using article: + //(http://itc.ktu.lt/index.php/ITC/article/view/11812/6479) + ax = start.x; + ay = start.y; + bx = end.x; + by = end.y; + + q1 = ax * ax + ay * ay; + q2 = ax * bx + ay * by + q1; + + k2 = static_cast (4.0/3.0) * ((sqrt(2 * q1 * q2) - q2) / (ax * by - ay * bx)); + + bControl1.x = ax - k2 * ay; + bControl1.y = ay + k2 * ax; + bControl2.x = bx + k2 * by; + bControl2.y = by - k2 * bx; + + //move points to proper arc center + start.x += center.x; + start.y += center.y; + end.x += center.x; + end.y += center.y; + bControl1.x += center.x; + bControl1.y += center.y; + bControl2.x += center.x; + bControl2.y += center.y; + + impl->path->moveTo(start.x, start.y); + impl->path->cubicTo(bControl1.x, bControl1.y, bControl2.x, bControl2.y, end.x, end.y); + + startAngle = endAngle; + } + + IMPL->flag |= RenderUpdateFlag::Path; + return Result::Success; +} + Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry) noexcept { diff --git a/test/makefile b/test/makefile index e1a8afb..29e6e77 100644 --- a/test/makefile +++ b/test/makefile @@ -18,4 +18,5 @@ 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 testArc testArc.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/testArc.cpp b/test/testArc.cpp new file mode 100644 index 0000000..3878aff --- /dev/null +++ b/test/testArc.cpp @@ -0,0 +1,142 @@ +#include "testCommon.h" + +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ + +void tvgDrawCmds(tvg::Canvas* canvas) +{ + if (!canvas) return; + + //draw reference rectangles + auto shape2 = tvg::Shape::gen(); + shape2->appendRect(0, 0, 200, 200, 0, 0); + shape2->stroke(255, 0, 0, 255); + shape2->stroke(2); + + auto shape3 = tvg::Shape::gen(); + shape3->moveTo(0, 100); + shape3->lineTo(200, 100); + shape3->stroke(255, 0, 0, 255); + shape3->stroke(2); + + auto shape4 = tvg::Shape::gen(); + shape4->moveTo(100, 0); + shape4->lineTo(100, 200); + shape4->stroke(255, 0, 0, 255); + shape4->stroke(2); + + //test arc + auto shape1 = tvg::Shape::gen(); + shape1->appendArc(0, 0, 200, 200, 10, 270); + shape1->stroke(255, 255, 255, 255); + shape1->stroke(3); + + //Appends Paths + if (canvas->push(move(shape2)) != tvg::Result::Success) return; + if (canvas->push(move(shape3)) != tvg::Result::Success) return; + if (canvas->push(move(shape4)) != tvg::Result::Success) return; + if (canvas->push(move(shape1)) != tvg::Result::Success) return; +} + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + +int main(int argc, char **argv) +{ + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Initialize ThorVG Engine + if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + + elm_init(argc, argv); + + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } + + elm_run(); + elm_shutdown(); + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} -- 2.7.4 From e98988da029d56f72c8d4ec82be4545e0907ea6a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 3 Aug 2020 19:58:12 +0900 Subject: [PATCH 07/16] common shape: support pie filling from arc. last argument pie=true makes arc to pie shape. Change-Id: I6f22d00fed77bf728a4ff6e5f1ca42f476ac1664 --- inc/thorvg.h | 2 +- inc/thorvg_capi.h | 2 +- src/bindings/capi/tvgCapi.cpp | 4 +-- src/lib/tvgShape.cpp | 84 +++++++++++++++++++++---------------------- test/testArc.cpp | 38 +++++++++----------- 5 files changed, 60 insertions(+), 70 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 50b03fd..d22acbb 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -237,7 +237,7 @@ public: //Shape Result appendRect(float x, float y, float w, float h, float rx, float ry) noexcept; Result appendCircle(float cx, float cy, float rx, float ry) noexcept; - Result appendArc(float x, float y, float w, float h, float startAngle, float sweep) noexcept; + Result appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept; Result appendPath(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) noexcept; //Stroke diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index b94c413..5c0428b 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -139,7 +139,7 @@ TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, 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_arc(Tvg_Paint* paint, float x, float y, float w, float h, float startAngle, float sweep); +TVG_EXPORT Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, float radius, float startAngle, float sweep, uint8_t pie); 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); diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 65eedd2..9897584 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -183,9 +183,9 @@ TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, return (Tvg_Result) reinterpret_cast(paint)->appendRect(x, y, w, h, rx, ry); } -TVG_EXPORT Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float x, float y, float w, float h, float startAngle, float sweep) +TVG_EXPORT Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, float radius, float startAngle, float sweep, uint8_t pie) { - return (Tvg_Result) reinterpret_cast(paint)->appendArc(x, y, w ,h, startAngle, sweep); + return (Tvg_Result) reinterpret_cast(paint)->appendArc(cx, cy, radius, startAngle, sweep, pie); } TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry) diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 57c097a..94f445e 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -150,73 +150,69 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept return Result::Success; } -Result Shape::appendArc(float x, float y, float w, float h, float startAngle, float sweep) noexcept +Result Shape::appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept { const float M_PI_HALF = M_PI / 2.0; - const float radius = w / 2; - - Point center = {x + radius, y + radius}; auto impl = pImpl.get(); + //just circle + if (sweep >= 360) return appendCircle(cx, cy, radius, radius); + startAngle = (startAngle * M_PI) / 180; sweep = sweep * M_PI / 180; - auto nCurves = ceil(sweep / M_PI_HALF); + auto nCurves = ceil(sweep / M_PI_HALF); auto fract = fmod(sweep, M_PI_HALF); fract = (fract < std::numeric_limits::epsilon()) ? M_PI_HALF : fract; + //Start from here + Point start = {radius * cos(startAngle), radius * sin(startAngle)}; + + if (pie) { + impl->path->moveTo(cx, cy); + impl->path->lineTo(start.x + cx, start.y + cy); + }else { + impl->path->moveTo(start.x + cx, start.y + cy); + } + for (int i = 0; i < nCurves; ++i) { - //bezier parameters - Point start = {0, 0}; - Point end = {0, 0}; - Point bControl1 = {0, 0}; - Point bControl2 = {0, 0}; - //variables needed to calculate bezier control points - auto ax = 0.0f, ay = 0.0f, bx = 0.0f, by = 0.0f, q1 = 0.0f, q2 = 0.0f, k2 = 0.0f; auto endAngle = startAngle + ((i != nCurves - 1) ? M_PI_HALF : fract); + Point end = {radius * cos(endAngle), radius * sin(endAngle)}; - //get bezier start and end point - start.x = radius * cos(startAngle); - start.y = radius * sin(startAngle); - end.x = radius * cos(endAngle); - end.y = radius * sin(endAngle); + //variables needed to calculate bezier control points //get bezier control points using article: //(http://itc.ktu.lt/index.php/ITC/article/view/11812/6479) - ax = start.x; - ay = start.y; - bx = end.x; - by = end.y; - - q1 = ax * ax + ay * ay; - q2 = ax * bx + ay * by + q1; - - k2 = static_cast (4.0/3.0) * ((sqrt(2 * q1 * q2) - q2) / (ax * by - ay * bx)); - - bControl1.x = ax - k2 * ay; - bControl1.y = ay + k2 * ax; - bControl2.x = bx + k2 * by; - bControl2.y = by - k2 * bx; - - //move points to proper arc center - start.x += center.x; - start.y += center.y; - end.x += center.x; - end.y += center.y; - bControl1.x += center.x; - bControl1.y += center.y; - bControl2.x += center.x; - bControl2.y += center.y; - - impl->path->moveTo(start.x, start.y); - impl->path->cubicTo(bControl1.x, bControl1.y, bControl2.x, bControl2.y, end.x, end.y); + auto ax = start.x; + auto ay = start.y; + auto bx = end.x; + auto by = end.y; + auto q1 = ax * ax + ay * ay; + auto q2 = ax * bx + ay * by + q1; + auto k2 = static_cast (4.0/3.0) * ((sqrt(2 * q1 * q2) - q2) / (ax * by - ay * bx)); + + start = end; //Next start point is the current end point + + end.x += cx; + end.y += cy; + + Point ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy}; + Point ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy}; + + impl->path->cubicTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y); startAngle = endAngle; } + if (pie) { + impl->path->moveTo(cx, cy); + impl->path->close(); + } + IMPL->flag |= RenderUpdateFlag::Path; + return Result::Success; } diff --git a/test/testArc.cpp b/test/testArc.cpp index 3878aff..c00f464 100644 --- a/test/testArc.cpp +++ b/test/testArc.cpp @@ -8,35 +8,29 @@ void tvgDrawCmds(tvg::Canvas* canvas) { if (!canvas) return; - //draw reference rectangles + //Arc Line + auto shape1 = tvg::Shape::gen(); + shape1->appendArc(150, 150, 100, 10, 270, false); + shape1->stroke(255, 255, 255, 255); + shape1->stroke(2); + if (canvas->push(move(shape1)) != tvg::Result::Success) return; + auto shape2 = tvg::Shape::gen(); - shape2->appendRect(0, 0, 200, 200, 0, 0); - shape2->stroke(255, 0, 0, 255); + shape2->appendArc(500, 150, 125, 0, 300, true); + shape2->stroke(255, 255, 255, 255); shape2->stroke(2); + if (canvas->push(move(shape2)) != tvg::Result::Success) return; + //Pie Fill auto shape3 = tvg::Shape::gen(); - shape3->moveTo(0, 100); - shape3->lineTo(200, 100); - shape3->stroke(255, 0, 0, 255); - shape3->stroke(2); + shape3->appendArc(150, 500, 100, 0, 75, true); + shape3->fill(255, 255, 255, 255); + if (canvas->push(move(shape3)) != tvg::Result::Success) return; auto shape4 = tvg::Shape::gen(); - shape4->moveTo(100, 0); - shape4->lineTo(100, 200); - shape4->stroke(255, 0, 0, 255); - shape4->stroke(2); - - //test arc - auto shape1 = tvg::Shape::gen(); - shape1->appendArc(0, 0, 200, 200, 10, 270); - shape1->stroke(255, 255, 255, 255); - shape1->stroke(3); - - //Appends Paths - if (canvas->push(move(shape2)) != tvg::Result::Success) return; - if (canvas->push(move(shape3)) != tvg::Result::Success) return; + shape4->appendArc(500, 500, 150, 0, 215, true); + shape4->fill(255, 255, 255, 255); if (canvas->push(move(shape4)) != tvg::Result::Success) return; - if (canvas->push(move(shape1)) != tvg::Result::Success) return; } /************************************************************************/ -- 2.7.4 From 7106272d97e1b3f653e54e3c9fc307020b860cb0 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 3 Aug 2020 20:06:02 +0900 Subject: [PATCH 08/16] common: code refactoring. return as soon as possible. Change-Id: If48e13e8976bc1692dadd9054b484bf7cd811917 --- src/lib/tvgShape.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 94f445e..53c7689 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -152,13 +152,13 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept Result Shape::appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept { - const float M_PI_HALF = M_PI / 2.0; - - auto impl = pImpl.get(); + const float M_PI_HALF = M_PI * 0.5f; //just circle if (sweep >= 360) return appendCircle(cx, cy, radius, radius); + auto impl = pImpl.get(); + startAngle = (startAngle * M_PI) / 180; sweep = sweep * M_PI / 180; -- 2.7.4 From 05757ec07cf0b050ffbd4d528fdb76ccbf92995c Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 4 Aug 2020 09:37:08 +0900 Subject: [PATCH 09/16] capi: revise some common paint interfaces and added picture stuff. Change-Id: I9850cbead5ce1ab172f284738fe8456cd19dc3f9 --- inc/thorvg_capi.h | 22 ++++++++++--- src/bindings/capi/tvgCapi.cpp | 72 +++++++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 5c0428b..ecd7ee6 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -128,10 +128,19 @@ TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas); /************************************************************************/ +/* Paint API */ +/************************************************************************/ +TVG_EXPORT Tvg_Result tvg_paint_del(Tvg_Paint* paint); +TVG_EXPORT Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor); +TVG_EXPORT Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree); +TVG_EXPORT Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y); +TVG_EXPORT Tvg_Result tvg_paint_transform(Tvg_Paint* paint, const Tvg_Matrix* m); + + +/************************************************************************/ /* 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); 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); @@ -147,10 +156,6 @@ TVG_EXPORT Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* d 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); -TVG_EXPORT Tvg_Result tvg_shape_scale(Tvg_Paint* paint, float factor); -TVG_EXPORT Tvg_Result tvg_shape_rotate(Tvg_Paint* paint, float degree); -TVG_EXPORT Tvg_Result tvg_shape_translate(Tvg_Paint* paint, float x, float y); -TVG_EXPORT Tvg_Result tvg_shape_transform(Tvg_Paint* paint, const Tvg_Matrix* m); TVG_EXPORT Tvg_Result tvg_shape_linear_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad); TVG_EXPORT Tvg_Result tvg_shape_radial_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad); @@ -166,6 +171,13 @@ TVG_EXPORT Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, floa TVG_EXPORT Tvg_Result tvg_gradient_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt); +/************************************************************************/ +/* Picture API */ +/************************************************************************/ +TVG_EXPORT Tvg_Paint* tvg_picture_new(); +TVG_EXPORT Tvg_Result tvg_picture_load(Tvg_Paint* paint, const char* path); +TVG_EXPORT Tvg_Result tvg_picture_get_viewbox(Tvg_Paint* paint, float* x, float* y, float* w, float* h); + #ifdef __cplusplus } #endif diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 9897584..9f9646e 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -132,19 +132,47 @@ TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas) /************************************************************************/ -/* Shape API */ +/* Paint API */ /************************************************************************/ -TVG_EXPORT Tvg_Paint* tvg_shape_new() +TVG_EXPORT Tvg_Result tvg_paint_del(Tvg_Paint* paint) { - return (Tvg_Paint*) Shape::gen().release(); + delete(paint); + return TVG_RESULT_SUCCESS; } -TVG_EXPORT Tvg_Result tvg_shape_del(Tvg_Paint* paint) +TVG_EXPORT Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor) { - delete(paint); - return TVG_RESULT_SUCCESS; + return (Tvg_Result) reinterpret_cast(paint)->scale(factor); +} + + +TVG_EXPORT Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree) +{ + return (Tvg_Result) reinterpret_cast(paint)->rotate(degree); +} + + +TVG_EXPORT Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y) +{ + return (Tvg_Result) reinterpret_cast(paint)->translate(x, y); +} + + +TVG_EXPORT Tvg_Result tvg_paint_transform(Tvg_Paint* paint, const Tvg_Matrix* m) +{ + return (Tvg_Result) reinterpret_cast(paint)->transform(*(reinterpret_cast(m))); +} + + +/************************************************************************/ +/* Shape API */ +/************************************************************************/ + +TVG_EXPORT Tvg_Paint* tvg_shape_new() +{ + return (Tvg_Paint*) Shape::gen().release(); } @@ -235,34 +263,38 @@ TVG_EXPORT Tvg_Result tvg_shape_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t return (Tvg_Result) reinterpret_cast(paint)->fill(r, g, b, a); } -TVG_EXPORT Tvg_Result tvg_shape_scale(Tvg_Paint* paint, float factor) -{ - return (Tvg_Result) reinterpret_cast(paint)->scale(factor); -} -TVG_EXPORT Tvg_Result tvg_shape_rotate(Tvg_Paint* paint, float degree) +TVG_EXPORT Tvg_Result tvg_shape_linear_gradient_set(Tvg_Paint* paint, Tvg_Gradient *gradient) { - return (Tvg_Result) reinterpret_cast(paint)->rotate(degree); + return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((LinearGradient*)(gradient))); } -TVG_EXPORT Tvg_Result tvg_shape_translate(Tvg_Paint* paint, float x, float y) + +TVG_EXPORT Tvg_Result tvg_shape_radial_gradient_set(Tvg_Paint* paint, Tvg_Gradient *gradient) { - return (Tvg_Result) reinterpret_cast(paint)->translate(x, y); + return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((RadialGradient*)(gradient))); } -TVG_EXPORT Tvg_Result tvg_shape_transform(Tvg_Paint* paint, const Tvg_Matrix* m) + +/************************************************************************/ +/* Picture API */ +/************************************************************************/ + +TVG_EXPORT Tvg_Paint* tvg_picture_new() { - return (Tvg_Result) reinterpret_cast(paint)->transform(*(reinterpret_cast(m))); + return (Tvg_Paint*) Picture::gen().release(); } -TVG_EXPORT Tvg_Result tvg_shape_linear_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad) + +TVG_EXPORT Tvg_Result tvg_picture_load(Tvg_Paint* paint, const char* path) { - return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((LinearGradient*)(grad))); + return (Tvg_Result) reinterpret_cast(paint)->load(path); } -TVG_EXPORT Tvg_Result tvg_shape_radial_gradient_set(Tvg_Paint* paint, Tvg_Gradient *grad) + +TVG_EXPORT Tvg_Result tvg_picture_get_viewbox(Tvg_Paint* paint, float* x, float* y, float* w, float* h) { - return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((RadialGradient*)(grad))); + return (Tvg_Result) reinterpret_cast(paint)->viewbox(x, y, w, h); } -- 2.7.4 From cfbd419fbd717693be8c67eeaf7063b76f7cdf18 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 4 Aug 2020 09:57:37 +0900 Subject: [PATCH 10/16] test arc: revise sample code. Change-Id: I3629befdf5ce74ae7822929a059b4c95f2a9e88e --- test/testArc.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/test/testArc.cpp b/test/testArc.cpp index c00f464..b02196e 100644 --- a/test/testArc.cpp +++ b/test/testArc.cpp @@ -10,27 +10,63 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Arc Line auto shape1 = tvg::Shape::gen(); - shape1->appendArc(150, 150, 100, 10, 270, false); + shape1->appendArc(150, 150, 80, 10, 180, false); shape1->stroke(255, 255, 255, 255); shape1->stroke(2); if (canvas->push(move(shape1)) != tvg::Result::Success) return; auto shape2 = tvg::Shape::gen(); - shape2->appendArc(500, 150, 125, 0, 300, true); + shape2->appendArc(400, 150, 80, 0, 300, false); shape2->stroke(255, 255, 255, 255); shape2->stroke(2); if (canvas->push(move(shape2)) != tvg::Result::Success) return; - //Pie Fill auto shape3 = tvg::Shape::gen(); - shape3->appendArc(150, 500, 100, 0, 75, true); - shape3->fill(255, 255, 255, 255); + shape3->appendArc(600, 150, 80, 300, 60, false); + shape3->stroke(255, 255, 255, 255); + shape3->stroke(2); if (canvas->push(move(shape3)) != tvg::Result::Success) return; + //Pie Line auto shape4 = tvg::Shape::gen(); - shape4->appendArc(500, 500, 150, 0, 215, true); - shape4->fill(255, 255, 255, 255); + shape4->appendArc(150, 400, 80, 10, 180, true); + shape4->stroke(255, 255, 255, 255); + shape4->stroke(2); if (canvas->push(move(shape4)) != tvg::Result::Success) return; + + auto shape5 = tvg::Shape::gen(); + shape5->appendArc(400, 400, 80, 0, 300, true); + shape5->stroke(255, 255, 255, 255); + shape5->stroke(2); + if (canvas->push(move(shape5)) != tvg::Result::Success) return; + + auto shape6 = tvg::Shape::gen(); + shape6->appendArc(600, 400, 80, 300, 60, true); + shape6->stroke(255, 255, 255, 255); + shape6->stroke(2); + if (canvas->push(move(shape6)) != tvg::Result::Success) return; + + //Pie Fill + auto shape7 = tvg::Shape::gen(); + shape7->appendArc(150, 650, 80, 10, 180, true); + shape7->fill(255, 255, 255, 255); + shape7->stroke(255, 0, 0, 255); + shape7->stroke(2); + if (canvas->push(move(shape7)) != tvg::Result::Success) return; + + auto shape8 = tvg::Shape::gen(); + shape8->appendArc(400, 650, 80, 0, 300, true); + shape8->fill(255, 255, 255, 255); + shape8->stroke(255, 0, 0, 255); + shape8->stroke(2); + if (canvas->push(move(shape8)) != tvg::Result::Success) return; + + auto shape9 = tvg::Shape::gen(); + shape9->appendArc(600, 650, 80, 300, 60, true); + shape9->fill(255, 255, 255, 255); + shape9->stroke(255, 0, 0, 255); + shape9->stroke(2); + if (canvas->push(move(shape9)) != tvg::Result::Success) return; } /************************************************************************/ -- 2.7.4 From 9979e2cbf7cc8811c167ae6e0fd85e2a31e8c7f6 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 5 Aug 2020 20:08:27 +0900 Subject: [PATCH 11/16] updated README prepare for github system. Change-Id: I0ee45e3ccb56f25f0252aad91a48151d62f9ed02 --- README | 7 ------- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index 31d0cbd..0000000 --- a/README +++ /dev/null @@ -1,7 +0,0 @@ -Thor Vector Graphics 0.1.0 - -****************************************************************************** - - FOR ANY ISSUES PLEASE EMAIL: - -****************************************************************************** diff --git a/README.md b/README.md new file mode 100644 index 0000000..aac7ad0 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# ThorVG + +ThorVG is a platform independent standalone C++ library for drawing vector-based shapes and SVG. + +# +## Contents +- [Building ThorVG](#building-thorvg) + - [Meson Build](#meson-build) +- [Quick Start](#quick-start) +- [Issues or Feature Requests?](#issues-or-feature-requests) +# +## Building ThorVG +thorvg supports [meson](https://mesonbuild.com/) build system. +# +### Meson Build +install [meson](http://mesonbuild.com/Getting-meson.html) and [ninja](https://ninja-build.org/) if not already installed. + +Run meson to configure ThorVG. +``` +meson build +``` +Run ninja to build & install ThorVG. +``` +ninja -C build install +``` +[Back to contents](#contents) +# +## Quick Start +ThorVG renders vector shapes on a given canvas buffer. + +You can initialize ThorVG engine first: +```cpp +tvg::Initializer::init(tvg::CanvasEngine::Sw); +``` +You can prepare a empty canvas for drawing on it. +```cpp +static uint32_t buffer[WIDTH * HEIGHT]; //canvas target buffer + +auto canvas = tvg::SwCanvas::gen(); //generate a canvas +canvas->target(buffer, WIDTH, WIDTH, HEIGHT); //stride, w, h +``` + +Next you can draw shapes onto the canvas. +```cpp +auto shape = tvg::Shape::gen(); //generate a shape +shape->appendRect(0, 0, 200, 200, 0, 0); //x, y, w, h, rx, ry +shape->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH +shape->fill(255, 255, 0, 255); //r, g, b, a + +canvas->push(move(shape)); //push shape drawing command +``` +Begin rendering & finish it at a particular time. +```cpp +canvas->draw(); +canvas->sync(); +``` +Lastly, you can acquire the rendered image in buffer memory. + +[Back to contents](#contents) +# +## Issues or Feature Requests? +For immidiate assistant or support please reach us in [Gitter](https://gitter.im/thorvg-dev/community#) -- 2.7.4 From 9f6b5eb59edb623e9909e8994255b86509ec61fc Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 6 Aug 2020 13:53:00 +0900 Subject: [PATCH 12/16] common: changed premultiplied color policy. Some user have no idea of premultiplied alpha concept, We suggest more user-friendly interfaces so that they don't confuse it. Now, this pre-multipying is acommplished by backend engines. Change-Id: Ifd84d56361cb56a8b98240bbd16690accf370bad --- src/lib/sw_engine/tvgSwCommon.h | 9 ++++++++- src/lib/sw_engine/tvgSwFill.cpp | 13 +++++++++++-- src/lib/sw_engine/tvgSwRaster.cpp | 8 ++++++++ test/testBlending.cpp | 6 +++--- test/testSceneTransform.cpp | 4 ++-- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 469ce0f..b653a93 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -244,6 +244,12 @@ static inline uint32_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t } +static inline uint8_t COLOR_ALPHA_MULTIPLY(uint32_t c, uint32_t a) +{ + return (c * a) >> 8; +} + + 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); @@ -290,7 +296,8 @@ 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) + +static 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; diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 266acaa..80540cc 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -46,7 +46,11 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata) if (pColors->a < 255) fill->translucent = true; - auto rgba = COLOR_ARGB_JOIN(pColors->r, pColors->g, pColors->b, pColors->a); + auto r = COLOR_ALPHA_MULTIPLY(pColors->r, pColors->a); + auto g = COLOR_ALPHA_MULTIPLY(pColors->g, pColors->a); + auto b = COLOR_ALPHA_MULTIPLY(pColors->b, pColors->a); + + auto rgba = COLOR_ARGB_JOIN(r, g, b, pColors->a); auto inc = 1.0f / static_cast(GRADIENT_STOP_SIZE); auto pos = 1.5f * inc; uint32_t i = 0; @@ -65,7 +69,12 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata) assert(curr && next); auto delta = 1.0f / (next->offset - curr->offset); if (next->a < 255) fill->translucent = true; - auto rgba2 = COLOR_ARGB_JOIN(next->r, next->g, next->b, next->a); + + auto r = COLOR_ALPHA_MULTIPLY(next->r, next->a); + auto g = COLOR_ALPHA_MULTIPLY(next->g, next->a); + auto b = COLOR_ALPHA_MULTIPLY(next->b, next->a); + + auto rgba2 = COLOR_ARGB_JOIN(r, g, b, next->a); while (pos < next->offset && i < GRADIENT_STOP_SIZE) { auto t = (pos - curr->offset) * delta; diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 5819bb8..ce2dc15 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -285,6 +285,10 @@ bool rasterGradientShape(Surface& surface, SwShape& shape, unsigned id) bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + r = COLOR_ALPHA_MULTIPLY(r, a); + g = COLOR_ALPHA_MULTIPLY(g, a); + b = COLOR_ALPHA_MULTIPLY(b, a); + //Fast Track if (shape.rect) { auto region = _clipRegion(surface, shape.bbox); @@ -300,6 +304,10 @@ 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) { + r = COLOR_ALPHA_MULTIPLY(r, a); + g = COLOR_ALPHA_MULTIPLY(g, a); + b = COLOR_ALPHA_MULTIPLY(b, a); + if (a == 255) return _rasterSolidRle(surface, shape.strokeRle, COLOR_ARGB_JOIN(r, g, b, a)); return _rasterTranslucentRle(surface, shape.strokeRle, COLOR_ARGB_JOIN(r, g, b, a)); } diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 5477b3b..59a4fad 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -19,13 +19,13 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Circle auto shape2 = tvg::Shape::gen(); shape2->appendCircle(400, 400, 200, 200); //cx, cy, radiusW, radiusH - shape2->fill(170, 170, 0, 170); //r, g, b, a + shape2->fill(255, 255, 0, 170); //r, g, b, a if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Ellipse auto shape3 = tvg::Shape::gen(); shape3->appendCircle(400, 400, 250, 100); //cx, cy, radiusW, radiusH - shape3->fill(100, 100, 100, 100); //r, g, b, a + shape3->fill(255, 255, 255, 100); //r, g, b, a if (canvas->push(move(shape3)) != tvg::Result::Success) return; //Prepare Star @@ -41,7 +41,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape4->lineTo(26, 361); shape4->lineTo(146, 343); shape4->close(); - shape4->fill(200, 0, 200, 200); + shape4->fill(255, 0, 200, 200); if (canvas->push(move(shape4)) != tvg::Result::Success) return; //Prepare Opaque Ellipse diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 0d0be8e..49558fb 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -58,7 +58,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape4->lineTo(-173, 12.5); shape4->lineTo(-53, -5.5); shape4->close(); - shape4->fill(0, 0, 127, 127); + shape4->fill(0, 0, 255, 127); shape4->stroke(3); //width shape4->stroke(0, 0, 255, 255); //r, g, b, a scene2->push(move(shape4)); @@ -78,7 +78,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape5->cubicTo(cx - halfRadius, cy + radius, cx - radius, cy + halfRadius, cx - radius, cy); shape5->cubicTo(cx - radius, cy - halfRadius, cx - halfRadius, cy - radius, cx, cy - radius); shape5->close(); - shape5->fill(127, 0, 0, 127); + shape5->fill(255, 0, 0, 127); scene2->push(move(shape5)); scene2->translate(500, 350); -- 2.7.4 From 28ae7a44114084fd1cd5df42edad6c1af7c9f7b3 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 6 Aug 2020 14:19:50 +0900 Subject: [PATCH 13/16] svg_loader: code refactoring remove macro code that does not helpful. This just decrease readibility and increase LOC. Change-Id: I9f1b11318447b45a9f96e7b00c18141fd9e71f9a --- src/loaders/svg_loader/tvgSvgLoader.cpp | 59 ++++++++++----------------------- 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 9d58792..36eac07 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -1004,12 +1004,6 @@ static SvgNode* _createPathNode(SvgLoaderData* loader, SvgNode* parent, const ch } -#define CIRCLE_DEF(Name, Field, Type) \ - { \ -#Name, Type, sizeof(#Name), offsetof(SvgCircleNode, Field) \ - } - - static constexpr struct { const char* tag; @@ -1017,9 +1011,9 @@ static constexpr struct int sz; size_t offset; } circleTags[] = { - CIRCLE_DEF(cx, cx, SvgParserLengthType::Horizontal), - CIRCLE_DEF(cy, cy, SvgParserLengthType::Vertical), - CIRCLE_DEF(r, r, SvgParserLengthType::Other) + {"cx", SvgParserLengthType::Horizontal, sizeof("cx"), offsetof(SvgCircleNode, cx)}, + {"cy", SvgParserLengthType::Vertical, sizeof("cy"), offsetof(SvgCircleNode, cy)}, + {"r", SvgParserLengthType::Other, sizeof("r"), offsetof(SvgCircleNode, r)} }; @@ -1063,12 +1057,6 @@ static SvgNode* _createCircleNode(SvgLoaderData* loader, SvgNode* parent, const } -#define ELLIPSE_DEF(Name, Field, Type) \ - { \ -#Name, Type, sizeof(#Name), offsetof(SvgEllipseNode, Field) \ - } - - static constexpr struct { const char* tag; @@ -1076,10 +1064,10 @@ static constexpr struct int sz; size_t offset; } ellipseTags[] = { - ELLIPSE_DEF(cx, cx, SvgParserLengthType::Horizontal), - ELLIPSE_DEF(cy, cy, SvgParserLengthType::Vertical), - ELLIPSE_DEF(rx, rx, SvgParserLengthType::Horizontal), - ELLIPSE_DEF(ry, ry, SvgParserLengthType::Vertical) + {"cx", SvgParserLengthType::Horizontal, sizeof("cx"), offsetof(SvgEllipseNode, cx)}, + {"cy", SvgParserLengthType::Vertical, sizeof("cy"), offsetof(SvgEllipseNode, cy)}, + {"rx", SvgParserLengthType::Horizontal, sizeof("rx"), offsetof(SvgEllipseNode, rx)}, + {"ry", SvgParserLengthType::Vertical, sizeof("ry"), offsetof(SvgEllipseNode, ry)} }; @@ -1202,13 +1190,6 @@ static SvgNode* _createPolylineNode(SvgLoaderData* loader, SvgNode* parent, cons return loader->svgParse->node; } - -#define RECT_DEF(Name, Field, Type) \ - { \ -#Name, Type, sizeof(#Name), offsetof(SvgRectNode, Field) \ - } - - static constexpr struct { const char* tag; @@ -1216,12 +1197,12 @@ static constexpr struct int sz; size_t offset; } rectTags[] = { - RECT_DEF(x, x, SvgParserLengthType::Horizontal), - RECT_DEF(y, y, SvgParserLengthType::Vertical), - RECT_DEF(width, w, SvgParserLengthType::Horizontal), - RECT_DEF(height, h, SvgParserLengthType::Vertical), - RECT_DEF(rx, rx, SvgParserLengthType::Horizontal), - RECT_DEF(ry, ry, SvgParserLengthType::Vertical) + {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgRectNode, x)}, + {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgRectNode, y)}, + {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgRectNode, w)}, + {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgRectNode, h)}, + {"rx", SvgParserLengthType::Horizontal, sizeof("rx"), offsetof(SvgRectNode, rx)}, + {"ry", SvgParserLengthType::Vertical, sizeof("ry"), offsetof(SvgRectNode, ry)} }; @@ -1271,12 +1252,6 @@ static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const ch } -#define LINE_DEF(Name, Field, Type) \ - { \ -#Name, Type, sizeof(#Name), offsetof(SvgLineNode, Field) \ - } - - static constexpr struct { const char* tag; @@ -1284,10 +1259,10 @@ static constexpr struct int sz; size_t offset; } lineTags[] = { - LINE_DEF(x1, x1, SvgParserLengthType::Horizontal), - LINE_DEF(y1, y1, SvgParserLengthType::Vertical), - LINE_DEF(x2, x2, SvgParserLengthType::Horizontal), - LINE_DEF(y2, y2, SvgParserLengthType::Vertical) + {"x1", SvgParserLengthType::Horizontal, sizeof("x1"), offsetof(SvgLineNode, x1)}, + {"y1", SvgParserLengthType::Vertical, sizeof("y1"), offsetof(SvgLineNode, y1)}, + {"x2", SvgParserLengthType::Horizontal, sizeof("x2"), offsetof(SvgLineNode, x2)}, + {"y2", SvgParserLengthType::Vertical, sizeof("y2"), offsetof(SvgLineNode, y2)} }; -- 2.7.4 From 4f0561697a16f3f0f893bcc8035a5fe257a7febd Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Thu, 6 Aug 2020 14:31:08 +0900 Subject: [PATCH 14/16] svg_loader: fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch is solving following build error. error: ‘offsetof’ was not declared in this scope Depending on build environment, this error could happen. Change-Id: I3512bb205f79a4d893cf33266db0a9109c0df886 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 36eac07..8851f02 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -17,6 +17,7 @@ #ifndef _TVG_SVG_LOADER_CPP_ #define _TVG_SVG_LOADER_CPP_ +#include #include "tvgSvgLoader.h" #include -- 2.7.4 From 892f729265ca4125700299da7d432d1f42891635 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 6 Aug 2020 14:35:56 +0900 Subject: [PATCH 15/16] svg_loader: code refactoring. ++neat Change-Id: I3b5552a2bbf09571ba01f0e31569b553913f400d --- 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 8851f02..c8fd79d 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -18,8 +18,8 @@ #define _TVG_SVG_LOADER_CPP_ #include -#include "tvgSvgLoader.h" #include +#include "tvgSvgLoader.h" /************************************************************************/ -- 2.7.4 From ad48f7d8ba8576970a8736f7e1ce8807fd4d6b6a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 6 Aug 2020 16:24:24 +0900 Subject: [PATCH 16/16] common: fix compile warnings. --Werror=unused-parameter Change-Id: I180464d770b1aa04afd39c30a3223a7cd48c78a4 --- src/lib/tvgCommon.h | 2 ++ src/lib/tvgRender.h | 6 +++--- src/meson.build | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index dddac62..87c7581 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -35,6 +35,8 @@ using namespace tvg; #define FILL_ID_LINEAR 0 #define FILL_ID_RADIAL 1 +#define TVG_UNUSED __attribute__ ((__unused__)) + #include "tvgBezier.h" #include "tvgLoader.h" #include "tvgLoaderMgr.h" diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 6a0897e..63f920e 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -51,10 +51,10 @@ class RenderMethod { public: virtual ~RenderMethod() {} - 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 void* prepare(TVG_UNUSED const Shape& shape, TVG_UNUSED void* data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; } + virtual bool dispose(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return false; } virtual bool preRender() { return false; } - virtual bool render(const Shape& shape, void *data) { return false; } + virtual bool render(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return false; } virtual bool postRender() { return false; } virtual bool clear() { return false; } virtual bool flush() { return false; } diff --git a/src/meson.build b/src/meson.build index ced59a5..40d85ce 100644 --- a/src/meson.build +++ b/src/meson.build @@ -12,7 +12,6 @@ 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, binding_dep, thread_dep] -- 2.7.4