From 275c2f9d7901bbf5d44e1fa2cf3a4fce32f2fc8f Mon Sep 17 00:00:00 2001 From: Subhransu Mohanty Date: Thu, 13 Aug 2020 13:01:53 +0900 Subject: [PATCH 01/16] tvg: added task support that runs on a threadpool. this patch adds an async() function that takes a shared_task and runs asyncronously in a threadpool. Change-Id: I02a47df6938656828f924fbf5e2bc075073b329b --- src/lib/meson.build | 1 + src/lib/tvgTask.cpp | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/tvgTask.h | 72 ++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 src/lib/tvgTask.cpp create mode 100644 src/lib/tvgTask.h diff --git a/src/lib/meson.build b/src/lib/meson.build index 631016d..503c35e 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -35,6 +35,7 @@ source_file = [ 'tvgScene.cpp', 'tvgShape.cpp', 'tvgSwCanvas.cpp', + 'tvgTask.cpp', ] common_dep = declare_dependency( diff --git a/src/lib/tvgTask.cpp b/src/lib/tvgTask.cpp new file mode 100644 index 0000000..81ce22e --- /dev/null +++ b/src/lib/tvgTask.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +template +class TaskQueue { + using lock_t = std::unique_lock; + std::deque _q; + bool _done{false}; + std::mutex _mutex; + std::condition_variable _ready; + +public: + bool try_pop(Task &task) + { + lock_t lock{_mutex, std::try_to_lock}; + if (!lock || _q.empty()) return false; + task = std::move(_q.front()); + _q.pop_front(); + return true; + } + + bool try_push(Task &&task) + { + { + lock_t lock{_mutex, std::try_to_lock}; + if (!lock) return false; + _q.push_back(std::move(task)); + } + _ready.notify_one(); + return true; + } + + void done() + { + { + lock_t lock{_mutex}; + _done = true; + } + _ready.notify_all(); + } + + bool pop(Task &task) + { + lock_t lock{_mutex}; + while (_q.empty() && !_done) _ready.wait(lock); + if (_q.empty()) return false; + task = std::move(_q.front()); + _q.pop_front(); + return true; + } + + void push(Task &&task) + { + { + lock_t lock{_mutex}; + _q.push_back(std::move(task)); + } + _ready.notify_one(); + } + +}; + +#include +#include + +namespace tvg +{ + +class Executor +{ + const unsigned _count{std::thread::hardware_concurrency()}; + std::vector _threads; + std::vector> _q{_count}; + std::atomic _index{0}; + void run(unsigned i) + { + // Task Loop + shared_task task; + while (true) { + bool success = false; + + for (unsigned n = 0; n != _count * 2; ++n) { + if (_q[(i + n) % _count].try_pop(task)) { + success = true; + break; + } + } + + if (!success && !_q[i].pop(task)) break; + + (*task)(); + } + } + + Executor() + { + for (unsigned n = 0; n != _count; ++n) { + _threads.emplace_back([&, n] { run(n); }); + } + } + ~Executor() + { + for (auto &e : _q) e.done(); + + for (auto &e : _threads) e.join(); + } + +public: + + static Executor& instance() { + static Executor singleton; + return singleton; + } + + void post(shared_task task) + { + task->prepare(); + + auto i = _index++; + + for (unsigned n = 0; n != _count; ++n) { + if (_q[(i + n) % _count].try_push(std::move(task))) return; + } + + if (_count > 0) { + _q[i % _count].push(std::move(task)); + } + } +}; + +void async(shared_task task) +{ + Executor::instance().post(std::move(task)); +} + +} + + diff --git a/src/lib/tvgTask.h b/src/lib/tvgTask.h new file mode 100644 index 0000000..9fb250e --- /dev/null +++ b/src/lib/tvgTask.h @@ -0,0 +1,72 @@ +/* + * 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_TASK_H_ +#define _TVG_TASK_H_ + +#include +#include + +namespace tvg +{ + +/* + Task Interface. + Able to run a task in the thread pool. derive from the + task interface and implement run method. + + To get the result call task->get() which will return immidiately if the + task is already finishd otherwise will wait till task completion. + */ + +class Task +{ +public: + virtual ~Task() = default; + void get() { if (_receiver.valid()) _receiver.get(); } + +protected: + virtual void run() = 0; +private: + void operator()() + { + run(); + _sender.set_value(); + } + void prepare() + { + _sender = std::promise(); + _receiver = _sender.get_future(); + } + friend class Executor; + + std::promise _sender; + std::future _receiver; +}; + + +using shared_task = std::shared_ptr; + +/* + async() function takes a shared task and runs it in + a thread pool asyncronously. call get() on the shared_task + to get the ressult out of the shared_task. + */ +void async(shared_task task); + +} + +#endif //_TVG_TASK_H_ \ No newline at end of file -- 2.7.4 From 72891162274dba579be585034140663193fab897 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 20:39:34 +0900 Subject: [PATCH 02/16] remove std async usage. we can't control any threads count that could drop the performance. remove async() and will come back with fine-tuned threading-pool. Change-Id: I17c39792234acfce6db334abc0ce12da23978a9a --- src/lib/sw_engine/tvgSwCommon.h | 38 +++---- src/lib/sw_engine/tvgSwRaster.cpp | 30 ++--- src/lib/sw_engine/tvgSwRenderer.cpp | 188 +++++++++----------------------- src/lib/sw_engine/tvgSwRenderer.h | 12 -- src/lib/sw_engine/tvgSwShape.cpp | 105 +++++++++--------- src/lib/sw_engine/tvgSwStroke.cpp | 48 ++++---- src/lib/tvgRender.h | 12 +- src/loaders/svg_loader/tvgSvgLoader.cpp | 54 +++++---- src/loaders/svg_loader/tvgSvgLoader.h | 3 +- 9 files changed, 197 insertions(+), 293 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index e7566c1..295f11a 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -269,22 +269,22 @@ SwFixed mathLength(SwPoint& pt); bool mathSmallCubic(SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut); SwFixed mathMean(SwFixed angle1, SwFixed angle2); -void shapeReset(SwShape& shape); -bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform); -bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); -bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, bool antiAlias); -void shapeDelOutline(SwShape& shape); -void shapeResetStroke(SwShape& shape, const Shape* sdata, const Matrix* transform); -bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transform, const SwSize& clip); -void shapeFree(SwShape& shape); -void shapeDelStroke(SwShape& shape); -bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transform, bool ctable); -void shapeResetFill(SwShape& shape); -void shapeDelFill(SwShape& shape); - -void strokeReset(SwStroke& stroke, const Shape* shape, const Matrix* transform); -bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline); -SwOutline* strokeExportOutline(SwStroke& stroke); +void shapeReset(SwShape* shape); +bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform); +bool shapePrepare(SwShape* shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); +bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias); +void shapeDelOutline(SwShape* shape); +void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform); +bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip); +void shapeFree(SwShape* shape); +void shapeDelStroke(SwShape* shape); +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, bool ctable); +void shapeResetFill(SwShape* shape); +void shapeDelFill(SwShape* shape); + +void strokeReset(SwStroke* stroke, const Shape* shape, const Matrix* transform); +bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); +SwOutline* strokeExportOutline(SwStroke* stroke); void strokeFree(SwStroke* stroke); bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable); @@ -296,9 +296,9 @@ void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias); void rleFree(SwRleData* rle); -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); -bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +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); +bool rasterStroke(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterClear(Surface& surface); diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 98579c5..46ef4ac 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -273,48 +273,48 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF /* External Class Implementation */ /************************************************************************/ -bool rasterGradientShape(Surface& surface, SwShape& shape, unsigned id) +bool rasterGradientShape(Surface& surface, SwShape* shape, unsigned id) { //Fast Track - if (shape.rect) { - auto region = _clipRegion(surface, shape.bbox); - if (id == FILL_ID_LINEAR) return _rasterLinearGradientRect(surface, region, shape.fill); - return _rasterRadialGradientRect(surface, region, shape.fill); + if (shape->rect) { + auto region = _clipRegion(surface, shape->bbox); + if (id == FILL_ID_LINEAR) return _rasterLinearGradientRect(surface, region, shape->fill); + return _rasterRadialGradientRect(surface, region, shape->fill); } else { - if (id == FILL_ID_LINEAR) return _rasterLinearGradientRle(surface, shape.rle, shape.fill); - return _rasterRadialGradientRle(surface, shape.rle, shape.fill); + if (id == FILL_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->rle, shape->fill); + return _rasterRadialGradientRle(surface, shape->rle, shape->fill); } return false; } -bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +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); + if (shape->rect) { + auto region = _clipRegion(surface, shape->bbox); if (a == 255) return _rasterSolidRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a)); return _rasterTranslucentRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a)); } else{ - if (a == 255) return _rasterSolidRle(surface, shape.rle, COLOR_ARGB_JOIN(r, g, b, a)); - return _rasterTranslucentRle(surface, shape.rle, COLOR_ARGB_JOIN(r, g, b, a)); + if (a == 255) return _rasterSolidRle(surface, shape->rle, COLOR_ARGB_JOIN(r, g, b, a)); + return _rasterTranslucentRle(surface, shape->rle, COLOR_ARGB_JOIN(r, g, b, a)); } return false; } -bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +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)); + 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/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 92fddfb..eb2f199 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -22,27 +22,12 @@ #ifndef _TVG_SW_RENDERER_CPP_ #define _TVG_SW_RENDERER_CPP_ -using namespace std; - #include "tvgSwCommon.h" #include "tvgSwRenderer.h" - /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ -namespace tvg { - struct SwTask - { - SwShape shape; - const Shape* sdata; - SwSize clip; - Matrix* transform; - RenderUpdateFlag flags; - future progress; - }; -} - static RenderInitializer renderInit; @@ -52,13 +37,6 @@ static RenderInitializer renderInit; SwRenderer::~SwRenderer() { - flush(); -} - - -bool SwRenderer::clear() -{ - return flush(); } @@ -77,66 +55,25 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t bool SwRenderer::preRender() { - //before we start rendering, we should finish all preparing tasks - while (prepareTasks.size() > 0) { - auto task = prepareTasks.front(); - if (task->progress.valid()) task->progress.get(); - prepareTasks.pop(); - renderTasks.push(task); - } - return true; -} - - -bool SwRenderer::postRender() -{ - auto asyncTask = [](SwRenderer* renderer) { - renderer->doRender(); - }; - - progress = async(launch::async, asyncTask, this); - - return true; + return rasterClear(surface); } -void SwRenderer::doRender() +bool SwRenderer::render(const Shape& sdata, TVG_UNUSED void *data) { - rasterClear(surface); - - while (renderTasks.size() > 0) { - auto task = renderTasks.front(); - uint8_t r, g, b, a; - if (auto fill = task->sdata->fill()) { - rasterGradientShape(surface, task->shape, fill->id()); - } else{ - task->sdata->fill(&r, &g, &b, &a); - if (a > 0) rasterSolidShape(surface, task->shape, r, g, b, a); - } - task->sdata->strokeColor(&r, &g, &b, &a); - if (a > 0) rasterStroke(surface, task->shape, r, g, b, a); - renderTasks.pop(); - } -} + auto shape = static_cast(data); + if (!shape) return false; + uint8_t r, g, b, a; -bool SwRenderer::flush() -{ - while (prepareTasks.size() > 0) { - auto task = prepareTasks.front(); - if (task->progress.valid()) task->progress.get(); - prepareTasks.pop(); + if (auto fill = sdata.fill()) { + rasterGradientShape(surface, shape, fill->id()); + } else{ + sdata.fill(&r, &g, &b, &a); + if (a > 0) rasterSolidShape(surface, shape, r, g, b, a); } - - if (progress.valid()) progress.get(); - - return true; -} - - -bool SwRenderer::render(TVG_UNUSED const Shape& sdata, TVG_UNUSED void *data) -{ - //Do Nothing + sdata.strokeColor(&r, &g, &b, &a); + if (a > 0) rasterStroke(surface, shape, r, g, b, a); return true; } @@ -144,91 +81,72 @@ bool SwRenderer::render(TVG_UNUSED const Shape& sdata, TVG_UNUSED void *data) bool SwRenderer::dispose(TVG_UNUSED const Shape& sdata, void *data) { - auto task = static_cast(data); - if (!task) return true; - if (task->progress.valid()) task->progress.get(); - shapeFree(task->shape); - if (task->transform) free(task->transform); - free(task); + auto shape = static_cast(data); + if (!shape) return false; + shapeFree(shape); return true; } void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags) { - //prepare task - auto task = static_cast(data); - if (!task) { - task = static_cast(calloc(1, sizeof(SwTask))); - if (!task) return nullptr; + //prepare shape data + auto shape = static_cast(data); + if (!shape) { + shape = static_cast(calloc(1, sizeof(SwShape))); + assert(shape); } - if (flags == RenderUpdateFlag::None || task->progress.valid()) return task; + if (flags == RenderUpdateFlag::None) return shape; - task->sdata = &sdata; - task->clip = {static_cast(surface.w), static_cast(surface.h)}; + SwSize clip = {static_cast(surface.w), static_cast(surface.h)}; - if (transform) { - if (!task->transform) task->transform = static_cast(malloc(sizeof(Matrix))); - assert(task->transform); - *task->transform = transform->m; - } else { - if (task->transform) free(task->transform); - task->transform = nullptr; + //Valid Stroking? + uint8_t strokeAlpha = 0; + auto strokeWidth = sdata.strokeWidth(); + if (strokeWidth > FLT_EPSILON) { + sdata.strokeColor(nullptr, nullptr, nullptr, &strokeAlpha); } - task->flags = flags; - - auto asyncTask = [](SwTask* task) { - - //Valid Stroking? - uint8_t strokeAlpha = 0; - auto strokeWidth = task->sdata->strokeWidth(); - if (strokeWidth > FLT_EPSILON) { - task->sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha); - } - - //Shape - if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) { - shapeReset(task->shape); - uint8_t alpha = 0; - task->sdata->fill(nullptr, nullptr, nullptr, &alpha); - bool renderShape = (alpha > 0 || task->sdata->fill()); - if (renderShape || strokeAlpha) { - if (!shapePrepare(task->shape, task->sdata, task->clip, task->transform)) return; - if (renderShape) { - auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true; - if (!shapeGenRle(task->shape, task->sdata, task->clip, antiAlias)) return; - } + const Matrix* matrix = (transform ? &transform->m : nullptr); + + //Shape + if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) { + shapeReset(shape); + uint8_t alpha = 0; + sdata.fill(nullptr, nullptr, nullptr, &alpha); + bool renderShape = (alpha > 0 || sdata.fill()); + if (renderShape || strokeAlpha) { + if (!shapePrepare(shape, &sdata, clip, matrix)) return shape; + if (renderShape) { + auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true; + if (!shapeGenRle(shape, &sdata, clip, antiAlias)) return shape; } } //Fill - if (task->flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { - auto fill = task->sdata->fill(); + if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { + auto fill = sdata.fill(); if (fill) { - auto ctable = (task->flags & RenderUpdateFlag::Gradient) ? true : false; - if (ctable) shapeResetFill(task->shape); - if (!shapeGenFillColors(task->shape, fill, task->transform, ctable)) return; + auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; + if (ctable) shapeResetFill(shape); + if (!shapeGenFillColors(shape, fill, matrix, ctable)) return shape; } else { - shapeDelFill(task->shape); + shapeDelFill(shape); } } //Stroke - if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { + if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { if (strokeAlpha > 0) { - shapeResetStroke(task->shape, task->sdata, task->transform); - if (!shapeGenStrokeRle(task->shape, task->sdata, task->transform, task->clip)) return; + shapeResetStroke(shape, &sdata, matrix); + if (!shapeGenStrokeRle(shape, &sdata, matrix, clip)) return shape; } else { - shapeDelStroke(task->shape); + shapeDelStroke(shape); } } - shapeDelOutline(task->shape); - }; - - prepareTasks.push(task); - task->progress = async((launch::async | launch::deferred), asyncTask, task); + shapeDelOutline(shape); + } - return task; + return shape; } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index d34c83c..9a41902 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -22,10 +22,6 @@ #ifndef _TVG_SW_RENDERER_H_ #define _TVG_SW_RENDERER_H_ -#include -#include -#include - namespace tvg { @@ -38,10 +34,7 @@ public: bool dispose(const Shape& shape, void *data) override; bool preRender() override; bool render(const Shape& shape, void *data) override; - bool postRender() override; bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h); - bool clear() override; - bool flush() override; uint32_t ref() override; uint32_t unref() override; @@ -49,13 +42,8 @@ public: static int init(); static int term(); - void doRender(); //Internally used for threading - private: Surface surface = {nullptr, 0, 0, 0}; - future progress; - queue prepareTasks; - queue renderTasks; SwRenderer(){}; ~SwRenderer(); diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index ed7c1e4..f9537d1 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -463,52 +463,52 @@ bool _fastTrack(const SwOutline* outline) /* External Class Implementation */ /************************************************************************/ -bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform) +bool shapePrepare(SwShape* shape, const Shape* sdata, const SwSize& clip, const Matrix* transform) { if (!shapeGenOutline(shape, sdata, transform)) return false; - if (!_updateBBox(shape.outline, shape.bbox)) return false; + if (!_updateBBox(shape->outline, shape->bbox)) return false; - if (!_checkValid(shape.outline, shape.bbox, clip)) return false; + if (!_checkValid(shape->outline, shape->bbox, clip)) return false; return true; } -bool shapeGenRle(SwShape& shape, TVG_UNUSED const Shape* sdata, const SwSize& clip, bool antiAlias) +bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, const SwSize& clip, bool antiAlias) { //FIXME: Should we draw it? //Case: Stroke Line //if (shape.outline->opened) return true; //Case A: Fast Track Rectangle Drawing - if ((shape.rect = _fastTrack(shape.outline))) return true; + if ((shape->rect = _fastTrack(shape->outline))) return true; //Case B: Normale Shape RLE Drawing - if ((shape.rle = rleRender(shape.outline, shape.bbox, clip, antiAlias))) return true; + if ((shape->rle = rleRender(shape->outline, shape->bbox, clip, antiAlias))) return true; return false; } -void shapeDelOutline(SwShape& shape) +void shapeDelOutline(SwShape* shape) { - auto outline = shape.outline; + auto outline = shape->outline; _delOutline(outline); - shape.outline = nullptr; + shape->outline = nullptr; } -void shapeReset(SwShape& shape) +void shapeReset(SwShape* shape) { shapeDelOutline(shape); - rleFree(shape.rle); - shape.rle = nullptr; - shape.rect = false; - _initBBox(shape.bbox); + rleFree(shape->rle); + shape->rle = nullptr; + shape->rect = false; + _initBBox(shape->bbox); } -bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform) +bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform) { assert(sdata); @@ -550,7 +550,7 @@ bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform ++outlinePtsCnt; //for close ++outlineCntrsCnt; //for end - auto outline = shape.outline; + auto outline = shape->outline; if (!outline) outline = static_cast(calloc(1, sizeof(SwOutline))); assert(outline); outline->opened = true; @@ -594,49 +594,49 @@ bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform //FIXME: //outline->flags = SwOutline::FillRule::Winding; - shape.outline = outline; + shape->outline = outline; return true; } -void shapeFree(SwShape& shape) +void shapeFree(SwShape* shape) { shapeDelOutline(shape); - rleFree(shape.rle); + rleFree(shape->rle); shapeDelFill(shape); - if (shape.stroke) { - rleFree(shape.strokeRle); - strokeFree(shape.stroke); + if (shape->stroke) { + rleFree(shape->strokeRle); + strokeFree(shape->stroke); } } -void shapeDelStroke(SwShape& shape) +void shapeDelStroke(SwShape* shape) { - if (!shape.stroke) return; - rleFree(shape.strokeRle); - shape.strokeRle = nullptr; - strokeFree(shape.stroke); - shape.stroke = nullptr; + if (!shape->stroke) return; + rleFree(shape->strokeRle); + shape->strokeRle = nullptr; + strokeFree(shape->stroke); + shape->stroke = nullptr; } -void shapeResetStroke(SwShape& shape, const Shape* sdata, const Matrix* transform) +void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform) { - if (!shape.stroke) shape.stroke = static_cast(calloc(1, sizeof(SwStroke))); - auto stroke = shape.stroke; - assert(stroke); + if (!shape->stroke) shape->stroke = static_cast(calloc(1, sizeof(SwStroke))); + auto stroke = shape->stroke; + if (!stroke) return; - strokeReset(*stroke, sdata, transform); + strokeReset(stroke, sdata, transform); - rleFree(shape.strokeRle); - shape.strokeRle = nullptr; + rleFree(shape->strokeRle); + shape->strokeRle = nullptr; } -bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transform, const SwSize& clip) +bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip) { assert(sdata); @@ -648,15 +648,15 @@ bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transfo if (!shapeOutline) return false; //Normal Style stroke } else { - if (!shape.outline) { + if (!shape->outline) { if (!shapeGenOutline(shape, sdata, transform)) return false; } - shapeOutline = shape.outline; + shapeOutline = shape->outline; } - if (!strokeParseOutline(*shape.stroke, *shapeOutline)) return false; + if (!strokeParseOutline(shape->stroke, *shapeOutline)) return false; - auto strokeOutline = strokeExportOutline(*shape.stroke); + auto strokeOutline = strokeExportOutline(shape->stroke); if (!strokeOutline) return false; SwBBox bbox; @@ -664,7 +664,7 @@ bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transfo if (!_checkValid(strokeOutline, bbox, clip)) return false; - shape.strokeRle = rleRender(strokeOutline, bbox, clip, true); + shape->strokeRle = rleRender(strokeOutline, bbox, clip, true); _delOutline(strokeOutline); @@ -672,26 +672,27 @@ bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transfo } -bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transform, bool ctable) +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, bool ctable) { - return fillGenColorTable(shape.fill, fill, transform, ctable); + return fillGenColorTable(shape->fill, fill, transform, ctable); } -void shapeResetFill(SwShape& shape) +void shapeResetFill(SwShape* shape) { - if (!shape.fill) shape.fill = static_cast(calloc(1, sizeof(SwFill))); - assert(shape.fill); - - fillReset(shape.fill); + if (!shape->fill) { + shape->fill = static_cast(calloc(1, sizeof(SwFill))); + if (!shape->fill) return; + } + fillReset(shape->fill); } -void shapeDelFill(SwShape& shape) +void shapeDelFill(SwShape* shape) { - if (!shape.fill) return; - fillFree(shape.fill); - shape.fill = nullptr; + if (!shape->fill) return; + fillFree(shape->fill); + shape->fill = nullptr; } diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index 70eb1ca..fbe28c1 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -846,34 +846,34 @@ void strokeFree(SwStroke* stroke) } -void strokeReset(SwStroke& stroke, const Shape* sdata, const Matrix* transform) +void strokeReset(SwStroke* stroke, const Shape* sdata, const Matrix* transform) { assert(sdata); if (transform) { - stroke.sx = sqrt(pow(transform->e11, 2) + pow(transform->e21, 2)); - stroke.sy = sqrt(pow(transform->e12, 2) + pow(transform->e22, 2)); + stroke->sx = sqrt(pow(transform->e11, 2) + pow(transform->e21, 2)); + stroke->sy = sqrt(pow(transform->e12, 2) + pow(transform->e22, 2)); } else { - stroke.sx = stroke.sy = 1.0f; + stroke->sx = stroke->sy = 1.0f; } - stroke.width = TO_SWCOORD(sdata->strokeWidth() * 0.5); - stroke.cap = sdata->strokeCap(); + stroke->width = TO_SWCOORD(sdata->strokeWidth() * 0.5); + stroke->cap = sdata->strokeCap(); //Save line join: it can be temporarily changed when stroking curves... - stroke.joinSaved = stroke.join = sdata->strokeJoin(); + stroke->joinSaved = stroke->join = sdata->strokeJoin(); - stroke.borders[0].ptsCnt = 0; - stroke.borders[0].start = -1; - stroke.borders[0].valid = false; + stroke->borders[0].ptsCnt = 0; + stroke->borders[0].start = -1; + stroke->borders[0].valid = false; - stroke.borders[1].ptsCnt = 0; - stroke.borders[1].start = -1; - stroke.borders[1].valid = false; + stroke->borders[1].ptsCnt = 0; + stroke->borders[1].start = -1; + stroke->borders[1].valid = false; } -bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline) +bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline) { uint32_t first = 0; @@ -895,7 +895,7 @@ bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline) //A contour cannot start with a cubic control point if (type == SW_CURVE_TYPE_CUBIC) return false; - _beginSubPath(stroke, start, outline.opened); + _beginSubPath(*stroke, start, outline.opened); while (pt < limit) { ++pt; @@ -903,7 +903,7 @@ bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline) //emit a signel line_to if (types[0] == SW_CURVE_TYPE_POINT) { - _lineTo(stroke, *pt); + _lineTo(*stroke, *pt); //types cubic } else { if (pt + 1 > limit || types[1] != SW_CURVE_TYPE_CUBIC) return false; @@ -912,28 +912,28 @@ bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline) types += 2; if (pt <= limit) { - _cubicTo(stroke, pt[-2], pt[-1], pt[0]); + _cubicTo(*stroke, pt[-2], pt[-1], pt[0]); continue; } - _cubicTo(stroke, pt[-2], pt[-1], start); + _cubicTo(*stroke, pt[-2], pt[-1], start); goto close; } } close: - if (!stroke.firstPt) _endSubPath(stroke); + if (!stroke->firstPt) _endSubPath(*stroke); first = last + 1; } return true; } -SwOutline* strokeExportOutline(SwStroke& stroke) +SwOutline* strokeExportOutline(SwStroke* stroke) { uint32_t count1, count2, count3, count4; - _getCounts(stroke.borders + 0, count1, count2); - _getCounts(stroke.borders + 1, count3, count4); + _getCounts(stroke->borders + 0, count1, count2); + _getCounts(stroke->borders + 1, count3, count4); auto ptsCnt = count1 + count3; auto cntrsCnt = count2 + count4; @@ -950,8 +950,8 @@ SwOutline* strokeExportOutline(SwStroke& stroke) outline->cntrs = static_cast(malloc(sizeof(uint32_t) * cntrsCnt)); assert(outline->cntrs); - _exportBorderOutline(stroke, outline, 0); //left - _exportBorderOutline(stroke, outline, 1); //right + _exportBorderOutline(*stroke, outline, 0); //left + _exportBorderOutline(*stroke, outline, 1); //right return outline; } diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 85292d2..60c76d5 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -57,12 +57,12 @@ class RenderMethod public: virtual ~RenderMethod() {} 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(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; } + virtual bool dispose(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; } + virtual bool preRender() { return true; } + virtual bool render(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; } + virtual bool postRender() { return true; } + virtual bool clear() { return true; } + virtual bool flush() { return true; } virtual uint32_t ref() { return 0; } virtual uint32_t unref() { return 0; } }; diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 205e8cb..442d3b7 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -2324,31 +2324,34 @@ bool SvgLoader::read() { if (content.empty()) return false; - auto asyncTask = [](SvgLoader *loader) { - bool res = simpleXmlParse(loader->content.c_str(), loader->content.size(), true, _svgLoaderParser, &(loader->loaderData)); - - if (!res) return unique_ptr(nullptr); - - if (loader->loaderData.doc) { - SvgNode *defs; - _updateStyle(loader->loaderData.doc, nullptr); - defs = loader->loaderData.doc->node.doc.defs; - if (defs) _updateGradient(loader->loaderData.doc, defs->node.defs.gradients); - else { - if (!loader->loaderData.gradients.empty()) { - vector gradientList; - for (auto gradient : loader->loaderData.gradients) { - gradientList.push_back(gradient); - } - _updateGradient(loader->loaderData.doc, gradientList); - gradientList.clear(); - } + loaderData = {vector(), + nullptr, + nullptr, + vector(), + nullptr, + nullptr, + 0, + false}; + + loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); + + if (!simpleXmlParse(content.c_str(), content.size(), true, _svgLoaderParser, &loaderData)) return false; + + if (loaderData.doc) { + _updateStyle(loaderData.doc, nullptr); + auto defs = loaderData.doc->node.doc.defs; + if (defs) _updateGradient(loaderData.doc, defs->node.defs.gradients); + else { + if (!loaderData.gradients.empty()) { + vector gradientList; + std::copy(loaderData.gradients.begin(), loaderData.gradients.end(), gradientList.begin()); + _updateGradient(loaderData.doc, gradientList); + gradientList.clear(); } } - return loader->builder.build(loader->loaderData.doc); - }; + } - rootProgress = async((launch::async | launch::deferred), asyncTask, this); + root = builder.build(loaderData.doc); return true; } @@ -2356,8 +2359,6 @@ bool SvgLoader::read() bool SvgLoader::close() { - if (rootProgress.valid()) root = rootProgress.get(); - if (loaderData.svgParse) { free(loaderData.svgParse); loaderData.svgParse = nullptr; @@ -2371,10 +2372,7 @@ bool SvgLoader::close() unique_ptr SvgLoader::data() { - if (rootProgress.valid()) root = rootProgress.get(); - - if (root) return move(root); - else return unique_ptr(nullptr); + return move(root); } #endif //_TVG_SVG_LOADER_CPP_ diff --git a/src/loaders/svg_loader/tvgSvgLoader.h b/src/loaders/svg_loader/tvgSvgLoader.h index 7f0ce3c..3ef981d 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.h +++ b/src/loaders/svg_loader/tvgSvgLoader.h @@ -24,7 +24,7 @@ #include "tvgSvgLoaderCommon.h" #include "tvgSvgSceneBuilder.h" -#include + class SvgLoader : public Loader { @@ -32,7 +32,6 @@ private: string content; SvgLoaderData loaderData; SvgSceneBuilder builder; - future> rootProgress; unique_ptr root; public: -- 2.7.4 From 93b517df062a42c511d93770558ade9293996362 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 14 Aug 2020 17:44:17 +0900 Subject: [PATCH 03/16] disable gl_engine in default. We don't include gl compile before it works properly. For development & test please turn it on in meson_option.txt locally. Change-Id: I2ff8b06f8e1b496922f70ec580662e8886a9b93d --- meson_options.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_options.txt b/meson_options.txt index 59d0130..3990b17 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,7 +1,7 @@ option('engines', type: 'array', choices: ['sw', 'gl'], - value: ['sw', 'gl'], + value: ['sw'], description: 'Enable Rasterizer Engine in thorvg') option('loaders', -- 2.7.4 From 709548701a7dc1c2ae61e6a473ccc0a072482b23 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 14 Aug 2020 18:47:03 +0900 Subject: [PATCH 04/16] loader svg: code refactoring. renamed svg loader path. Change-Id: I0219721540ea981d15d17b9571c1ee9b37651fb8 --- src/loaders/meson.build | 2 +- src/loaders/{svg_loader => svg}/meson.build | 0 src/loaders/{svg_loader => svg}/tvgSimpleXmlParser.cpp | 0 src/loaders/{svg_loader => svg}/tvgSimpleXmlParser.h | 0 src/loaders/{svg_loader => svg}/tvgSvgLoader.cpp | 0 src/loaders/{svg_loader => svg}/tvgSvgLoader.h | 0 src/loaders/{svg_loader => svg}/tvgSvgLoaderCommon.h | 0 src/loaders/{svg_loader => svg}/tvgSvgPath.cpp | 0 src/loaders/{svg_loader => svg}/tvgSvgPath.h | 0 src/loaders/{svg_loader => svg}/tvgSvgSceneBuilder.cpp | 0 src/loaders/{svg_loader => svg}/tvgSvgSceneBuilder.h | 0 11 files changed, 1 insertion(+), 1 deletion(-) rename src/loaders/{svg_loader => svg}/meson.build (100%) rename src/loaders/{svg_loader => svg}/tvgSimpleXmlParser.cpp (100%) rename src/loaders/{svg_loader => svg}/tvgSimpleXmlParser.h (100%) rename src/loaders/{svg_loader => svg}/tvgSvgLoader.cpp (100%) rename src/loaders/{svg_loader => svg}/tvgSvgLoader.h (100%) rename src/loaders/{svg_loader => svg}/tvgSvgLoaderCommon.h (100%) rename src/loaders/{svg_loader => svg}/tvgSvgPath.cpp (100%) rename src/loaders/{svg_loader => svg}/tvgSvgPath.h (100%) rename src/loaders/{svg_loader => svg}/tvgSvgSceneBuilder.cpp (100%) rename src/loaders/{svg_loader => svg}/tvgSvgSceneBuilder.h (100%) diff --git a/src/loaders/meson.build b/src/loaders/meson.build index 873cfa7..bc67b53 100644 --- a/src/loaders/meson.build +++ b/src/loaders/meson.build @@ -1,7 +1,7 @@ subloader_dep = [] if get_option('loaders').contains('svg') == true - subdir('svg_loader') + subdir('svg') message('Enable SVG Loader') endif diff --git a/src/loaders/svg_loader/meson.build b/src/loaders/svg/meson.build similarity index 100% rename from src/loaders/svg_loader/meson.build rename to src/loaders/svg/meson.build diff --git a/src/loaders/svg_loader/tvgSimpleXmlParser.cpp b/src/loaders/svg/tvgSimpleXmlParser.cpp similarity index 100% rename from src/loaders/svg_loader/tvgSimpleXmlParser.cpp rename to src/loaders/svg/tvgSimpleXmlParser.cpp diff --git a/src/loaders/svg_loader/tvgSimpleXmlParser.h b/src/loaders/svg/tvgSimpleXmlParser.h similarity index 100% rename from src/loaders/svg_loader/tvgSimpleXmlParser.h rename to src/loaders/svg/tvgSimpleXmlParser.h diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp similarity index 100% rename from src/loaders/svg_loader/tvgSvgLoader.cpp rename to src/loaders/svg/tvgSvgLoader.cpp diff --git a/src/loaders/svg_loader/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h similarity index 100% rename from src/loaders/svg_loader/tvgSvgLoader.h rename to src/loaders/svg/tvgSvgLoader.h diff --git a/src/loaders/svg_loader/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h similarity index 100% rename from src/loaders/svg_loader/tvgSvgLoaderCommon.h rename to src/loaders/svg/tvgSvgLoaderCommon.h diff --git a/src/loaders/svg_loader/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp similarity index 100% rename from src/loaders/svg_loader/tvgSvgPath.cpp rename to src/loaders/svg/tvgSvgPath.cpp diff --git a/src/loaders/svg_loader/tvgSvgPath.h b/src/loaders/svg/tvgSvgPath.h similarity index 100% rename from src/loaders/svg_loader/tvgSvgPath.h rename to src/loaders/svg/tvgSvgPath.h diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp similarity index 100% rename from src/loaders/svg_loader/tvgSvgSceneBuilder.cpp rename to src/loaders/svg/tvgSvgSceneBuilder.cpp diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.h b/src/loaders/svg/tvgSvgSceneBuilder.h similarity index 100% rename from src/loaders/svg_loader/tvgSvgSceneBuilder.h rename to src/loaders/svg/tvgSvgSceneBuilder.h -- 2.7.4 From 1eb11f249ef62217e6f47fcc90b459764d0685b1 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 14 Aug 2020 18:51:38 +0900 Subject: [PATCH 05/16] common initializer: introduce thread count api. this interface controls the number of threads working behind. default is 0 == only syncrhonous. Change-Id: I8404f33359e6213acc5e578061568fede50cd9a6 --- inc/thorvg.h | 2 ++ src/lib/tvgInitializer.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/inc/thorvg.h b/inc/thorvg.h index 9759245..452234d 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -365,6 +365,8 @@ public: */ static Result init(CanvasEngine engine) noexcept; static Result term(CanvasEngine engine) noexcept; + static Result threads(uint32_t cnt) noexcept; + static uint32_t threads() noexcept; _TVG_DISABLE_CTOR(Initializer); }; diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 2009299..3367603 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -38,6 +38,8 @@ /* Internal Class Implementation */ /************************************************************************/ +static uint32_t threadCnt = 0; + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -93,4 +95,18 @@ Result Initializer::term(CanvasEngine engine) noexcept return Result::Success; } + +Result Initializer::threads(uint32_t cnt) noexcept +{ + threadCnt = cnt; + + return Result::Success; +} + + +uint32_t Initializer::threads() noexcept +{ + return threadCnt; +} + #endif /* _TVG_INITIALIZER_CPP_ */ -- 2.7.4 From 7ab71c52d038a5940641c61871aca169ece36197 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 14 Aug 2020 19:35:39 +0900 Subject: [PATCH 06/16] picture svg: introduce load() with memory data input source. picture now affords the memory data as input source so that user can pass svg data memory directly. Change-Id: I246c09b682a2d60e53ad556ce0c90337142ee4f1 --- .gitignore | 1 + inc/thorvg.h | 1 + src/lib/tvgLoader.h | 1 + src/lib/tvgLoaderMgr.cpp | 3 +- src/lib/tvgLoaderMgr.h | 2 +- src/lib/tvgPicture.cpp | 8 +++ src/lib/tvgPictureImpl.h | 19 ++++- src/loaders/svg/tvgSvgLoader.cpp | 56 ++++++++++----- src/loaders/svg/tvgSvgLoader.h | 7 +- test/makefile | 1 + test/testSvg2.cpp | 148 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 222 insertions(+), 25 deletions(-) create mode 100644 test/testSvg2.cpp diff --git a/.gitignore b/.gitignore index 7f4d09b..53a53b5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ testLinearGradient testRadialGradient testGradientTransform testSvg +testSvg2 testAsync testCapi testArc diff --git a/inc/thorvg.h b/inc/thorvg.h index 452234d..3f43a2f 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -267,6 +267,7 @@ public: ~Picture(); Result load(const std::string& path) noexcept; + Result load(const char* data, uint32_t size) noexcept; Result viewbox(float* x, float* y, float* w, float* h) const noexcept; static std::unique_ptr gen() noexcept; diff --git a/src/lib/tvgLoader.h b/src/lib/tvgLoader.h index c714f92..9c7279e 100644 --- a/src/lib/tvgLoader.h +++ b/src/lib/tvgLoader.h @@ -37,6 +37,7 @@ public: virtual ~Loader() {} virtual bool open(const char* path) = 0; + virtual bool open(const char* data, uint32_t size) = 0; virtual bool read() = 0; virtual bool close() = 0; virtual unique_ptr data() = 0; diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index a35dcd5..5e59a44 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -50,12 +50,11 @@ bool LoaderMgr::term() return true; } -unique_ptr LoaderMgr::loader(const char* path) +unique_ptr LoaderMgr::loader() { #ifdef THORVG_SVG_LOADER_SUPPORT return unique_ptr(new SvgLoader); #endif - cout << "Non supported format: " << path << endl; return nullptr; } diff --git a/src/lib/tvgLoaderMgr.h b/src/lib/tvgLoaderMgr.h index 7c9d52e..95a0676 100644 --- a/src/lib/tvgLoaderMgr.h +++ b/src/lib/tvgLoaderMgr.h @@ -26,7 +26,7 @@ struct LoaderMgr { static bool init(); static bool term(); - static unique_ptr loader(const char* path); + static unique_ptr loader(); }; #endif //_TVG_LOADER_MGR_H_ \ No newline at end of file diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 7595afa..7083692 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -53,6 +53,14 @@ Result Picture::load(const std::string& path) noexcept } +Result Picture::load(const char* data, uint32_t size) noexcept +{ + if (!data || size <= 0) return Result::InvalidArguments; + + return IMPL->load(data, size); +} + + Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept { if (IMPL->viewbox(x, y, w, h)) return Result::Success; diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 45e2e9d..5ab9618 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -84,8 +84,23 @@ struct Picture::Impl 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; + loader = LoaderMgr::loader(); + if (!loader || !loader->open(path.c_str())) { + cout << "Non supported format: " << path.c_str() << endl; + return Result::NonSupport; + } + if (!loader->read()) return Result::Unknown; + return Result::Success; + } + + Result load(const char* data, uint32_t size) + { + if (loader) loader->close(); + loader = LoaderMgr::loader(); + if (!loader || !loader->open(data, size)) { + cout << "Non supported load data" << endl; + return Result::NonSupport; + } if (!loader->read()) return Result::Unknown; return Result::Success; } diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 442d3b7..1579390 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -35,6 +35,7 @@ typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength); static void _freeNode(SvgNode* node); + static char* _skipSpace(const char* str, const char* end) { while (((end != nullptr && str < end) || (end == nullptr && *str != '\0')) && isspace(*str)) @@ -2280,29 +2281,15 @@ SvgLoader::~SvgLoader() } -bool SvgLoader::open(const char* path) +bool SvgLoader::header() { - ifstream f; - f.open(path); - - if (!f.is_open()) - { - cout << "ERROR: Failed to open file = " << path; - return false; - } else { - getline(f, content, '\0'); - f.close(); - - if (content.empty()) return false; - } - //For valid check, only tag is parsed first. //If the tag is found, the loaded file is valid and stores viewbox information. //After that, the remaining content data is parsed in order with async. loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); if (!loaderData.svgParse) return false; - simpleXmlParse(content.c_str(), content.size(), true, _svgLoaderParserForValidCheck, &(loaderData)); + simpleXmlParse(content, size, true, _svgLoaderParserForValidCheck, &(loaderData)); if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) { //Return the brief resource info such as viewbox: @@ -2310,7 +2297,6 @@ bool SvgLoader::open(const char* path) this->vy = loaderData.doc->node.doc.vy; this->vw = loaderData.doc->node.doc.vw; this->vh = loaderData.doc->node.doc.vh; - } else { cout << "ERROR : No SVG File. There is no " <content = data; + this->size = size; + + return header(); +} + + +bool SvgLoader::open(const char* path) +{ + ifstream f; + f.open(path); + + if (!f.is_open()) + { + cout << "ERROR: Failed to open file = " << path; + return false; + } else { + getline(f, filePath, '\0'); + f.close(); + + if (filePath.empty()) return false; + + this->content = filePath.c_str(); + this->size = filePath.size(); + } + + return header(); +} + + bool SvgLoader::read() { - if (content.empty()) return false; + if (!content || size == 0) return false; loaderData = {vector(), nullptr, @@ -2335,7 +2353,7 @@ bool SvgLoader::read() loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); - if (!simpleXmlParse(content.c_str(), content.size(), true, _svgLoaderParser, &loaderData)) return false; + if (!simpleXmlParse(content, size, true, _svgLoaderParser, &loaderData)) return false; if (loaderData.doc) { _updateStyle(loaderData.doc, nullptr); diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index 3ef981d..e85582b 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -29,7 +29,10 @@ class SvgLoader : public Loader { private: - string content; + string filePath; + const char* content = nullptr; + uint32_t size = 0; + SvgLoaderData loaderData; SvgSceneBuilder builder; unique_ptr root; @@ -39,6 +42,8 @@ public: ~SvgLoader(); bool open(const char* path) override; + bool open(const char* data, uint32_t size) override; + bool header(); bool read() override; bool close() override; unique_ptr data() override; diff --git a/test/makefile b/test/makefile index 29e6e77..f48278d 100644 --- a/test/makefile +++ b/test/makefile @@ -17,6 +17,7 @@ all: gcc -o testRadialGradient testRadialGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` 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 testSvg2 testSvg2.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/testSvg2.cpp b/test/testSvg2.cpp new file mode 100644 index 0000000..171db91 --- /dev/null +++ b/test/testSvg2.cpp @@ -0,0 +1,148 @@ +#include "testCommon.h" + +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ + +static const char* svg = ""; + + +void tvgDrawCmds(tvg::Canvas* canvas) +{ + if (!canvas) return; + + //Background + auto shape = tvg::Shape::gen(); + shape->appendRect(0, 0, WIDTH, HEIGHT, 0, 0); //x, y, w, h, rx, ry + shape->fill(255, 255, 255, 255); //r, g, b, a + + if (canvas->push(move(shape)) != tvg::Result::Success) return; + + auto picture = tvg::Picture::gen(); + if (picture->load(svg, strlen(svg)) != tvg::Result::Success) return; + + float x, y, w, h; + picture->viewbox(&x, &y, &w, &h); + + float rate = (WIDTH/(w > h ? w : h)); + picture->scale(rate); + + x *= rate; + y *= rate; + w *= rate; + h *= rate; + + //Center Align ? + if (w > h) { + y -= (WIDTH - h) * 0.5f; + } else { + x -= (WIDTH - w) * 0.5f; + } + + picture->translate(-x, -y); + + canvas->push(move(picture)); +} + + +/************************************************************************/ +/* 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(tvg::CanvasEngine::Sw); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} -- 2.7.4 From f4d1065d5247abfd074aaff08a2db28343288357 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 15 Aug 2020 16:29:46 +0900 Subject: [PATCH 07/16] sw_engine: convert colorspace ARGB -> RGBA in default. We can use RGBA colorspace rather ARGB for pixel data. This would be better for many rendering system, since it's more widely preferred than ARGB including opengl. Change-Id: Ibbfe6a511d77bf0ef30ce261995467c11164d306 --- inc/thorvg.h | 4 +- inc/thorvg_capi.h | 4 +- src/bindings/capi/tvgCapi.cpp | 4 +- src/lib/sw_engine/tvgSwCommon.h | 30 ++++++--- src/lib/sw_engine/tvgSwFill.cpp | 26 ++++---- src/lib/sw_engine/tvgSwRaster.cpp | 124 ++++++++++++++++++++++++------------ src/lib/sw_engine/tvgSwRenderer.cpp | 5 +- src/lib/sw_engine/tvgSwRenderer.h | 2 +- src/lib/sw_engine/tvgSwShape.cpp | 4 +- src/lib/tvgGlCanvas.cpp | 2 +- src/lib/tvgRender.h | 1 + src/lib/tvgSwCanvas.cpp | 4 +- test/testArc.cpp | 2 +- test/testAsync.cpp | 2 +- test/testBlending.cpp | 2 +- test/testBoundary.cpp | 2 +- test/testCapi.c | 2 +- test/testCustomTransform.cpp | 2 +- test/testDirectUpdate.cpp | 2 +- test/testGradientTransform.cpp | 2 +- test/testLinearGradient.cpp | 2 +- test/testMultiShapes.cpp | 2 +- test/testPath.cpp | 2 +- test/testPathCopy.cpp | 2 +- test/testRadialGradient.cpp | 2 +- test/testScene.cpp | 2 +- test/testSceneTransform.cpp | 2 +- test/testShape.cpp | 2 +- test/testStroke.cpp | 2 +- test/testStrokeLine.cpp | 2 +- test/testSvg.cpp | 2 +- test/testSvg2.cpp | 2 +- test/testTransform.cpp | 2 +- test/testUpdate.cpp | 2 +- 34 files changed, 157 insertions(+), 97 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 3f43a2f..9ed5498 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -311,7 +311,9 @@ class TVG_EXPORT SwCanvas final : public Canvas public: ~SwCanvas(); - Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept; + enum Colorspace { RGBA8888 = 0, ARGB8888 }; + + Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept; static std::unique_ptr gen() noexcept; diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 763d71b..2f1bf96 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -23,6 +23,8 @@ typedef struct _Tvg_Gradient Tvg_Gradient; #define TVG_ENGINE_SW (1 << 1) #define TVG_ENGINE_GL (1 << 2) +#define TVG_COLORSPACE_RGBA8888 0 +#define TVG_COLORSPACE_ARGB8888 1 typedef enum { TVG_RESULT_SUCCESS = 0, @@ -94,7 +96,7 @@ TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method); /* SwCanvas API */ /************************************************************************/ TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create(); -TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h); +TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs); /************************************************************************/ diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index e05435a..ac8cdcb 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -88,9 +88,9 @@ TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas) } -TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) +TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs) { - return (Tvg_Result) reinterpret_cast(canvas)->target(buffer, stride, w, h); + return (Tvg_Result) reinterpret_cast(canvas)->target(buffer, stride, w, h, static_cast(cs)); } diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 295f11a..e5d4719 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -222,20 +222,26 @@ static inline SwCoord TO_SWCOORD(float val) } -static inline uint32_t COLOR_ALPHA(uint32_t rgba) +static inline uint32_t RGBA_ALPHA(uint32_t rgba) { - return (rgba >> 24) & 0xff; + return rgba & 0x000000ff; } -static inline uint32_t COLOR_ALPHA_BLEND(uint32_t rgba, uint32_t alpha) +static inline uint32_t ARGB_ALPHA(uint32_t argb) +{ + return (argb >> 24) & 0xff; +} + + +static inline uint32_t RGBA_ALPHA_BLEND(uint32_t rgba, uint32_t alpha) { return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) + ((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff)); } -static inline uint32_t COLOR_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rgba2, uint32_t b) +static inline uint32_t RGBA_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rgba2, uint32_t b) { auto t = (((rgba1 & 0xff00ff) * a + (rgba2 & 0xff00ff) * b) >> 8) & 0xff00ff; rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00; @@ -243,13 +249,19 @@ static inline uint32_t COLOR_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rg } -static inline uint32_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static inline uint32_t RGBA_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (r << 24 | g << 16 | b << 8 | a); +} + + +static inline uint32_t ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return (a << 24 | r << 16 | g << 8 | b); } -static inline uint8_t COLOR_ALPHA_MULTIPLY(uint32_t c, uint32_t a) +static inline uint8_t ALPHA_MULTIPLY(uint32_t c, uint32_t a) { return (c * a) >> 8; } @@ -278,7 +290,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip); void shapeFree(SwShape* shape); void shapeDelStroke(SwShape* shape); -bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, bool ctable); +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable); void shapeResetFill(SwShape* shape); void shapeDelFill(SwShape* shape); @@ -287,7 +299,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); SwOutline* strokeExportOutline(SwStroke* stroke); void strokeFree(SwStroke* stroke); -bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable); +bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable); void fillReset(SwFill* fill); void fillFree(SwFill* fill); void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len); @@ -302,7 +314,7 @@ bool rasterStroke(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_ bool rasterClear(Surface& surface); -static inline void rasterARGB32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) +static inline void rasterRGBA32(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 ae938fd..cd68d0f 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -34,7 +34,7 @@ #define FIXPT_SIZE (1<a < 255) fill->translucent = true; - 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 r = ALPHA_MULTIPLY(pColors->r, pColors->a); + auto g = ALPHA_MULTIPLY(pColors->g, pColors->a); + auto b = ALPHA_MULTIPLY(pColors->b, pColors->a); - auto rgba = COLOR_ARGB_JOIN(r, g, b, pColors->a); + auto rgba = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, pColors->a) : 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; @@ -75,17 +75,17 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata) auto delta = 1.0f / (next->offset - curr->offset); if (next->a < 255) fill->translucent = true; - 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 r = ALPHA_MULTIPLY(next->r, next->a); + auto g = ALPHA_MULTIPLY(next->g, next->a); + auto b = ALPHA_MULTIPLY(next->b, next->a); - auto rgba2 = COLOR_ARGB_JOIN(r, g, b, next->a); + auto rgba2 = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, next->a) : ARGB_JOIN(r, g, b, next->a); while (pos < next->offset && i < GRADIENT_STOP_SIZE) { auto t = (pos - curr->offset) * delta; auto dist = static_cast(256 * t); auto dist2 = 256 - dist; - fill->ctable[i] = COLOR_INTERPOLATE(rgba, dist2, rgba2, dist); + fill->ctable[i] = RGBA_INTERPOLATE(rgba, dist2, rgba2, dist); ++i; pos += inc; } @@ -252,7 +252,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, if (fabsf(inc) < FLT_EPSILON) { auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); - rasterARGB32(dst, color, offset, len); + rasterRGBA32(dst, color, offset, len); return; } @@ -282,7 +282,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, } -bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable) +bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable) { if (!fill) return false; @@ -291,7 +291,7 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, fill->spread = fdata->spread(); if (ctable) { - if (!_updateColorTable(fill, fdata)) return false; + if (!_updateColorTable(fill, fdata, cs)) return false; } if (fdata->id() == FILL_ID_LINEAR) { diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 46ef4ac..d07d7eb 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -45,12 +45,12 @@ static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint3 auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); - auto ialpha = 255 - COLOR_ALPHA(color); + auto ialpha = 255 - (surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(color) : ARGB_ALPHA(color); for (uint32_t y = 0; y < h; ++y) { auto dst = &buffer[y * surface.stride]; for (uint32_t x = 0; x < w; ++x) { - dst[x] = color + COLOR_ALPHA_BLEND(dst[x], ialpha); + dst[x] = color + RGBA_ALPHA_BLEND(dst[x], ialpha); } } return true; @@ -64,7 +64,7 @@ static bool _rasterSolidRect(Surface& surface, const SwBBox& region, uint32_t co auto h = static_cast(region.max.y - region.min.y); for (uint32_t y = 0; y < h; ++y) { - rasterARGB32(buffer + y * surface.stride, color, region.min.x, w); + rasterRGBA32(buffer + y * surface.stride, color, region.min.x, w); } return true; } @@ -79,11 +79,11 @@ static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t col for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface.buffer[span->y * surface.stride + span->x]; - if (span->coverage < 255) src = COLOR_ALPHA_BLEND(color, span->coverage); + if (span->coverage < 255) src = RGBA_ALPHA_BLEND(color, span->coverage); else src = color; - auto ialpha = 255 - COLOR_ALPHA(src); + auto ialpha = 255 - ((surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(src) : ARGB_ALPHA(src)); for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = src + COLOR_ALPHA_BLEND(dst[i], ialpha); + dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha); } ++span; } @@ -99,13 +99,13 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) for (uint32_t i = 0; i < rle->size; ++i) { if (span->coverage == 255) { - rasterARGB32(surface.buffer + span->y * surface.stride, color, span->x, span->len); + rasterRGBA32(surface.buffer + span->y * surface.stride, color, span->x, span->len); } else { auto dst = &surface.buffer[span->y * surface.stride + span->x]; - auto src = COLOR_ALPHA_BLEND(color, span->coverage); + auto src = RGBA_ALPHA_BLEND(color, span->coverage); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = src + COLOR_ALPHA_BLEND(dst[i], ialpha); + dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -131,8 +131,14 @@ static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, co for (uint32_t y = 0; y < h; ++y) { auto dst = &buffer[y * surface.stride]; fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w); - for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x])); + if (surface.cs == SwCanvas::RGBA8888) { + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - RGBA_ALPHA(tmpBuf[x])); + } + } else { + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - ARGB_ALPHA(tmpBuf[x])); + } } } //Opaque Gradient @@ -162,8 +168,14 @@ static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, co for (uint32_t y = 0; y < h; ++y) { auto dst = &buffer[y * surface.stride]; fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w); - for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x])); + if (surface.cs == SwCanvas::RGBA8888) { + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - RGBA_ALPHA(tmpBuf[x])); + } + } else { + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - ARGB_ALPHA(tmpBuf[x])); + } } } //Opaque Gradient @@ -191,14 +203,27 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface.buffer[span->y * surface.stride + span->x]; fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); - if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(buf[i])); + if (surface.cs == SwCanvas::RGBA8888) { + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(buf[i])); + } + } else { + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(tmp)); + } } } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = COLOR_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(tmp)); + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(buf[i])); + } + } else { + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(tmp)); + } } } ++span; @@ -213,7 +238,7 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = COLOR_ALPHA_BLEND(buf[i], span->coverage) + COLOR_ALPHA_BLEND(dst[i], ialpha); + dst[i] = RGBA_ALPHA_BLEND(buf[i], span->coverage) + RGBA_ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -237,14 +262,27 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface.buffer[span->y * surface.stride + span->x]; fillFetchRadial(fill, buf, span->y, span->x, span->len); - if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(buf[i])); + if (surface.cs == SwCanvas::RGBA8888) { + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(buf[i])); + } + } else { + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(tmp)); + } } } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = COLOR_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(tmp)); + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(buf[i])); + } + } else { + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(tmp)); + } } } ++span; @@ -259,7 +297,7 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF fillFetchRadial(fill, buf, span->y, span->x, span->len); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = COLOR_ALPHA_BLEND(buf[i], span->coverage) + COLOR_ALPHA_BLEND(dst[i], ialpha); + dst[i] = RGBA_ALPHA_BLEND(buf[i], span->coverage) + RGBA_ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -290,18 +328,20 @@ 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); + r = ALPHA_MULTIPLY(r, a); + g = ALPHA_MULTIPLY(g, a); + b = ALPHA_MULTIPLY(b, a); + + auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a); //Fast Track if (shape->rect) { auto region = _clipRegion(surface, shape->bbox); - if (a == 255) return _rasterSolidRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a)); - return _rasterTranslucentRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a)); + if (a == 255) return _rasterSolidRect(surface, region, color); + return _rasterTranslucentRect(surface, region, color); } else{ - if (a == 255) return _rasterSolidRle(surface, shape->rle, COLOR_ARGB_JOIN(r, g, b, a)); - return _rasterTranslucentRle(surface, shape->rle, COLOR_ARGB_JOIN(r, g, b, a)); + if (a == 255) return _rasterSolidRle(surface, shape->rle, color); + return _rasterTranslucentRle(surface, shape->rle, color); } return false; } @@ -309,12 +349,14 @@ 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); + r = ALPHA_MULTIPLY(r, a); + g = ALPHA_MULTIPLY(g, a); + b = ALPHA_MULTIPLY(b, a); + + auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, 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)); + if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color); + return _rasterTranslucentRle(surface, shape->strokeRle, color); } @@ -323,10 +365,10 @@ bool rasterClear(Surface& surface) if (!surface.buffer || surface.stride <= 0 || surface.w <= 0 || surface.h <= 0) return false; if (surface.w == surface.stride) { - rasterARGB32(surface.buffer, 0x00000000, 0, surface.w * surface.h); + rasterRGBA32(surface.buffer, 0x00000000, 0, surface.w * surface.h); } else { for (uint32_t i = 0; i < surface.h; i++) { - rasterARGB32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w); + rasterRGBA32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w); } } return true; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index eb2f199..66608f5 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -40,7 +40,7 @@ SwRenderer::~SwRenderer() } -bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) +bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs) { if (!buffer || stride == 0 || w == 0 || h == 0) return false; @@ -48,6 +48,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t surface.stride = stride; surface.w = w; surface.h = h; + surface.cs = cs; return true; } @@ -129,7 +130,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* if (fill) { auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; if (ctable) shapeResetFill(shape); - if (!shapeGenFillColors(shape, fill, matrix, ctable)) return shape; + if (!shapeGenFillColors(shape, fill, matrix, surface.cs, ctable)) return shape; } else { shapeDelFill(shape); } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 9a41902..5657602 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -34,7 +34,7 @@ public: bool dispose(const Shape& shape, void *data) override; bool preRender() override; bool render(const Shape& shape, void *data) override; - bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h); + bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs); uint32_t ref() override; uint32_t unref() override; diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index f9537d1..3704a2c 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -672,9 +672,9 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo } -bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, bool ctable) +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable) { - return fillGenColorTable(shape->fill, fill, transform, ctable); + return fillGenColorTable(shape->fill, fill, transform, cs, ctable); } diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index 7f2c04b..1ac5732 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -70,7 +70,7 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t auto renderer = static_cast(Canvas::pImpl.get()->renderer); if (!renderer) return Result::MemoryCorruption; - if (!renderer->target(buffer, stride, w, h)) return Result::Unknown; + if (!renderer->target(buffer, stride, w, h, 0)) return Result::Unknown; return Result::Success; #endif diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 60c76d5..3535bf4 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -31,6 +31,7 @@ struct Surface uint32_t* buffer; uint32_t stride; uint32_t w, h; + uint32_t cs; }; enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, All = 32}; diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index e958ea2..755d422 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -62,14 +62,14 @@ SwCanvas::~SwCanvas() } -Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept +Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept { #ifdef THORVG_SW_RASTER_SUPPORT //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl.get()->renderer); if (!renderer) return Result::MemoryCorruption; - if (!renderer->target(buffer, stride, w, h)) return Result::InvalidArguments; + if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments; return Result::Success; #endif diff --git a/test/testArc.cpp b/test/testArc.cpp index b02196e..1f15812 100644 --- a/test/testArc.cpp +++ b/test/testArc.cpp @@ -79,7 +79,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testAsync.cpp b/test/testAsync.cpp index edc6dde..608cefb 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -68,7 +68,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); } Eina_Bool animSwCb(void* data) diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 59a4fad..743b1e0 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -62,7 +62,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index 57a3d6c..3830687 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -51,7 +51,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testCapi.c b/test/testCapi.c index 90c4e1d..c6df396 100644 --- a/test/testCapi.c +++ b/test/testCapi.c @@ -16,7 +16,7 @@ void testCapi() tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL); Tvg_Canvas* canvas = tvg_swcanvas_create(); - tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT); + tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888); Tvg_Paint* shape = tvg_shape_new(); tvg_shape_append_rect(shape, 0, 0, 200, 200, 0, 0); diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 4803ef1..9daa6fc 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -92,7 +92,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 3c275b6..8dcc474 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -55,7 +55,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index 4fa426b..77d5f6a 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -120,7 +120,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index f98fc97..db11682 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -80,7 +80,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 5a6d34f..12009bc 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -40,7 +40,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testPath.cpp b/test/testPath.cpp index 52c56ef..de6ef60 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -57,7 +57,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index 0ae364b..fb1080b 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -94,7 +94,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index a6c10ba..6e77291 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -80,7 +80,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testScene.cpp b/test/testScene.cpp index 5b12020..daa5d86 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -87,7 +87,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 49558fb..e64fa9a 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -116,7 +116,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testShape.cpp b/test/testShape.cpp index 88519d0..af4d0c4 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -30,7 +30,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testStroke.cpp b/test/testStroke.cpp index 9174872..778d7c7 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -77,7 +77,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 445f840..1205bb1 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -114,7 +114,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testSvg.cpp b/test/testSvg.cpp index e16f19b..06fe350 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -72,7 +72,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testSvg2.cpp b/test/testSvg2.cpp index 171db91..2300f21 100644 --- a/test/testSvg2.cpp +++ b/test/testSvg2.cpp @@ -55,7 +55,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 7529d14..5ef33f4 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -83,7 +83,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 9c21343..3ff6c24 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -44,7 +44,7 @@ void tvgSwTest(uint32_t* buffer) { //Create a Canvas swCanvas = tvg::SwCanvas::gen(); - swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare -- 2.7.4 From a5beca736913ecb5be833fd6d36d883f92cfd329 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 18 Aug 2020 20:19:31 +0900 Subject: [PATCH 08/16] sw_engine: code refactoring introduce compositor table for runtime colorspace switching. Change-Id: If179d1e1625f995e114d66cf1bf13742c54ed4f7 --- src/lib/sw_engine/tvgSwCommon.h | 61 ++++------- src/lib/sw_engine/tvgSwFill.cpp | 10 +- src/lib/sw_engine/tvgSwRaster.cpp | 203 ++++++++++++++++++------------------ src/lib/sw_engine/tvgSwRenderer.cpp | 22 ++-- src/lib/sw_engine/tvgSwRenderer.h | 6 +- src/lib/sw_engine/tvgSwShape.cpp | 4 +- 6 files changed, 148 insertions(+), 158 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index e5d4719..ee70599 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -38,8 +38,6 @@ static double timeStamp() } #endif -using namespace tvg; - #define SW_CURVE_TYPE_POINT 0 #define SW_CURVE_TYPE_CUBIC 1 #define SW_OUTLINE_FILL_WINDING 0 @@ -215,58 +213,40 @@ struct SwShape bool rect; //Fast Track: Othogonal rectangle? }; - -static inline SwCoord TO_SWCOORD(float val) +struct SwCompositor { - return SwCoord(val * 64); -} - + uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); + uint32_t (*alpha)(uint32_t rgba); +}; -static inline uint32_t RGBA_ALPHA(uint32_t rgba) +struct SwSurface : Surface { - return rgba & 0x000000ff; -} - + SwCompositor comp; +}; -static inline uint32_t ARGB_ALPHA(uint32_t argb) +static inline SwCoord TO_SWCOORD(float val) { - return (argb >> 24) & 0xff; + return SwCoord(val * 64); } - static inline uint32_t RGBA_ALPHA_BLEND(uint32_t rgba, uint32_t alpha) { - return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) + - ((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff)); + return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) + + ((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff)); } - static inline uint32_t RGBA_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rgba2, uint32_t b) { - auto t = (((rgba1 & 0xff00ff) * a + (rgba2 & 0xff00ff) * b) >> 8) & 0xff00ff; - rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00; - return (rgba1 |= t); -} - - -static inline uint32_t RGBA_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - return (r << 24 | g << 16 | b << 8 | a); + auto t = (((rgba1 & 0xff00ff) * a + (rgba2 & 0xff00ff) * b) >> 8) & 0xff00ff; + rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00; + return (rgba1 |= t); } - -static inline uint32_t ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - return (a << 24 | r << 16 | g << 8 | b); -} - - static inline uint8_t 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 +270,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip); void shapeFree(SwShape* shape); void shapeDelStroke(SwShape* shape); -bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable); +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable); void shapeResetFill(SwShape* shape); void shapeDelFill(SwShape* shape); @@ -299,7 +279,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); SwOutline* strokeExportOutline(SwStroke* stroke); void strokeFree(SwStroke* stroke); -bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable); +bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable); void fillReset(SwFill* fill); void fillFree(SwFill* fill); void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len); @@ -308,10 +288,11 @@ void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias); void rleFree(SwRleData* rle); -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); -bool rasterStroke(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); -bool rasterClear(Surface& surface); +bool rasterCompositor(SwSurface* surface); +bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); +bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +bool rasterClear(SwSurface* surface); static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index cd68d0f..e748651 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -34,7 +34,7 @@ #define FIXPT_SIZE (1<g, pColors->a); auto b = ALPHA_MULTIPLY(pColors->b, pColors->a); - auto rgba = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, pColors->a) : ARGB_JOIN(r, g, b, pColors->a); + auto rgba = surface->comp.join(r, g, b, pColors->a); auto inc = 1.0f / static_cast(GRADIENT_STOP_SIZE); auto pos = 1.5f * inc; uint32_t i = 0; @@ -79,7 +79,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, uint32_t cs) auto g = ALPHA_MULTIPLY(next->g, next->a); auto b = ALPHA_MULTIPLY(next->b, next->a); - auto rgba2 = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, next->a) : ARGB_JOIN(r, g, b, next->a); + auto rgba2 = surface->comp.join(r, g, b, next->a); while (pos < next->offset && i < GRADIENT_STOP_SIZE) { auto t = (pos - curr->offset) * delta; @@ -282,7 +282,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, } -bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable) +bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable) { if (!fill) return false; @@ -291,7 +291,7 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, fill->spread = fdata->spread(); if (ctable) { - if (!_updateColorTable(fill, fdata, cs)) return false; + if (!_updateColorTable(fill, fdata, surface)) return false; } if (fdata->id() == FILL_ID_LINEAR) { diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index d07d7eb..072c74c 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -28,27 +28,51 @@ /* Internal Class Implementation */ /************************************************************************/ -static SwBBox _clipRegion(Surface& surface, SwBBox& in) +static uint32_t _rgbaAlpha(uint32_t rgba) +{ + return rgba & 0x000000ff; +} + + +static uint32_t _argbAlpha(uint32_t argb) +{ + return (argb >> 24) & 0xff; +} + + +static uint32_t _rgbaJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (r << 24 | g << 16 | b << 8 | a); +} + + +static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (a << 24 | r << 16 | g << 8 | b); +} + + +static SwBBox _clipRegion(Surface* surface, SwBBox& in) { auto bbox = in; if (bbox.min.x < 0) bbox.min.x = 0; if (bbox.min.y < 0) bbox.min.y = 0; - if (bbox.max.x > static_cast(surface.w)) bbox.max.x = surface.w; - if (bbox.max.y > static_cast(surface.h)) bbox.max.y = surface.h; + if (bbox.max.x > static_cast(surface->w)) bbox.max.x = surface->w; + if (bbox.max.y > static_cast(surface->h)) bbox.max.y = surface->h; return bbox; } -static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint32_t color) +static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) { - auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x; auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); - auto ialpha = 255 - (surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(color) : ARGB_ALPHA(color); + auto ialpha = 255 - surface->comp.alpha(color); for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface.stride]; + auto dst = &buffer[y * surface->stride]; for (uint32_t x = 0; x < w; ++x) { dst[x] = color + RGBA_ALPHA_BLEND(dst[x], ialpha); } @@ -57,20 +81,20 @@ static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint3 } -static bool _rasterSolidRect(Surface& surface, const SwBBox& region, uint32_t color) +static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint32_t color) { - auto buffer = surface.buffer + (region.min.y * surface.stride); + auto buffer = surface->buffer + (region.min.y * surface->stride); auto w = static_cast(region.max.x - region.min.x); auto h = static_cast(region.max.y - region.min.y); for (uint32_t y = 0; y < h; ++y) { - rasterRGBA32(buffer + y * surface.stride, color, region.min.x, w); + rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w); } return true; } -static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t color) +static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t color) { if (!rle) return false; @@ -78,10 +102,10 @@ static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t col uint32_t src; for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; if (span->coverage < 255) src = RGBA_ALPHA_BLEND(color, span->coverage); else src = color; - auto ialpha = 255 - ((surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(src) : ARGB_ALPHA(src)); + auto ialpha = 255 - surface->comp.alpha(src); for (uint32_t i = 0; i < span->len; ++i) { dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha); } @@ -91,7 +115,7 @@ static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t col } -static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) +static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color) { if (!rle) return false; @@ -99,9 +123,9 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) for (uint32_t i = 0; i < rle->size; ++i) { if (span->coverage == 255) { - rasterRGBA32(surface.buffer + span->y * surface.stride, color, span->x, span->len); + rasterRGBA32(surface->buffer + span->y * surface->stride, color, span->x, span->len); } else { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto src = RGBA_ALPHA_BLEND(color, span->coverage); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { @@ -114,74 +138,62 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) } -static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, const SwFill* fill) +static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { if (!fill) return false; - auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x; auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); //Translucent Gradient if (fill->translucent) { - auto tmpBuf = static_cast(alloca(surface.w * sizeof(uint32_t))); + auto tmpBuf = static_cast(alloca(surface->w * sizeof(uint32_t))); if (!tmpBuf) return false; for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface.stride]; + auto dst = &buffer[y * surface->stride]; fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w); - if (surface.cs == SwCanvas::RGBA8888) { - for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - RGBA_ALPHA(tmpBuf[x])); - } - } else { - for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - ARGB_ALPHA(tmpBuf[x])); - } + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); } } //Opaque Gradient } else { for (uint32_t y = 0; y < h; ++y) { - fillFetchLinear(fill, buffer + y * surface.stride, region.min.y + y, region.min.x, 0, w); + fillFetchLinear(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, 0, w); } } return true; } -static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, const SwFill* fill) +static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { if (!fill) return false; - auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x; + auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x; auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); //Translucent Gradient if (fill->translucent) { - auto tmpBuf = static_cast(alloca(surface.w * sizeof(uint32_t))); + auto tmpBuf = static_cast(alloca(surface->w * sizeof(uint32_t))); if (!tmpBuf) return false; for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface.stride]; + auto dst = &buffer[y * surface->stride]; fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w); - if (surface.cs == SwCanvas::RGBA8888) { - for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - RGBA_ALPHA(tmpBuf[x])); - } - } else { - for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - ARGB_ALPHA(tmpBuf[x])); - } + for (uint32_t x = 0; x < w; ++x) { + dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); } } //Opaque Gradient } else { for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface.stride]; + auto dst = &buffer[y * surface->stride]; fillFetchRadial(fill, dst, region.min.y + y, region.min.x, w); } } @@ -189,11 +201,11 @@ static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, co } -static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwFill* fill) +static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const SwFill* fill) { if (!rle || !fill) return false; - auto buf = static_cast(alloca(surface.w * sizeof(uint32_t))); + auto buf = static_cast(alloca(surface->w * sizeof(uint32_t))); if (!buf) return false; auto span = rle->spans; @@ -201,29 +213,16 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF //Translucent Gradient if (fill->translucent) { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); - if (surface.cs == SwCanvas::RGBA8888) { - if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(buf[i])); - } - } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(tmp)); - } + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); } } else { - if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(buf[i])); - } - } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(tmp)); - } + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); } } ++span; @@ -232,9 +231,9 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF } else { for (uint32_t i = 0; i < rle->size; ++i) { if (span->coverage == 255) { - fillFetchLinear(fill, surface.buffer + span->y * surface.stride, span->y, span->x, span->x, span->len); + fillFetchLinear(fill, surface->buffer + span->y * surface->stride, span->y, span->x, span->x, span->len); } else { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { @@ -248,11 +247,11 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF } -static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwFill* fill) +static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const SwFill* fill) { if (!rle || !fill) return false; - auto buf = static_cast(alloca(surface.w * sizeof(uint32_t))); + auto buf = static_cast(alloca(surface->w * sizeof(uint32_t))); if (!buf) return false; auto span = rle->spans; @@ -260,29 +259,16 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF //Translucent Gradient if (fill->translucent) { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; fillFetchRadial(fill, buf, span->y, span->x, span->len); - if (surface.cs == SwCanvas::RGBA8888) { - if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(buf[i])); - } - } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(tmp)); - } + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); } } else { - if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(buf[i])); - } - } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(tmp)); - } + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); } } ++span; @@ -290,7 +276,7 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF //Opaque Gradient } else { for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface.buffer[span->y * surface.stride + span->x]; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; if (span->coverage == 255) { fillFetchRadial(fill, dst, span->y, span->x, span->len); } else { @@ -311,7 +297,24 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF /* External Class Implementation */ /************************************************************************/ -bool rasterGradientShape(Surface& surface, SwShape* shape, unsigned id) +bool rasterCompositor(SwSurface* surface) +{ + if (surface->cs == SwCanvas::RGBA8888) { + surface->comp.alpha = _rgbaAlpha; + surface->comp.join = _rgbaJoin; + } else if (surface->cs == SwCanvas::ARGB8888) { + surface->comp.alpha = _argbAlpha; + surface->comp.join = _argbJoin; + } else { + //What Color Space ??? + return false; + } + + return true; +} + + +bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id) { //Fast Track if (shape->rect) { @@ -326,13 +329,13 @@ 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) +bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { r = ALPHA_MULTIPLY(r, a); g = ALPHA_MULTIPLY(g, a); b = ALPHA_MULTIPLY(b, a); - auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a); + auto color = surface->comp.join(r, g, b, a); //Fast Track if (shape->rect) { @@ -347,28 +350,28 @@ 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 rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { r = ALPHA_MULTIPLY(r, a); g = ALPHA_MULTIPLY(g, a); b = ALPHA_MULTIPLY(b, a); - auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a); + auto color = surface->comp.join(r, g, b, a); if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color); return _rasterTranslucentRle(surface, shape->strokeRle, color); } -bool rasterClear(Surface& surface) +bool rasterClear(SwSurface* surface) { - if (!surface.buffer || surface.stride <= 0 || surface.w <= 0 || surface.h <= 0) return false; + if (!surface || !surface->buffer || surface->stride <= 0 || surface->w <= 0 || surface->h <= 0) return false; - if (surface.w == surface.stride) { - rasterRGBA32(surface.buffer, 0x00000000, 0, surface.w * surface.h); + if (surface->w == surface->stride) { + rasterRGBA32(surface->buffer, 0x00000000, 0, surface->w * surface->h); } else { - for (uint32_t i = 0; i < surface.h; i++) { - rasterRGBA32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w); + for (uint32_t i = 0; i < surface->h; i++) { + rasterRGBA32(surface->buffer + surface->stride * i, 0x00000000, 0, surface->w); } } return true; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 66608f5..8d02b40 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -37,6 +37,7 @@ static RenderInitializer renderInit; SwRenderer::~SwRenderer() { + if (surface) delete(surface); } @@ -44,13 +45,18 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t { if (!buffer || stride == 0 || w == 0 || h == 0) return false; - surface.buffer = buffer; - surface.stride = stride; - surface.w = w; - surface.h = h; - surface.cs = cs; + if (!surface) { + surface = new SwSurface; + if (!surface) return false; + } - return true; + surface->buffer = buffer; + surface->stride = stride; + surface->w = w; + surface->h = h; + surface->cs = cs; + + return rasterCompositor(surface); } @@ -100,7 +106,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* if (flags == RenderUpdateFlag::None) return shape; - SwSize clip = {static_cast(surface.w), static_cast(surface.h)}; + SwSize clip = {static_cast(surface->w), static_cast(surface->h)}; //Valid Stroking? uint8_t strokeAlpha = 0; @@ -130,7 +136,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* if (fill) { auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; if (ctable) shapeResetFill(shape); - if (!shapeGenFillColors(shape, fill, matrix, surface.cs, ctable)) return shape; + if (!shapeGenFillColors(shape, fill, matrix, surface, ctable)) return shape; } else { shapeDelFill(shape); } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 5657602..2185f34 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -22,11 +22,11 @@ #ifndef _TVG_SW_RENDERER_H_ #define _TVG_SW_RENDERER_H_ +struct SwSurface; + namespace tvg { -struct SwTask; - class SwRenderer : public RenderMethod { public: @@ -43,7 +43,7 @@ public: static int term(); private: - Surface surface = {nullptr, 0, 0, 0}; + SwSurface* surface = nullptr; SwRenderer(){}; ~SwRenderer(); diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 3704a2c..c94ef26 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -672,9 +672,9 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo } -bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable) +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable) { - return fillGenColorTable(shape->fill, fill, transform, cs, ctable); + return fillGenColorTable(shape->fill, fill, transform, surface, ctable); } -- 2.7.4 From 70b4703707a1bd5ebc4ffa372a4fe2dce86ce83f Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 18 Aug 2020 20:35:13 +0900 Subject: [PATCH 09/16] remove print/cout logs. we need a comprehensive logging interface for this. right now, leave as "LOG:" to replace later. Change-Id: I25321223cd48ec13a1de5e4140cfea75a2f42866 --- src/lib/sw_engine/tvgSwFill.cpp | 2 +- src/lib/sw_engine/tvgSwRle.cpp | 6 +++--- src/lib/sw_engine/tvgSwStroke.cpp | 4 +++- src/lib/tvgPictureImpl.h | 4 ++-- src/loaders/svg/tvgSvgLoader.cpp | 14 +++++++------- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index e748651..1539c17 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -300,7 +300,7 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, return _prepareRadial(fill, static_cast(fdata), transform); } - cout << "What type of gradient?!" << endl; + //LOG: What type of gradient?! return false; } diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index 6f1f2f2..fb4b87b 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -193,11 +193,11 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor //span has ushort coordinates. check limit overflow if (x >= SHRT_MAX) { - cout << "x(" << x << ") coordinate overflow!" << endl; + //LOG: x coordinate overflow! x = SHRT_MAX; } if (y >= SHRT_MAX) { - cout << "y(" << y << ") coordinate overflow!" << endl; + //LOG: y coordinate overflow! y = SHRT_MAX; } @@ -616,7 +616,7 @@ static bool _decomposeOutline(RleWorker& rw) return true; invalid_outline: - cout << "Invalid Outline!" << endl; + //LOG: Invalid Outline! return false; } diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index fbe28c1..94c738c 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -812,7 +812,9 @@ static void _exportBorderOutline(SwStroke& stroke, SwOutline* outline, uint32_t if (*src & SW_STROKE_TAG_POINT) *tags = SW_CURVE_TYPE_POINT; else if (*src & SW_STROKE_TAG_CUBIC) *tags = SW_CURVE_TYPE_CUBIC; - else cout << "what type of stroke outline??" << endl; + else { + //LOG: What type of stroke outline?? + } if (*src & SW_STROKE_TAG_END) { *cntrs = idx; diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 5ab9618..d430de4 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -86,7 +86,7 @@ struct Picture::Impl if (loader) loader->close(); loader = LoaderMgr::loader(); if (!loader || !loader->open(path.c_str())) { - cout << "Non supported format: " << path.c_str() << endl; + //LOG: Non supported format return Result::NonSupport; } if (!loader->read()) return Result::Unknown; @@ -98,7 +98,7 @@ struct Picture::Impl if (loader) loader->close(); loader = LoaderMgr::loader(); if (!loader || !loader->open(data, size)) { - cout << "Non supported load data" << endl; + //LOG: Non supported load data return Result::NonSupport; } if (!loader->read()) return Result::Unknown; diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 1579390..f1d9432 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -1118,7 +1118,7 @@ static SvgNode* _createEllipseNode(SvgLoaderData* loader, SvgNode* parent, const } -static void _attrParsePolygonPoints(const char* str, float** points, int* ptCount) +static bool _attrParsePolygonPoints(const char* str, float** points, int* ptCount) { float tmp[50]; int tmpCount = 0; @@ -1147,11 +1147,11 @@ static void _attrParsePolygonPoints(const char* str, float** points, int* ptCoun } *ptCount = count; *points = pointArray; - return; + return true; error_alloc: - printf("ERR : allocation for point array failed. out of memory"); - abort(); + //LOG: allocation for point array failed. out of memory + return false; } @@ -1168,7 +1168,7 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value else polygon = &(node->node.polyline); if (!strcmp(key, "points")) { - _attrParsePolygonPoints(value, &polygon->points, &polygon->pointsCount); + return _attrParsePolygonPoints(value, &polygon->points, &polygon->pointsCount); } else if (!strcmp(key, "style")) { return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); } else if (!strcmp(key, "id")) { @@ -2298,7 +2298,7 @@ bool SvgLoader::header() this->vw = loaderData.doc->node.doc.vw; this->vh = loaderData.doc->node.doc.vh; } else { - cout << "ERROR : No SVG File. There is no " < return false; } @@ -2322,7 +2322,7 @@ bool SvgLoader::open(const char* path) if (!f.is_open()) { - cout << "ERROR: Failed to open file = " << path; + //LOG: Failed to open file return false; } else { getline(f, filePath, '\0'); -- 2.7.4 From ffa4a7248baf1ce68763f8243a7f25be9feba5f3 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 19 Aug 2020 14:50:49 +0900 Subject: [PATCH 10/16] code refactoring Now, stabilizing is pretty enough. Remove assert code so that we never abort process in any cases. This also reduce the binary size. Change-Id: Ia7d2d5c5a0757b12481eaebad7a86aade6a89c1e --- src/lib/sw_engine/tvgSwFill.cpp | 11 +---------- src/lib/sw_engine/tvgSwMath.cpp | 2 -- src/lib/sw_engine/tvgSwRenderer.cpp | 2 +- src/lib/sw_engine/tvgSwRle.cpp | 13 ------------- src/lib/sw_engine/tvgSwShape.cpp | 21 --------------------- src/lib/sw_engine/tvgSwStroke.cpp | 36 ++---------------------------------- src/lib/tvgCommon.h | 1 - src/lib/tvgGlCanvas.cpp | 5 +---- src/lib/tvgLinearGradient.cpp | 5 +---- src/lib/tvgRadialGradient.cpp | 5 +---- src/lib/tvgRender.cpp | 2 -- src/lib/tvgRender.h | 3 --- src/lib/tvgShapeImpl.h | 3 --- src/lib/tvgShapePath.h | 2 -- src/lib/tvgSwCanvas.cpp | 5 +---- 15 files changed, 8 insertions(+), 108 deletions(-) diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 1539c17..ccc0574 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -36,11 +36,9 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surface) { - assert(fill && fdata); - if (!fill->ctable) { fill->ctable = static_cast(malloc(GRADIENT_STOP_SIZE * sizeof(uint32_t))); - assert(fill->ctable); + if (!fill->ctable) return false; } const Fill::ColorStop* colors; @@ -71,7 +69,6 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac for (uint32_t j = 0; j < cnt - 1; ++j) { auto curr = colors + j; auto next = curr + 1; - assert(curr && next); auto delta = 1.0f / (next->offset - curr->offset); if (next->a < 255) fill->translucent = true; @@ -104,8 +101,6 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* transform) { - assert(fill && linear); - float x1, x2, y1, y2; if (linear->linear(&x1, &y1, &x2, &y2) != Result::Success) return false; @@ -140,8 +135,6 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix* transform) { - assert(fill && radial); - float radius; if (radial->radial(&fill->radial.cx, &fill->radial.cy, &radius) != Result::Success) return false; if (radius < FLT_EPSILON) return true; @@ -286,8 +279,6 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, { if (!fill) return false; - assert(fdata); - fill->spread = fdata->spread(); if (ctable) { diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index 5ac3912..5227d79 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -384,8 +384,6 @@ SwFixed mathLength(SwPoint& pt) void mathSplitCubic(SwPoint* base) { - assert(base); - SwCoord a, b, c, d; base[6].x = base[3].x; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 8d02b40..b173ce4 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -101,7 +101,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* auto shape = static_cast(data); if (!shape) { shape = static_cast(calloc(1, sizeof(SwShape))); - assert(shape); + if (!shape) return nullptr; } if (flags == RenderUpdateFlag::None) return shape; diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index fb4b87b..c9aa6ae 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -145,8 +145,6 @@ static inline SwCoord HYPOT(SwPoint pt) static void _genSpan(SwRleData* rle, SwSpan* spans, uint32_t count) { - assert(rle && spans); - auto newSize = rle->size + count; /* allocate enough memory for new spans */ @@ -155,12 +153,10 @@ static void _genSpan(SwRleData* rle, SwSpan* spans, uint32_t count) if (rle->alloc < newSize) { rle->alloc = (newSize * 2); rle->spans = static_cast(realloc(rle->spans, rle->alloc * sizeof(SwSpan))); - assert(rle->spans); } //copy the new spans to the allocated memory SwSpan* lastSpan = rle->spans + rle->size; - assert(lastSpan); memcpy(lastSpan, spans, count * sizeof(SwSpan)); rle->size = newSize; @@ -205,7 +201,6 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor if (!rw.antiAlias) coverage = 255; auto count = rw.spansCnt; auto span = rw.spans + count - 1; - assert(span); //see whether we can add this span to the current list if ((count > 0) && (rw.ySpan == y) && @@ -226,10 +221,8 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor rw.spansCnt = 0; rw.ySpan = 0; span = rw.spans; - assert(span); } else { ++span; - assert(span); } //Clip x range @@ -290,7 +283,6 @@ static Cell* _findCell(RleWorker& rw) if (x > rw.cellXCnt) x = rw.cellXCnt; auto pcell = &rw.yCells[rw.cellPos.y]; - assert(pcell); while(true) { Cell* cell = *pcell; @@ -302,7 +294,6 @@ static Cell* _findCell(RleWorker& rw) if (rw.cellsCnt >= rw.maxCells) longjmp(rw.jmpBuf, 1); auto cell = rw.cells + rw.cellsCnt++; - assert(cell); cell->x = x; cell->area = 0; cell->cover = 0; @@ -317,7 +308,6 @@ static void _recordCell(RleWorker& rw) { if (rw.area | rw.cover) { auto cell = _findCell(rw); - assert(cell); cell->area += rw.area; cell->cover += rw.cover; } @@ -498,8 +488,6 @@ static void _lineTo(RleWorker& rw, const SwPoint& to) static void _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to) { auto arc = rw.bezStack; - assert(arc); - arc[0] = to; arc[1] = ctrl2; arc[2] = ctrl1; @@ -668,7 +656,6 @@ SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& rw.clip = clip; rw.antiAlias = antiAlias; rw.rle = reinterpret_cast(calloc(1, sizeof(SwRleData))); - assert(rw.rle); //Generate RLE Band bands[BAND_SIZE]; diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index c94ef26..f14d3b6 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -76,7 +76,6 @@ static void _growOutlineContour(SwOutline& outline, uint32_t n) if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return; outline.reservedCntrsCnt = outline.cntrsCnt + n; outline.cntrs = static_cast(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t))); - assert(outline.cntrs); } @@ -85,9 +84,7 @@ static void _growOutlinePoint(SwOutline& outline, uint32_t n) if (outline.reservedPtsCnt >= outline.ptsCnt + n) return; outline.reservedPtsCnt = outline.ptsCnt + n; outline.pts = static_cast(realloc(outline.pts, outline.reservedPtsCnt * sizeof(SwPoint))); - assert(outline.pts); outline.types = static_cast(realloc(outline.types, outline.reservedPtsCnt * sizeof(uint8_t))); - assert(outline.types); } @@ -114,8 +111,6 @@ static void _outlineEnd(SwOutline& outline) static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform) { - assert(to); - _growOutlinePoint(outline, 1); outline.pts[outline.ptsCnt] = _transform(to, transform); @@ -134,8 +129,6 @@ static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* tr static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* transform) { - assert(to); - _growOutlinePoint(outline, 1); outline.pts[outline.ptsCnt] = _transform(to, transform); @@ -146,8 +139,6 @@ static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* tr static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* to, const Matrix* transform) { - assert(ctrl1 && ctrl2 && to); - _growOutlinePoint(outline, 3); outline.pts[outline.ptsCnt] = _transform(ctrl1, transform); @@ -203,7 +194,6 @@ static bool _updateBBox(SwOutline* outline, SwBBox& bbox) if (!outline) return false; auto pt = outline->pts; - assert(pt); if (outline->ptsCnt <= 0) { _initBBox(bbox); @@ -236,8 +226,6 @@ static bool _updateBBox(SwOutline* outline, SwBBox& bbox) static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip) { - assert(outline); - if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) return false; //Check boundary @@ -341,8 +329,6 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform) { - assert(sdata); - const PathCommand* cmds = nullptr; auto cmdCnt = sdata->pathCommands(&cmds); @@ -361,12 +347,10 @@ SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform) const float* pattern; dash.cnt = sdata->strokeDash(&pattern); - assert(dash.cnt > 0 && pattern); //Is it safe to mutual exclusive? dash.pattern = const_cast(pattern); dash.outline = static_cast(calloc(1, sizeof(SwOutline))); - assert(dash.outline); dash.outline->opened = true; //smart reservation @@ -510,8 +494,6 @@ void shapeReset(SwShape* shape) bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform) { - assert(sdata); - const PathCommand* cmds = nullptr; auto cmdCnt = sdata->pathCommands(&cmds); @@ -552,7 +534,6 @@ bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform auto outline = shape->outline; if (!outline) outline = static_cast(calloc(1, sizeof(SwOutline))); - assert(outline); outline->opened = true; _growOutlinePoint(*outline, outlinePtsCnt); @@ -638,8 +619,6 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip) { - assert(sdata); - SwOutline* shapeOutline = nullptr; //Dash Style Stroke diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index 94c738c..8400237 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -48,8 +48,6 @@ static inline void SCALE(SwStroke& stroke, SwPoint& pt) static void _growBorder(SwStrokeBorder* border, uint32_t newPts) { - assert(border); - auto maxOld = border->maxPts; auto maxNew = border->ptsCnt + newPts; @@ -61,21 +59,15 @@ static void _growBorder(SwStrokeBorder* border, uint32_t newPts) maxCur += (maxCur >> 1) + 16; border->pts = static_cast(realloc(border->pts, maxCur * sizeof(SwPoint))); - assert(border->pts); - border->tags = static_cast(realloc(border->tags, maxCur * sizeof(uint8_t))); - assert(border->tags); - border->maxPts = maxCur; } static void _borderClose(SwStrokeBorder* border, bool reverse) { - assert(border && border->start >= 0); - - uint32_t start = border->start; - uint32_t count = border->ptsCnt; + auto start = border->start; + auto count = border->ptsCnt; //Don't record empty paths! if (count <= start + 1U) { @@ -123,8 +115,6 @@ static void _borderClose(SwStrokeBorder* border, bool reverse) static void _borderCubicTo(SwStrokeBorder* border, SwPoint& ctrl1, SwPoint& ctrl2, SwPoint& to) { - assert(border && border->start >= 0); - _growBorder(border, 3); auto pt = border->pts + border->ptsCnt; @@ -199,8 +189,6 @@ static void _borderArcTo(SwStrokeBorder* border, SwPoint& center, SwFixed radius static void _borderLineTo(SwStrokeBorder* border, SwPoint& to, bool movable) { - assert(border && border->start >= 0); - if (border->movable) { //move last point border->pts[border->ptsCnt - 1] = to; @@ -221,8 +209,6 @@ static void _borderLineTo(SwStrokeBorder* border, SwPoint& to, bool movable) static void _borderMoveTo(SwStrokeBorder* border, SwPoint& to) { - assert(border); - //close current open path if any? if (border->start >= 0) _borderClose(border, false); @@ -249,10 +235,7 @@ static void _outside(SwStroke& stroke, int32_t side, SwFixed lineLength) { constexpr SwFixed MITER_LIMIT = 4 * (1 << 16); - assert(MITER_LIMIT >= 0x10000); - auto border = stroke.borders + side; - assert(border); if (stroke.join == StrokeJoin::Round) { _arcTo(stroke, side); @@ -640,8 +623,6 @@ static void _addReverseLeft(SwStroke& stroke, bool opened) { auto right = stroke.borders + 0; auto left = stroke.borders + 1; - assert(left->start >= 0); - auto newPts = left->ptsCnt - left->start; if (newPts <= 0) return; @@ -708,7 +689,6 @@ static void _endSubPath(SwStroke& stroke) { if (stroke.openSubPath) { auto right = stroke.borders; - assert(right); /* all right, this is an opened path, we need to add a cap between right & left, add the reverse of left, then add a final cap @@ -756,8 +736,6 @@ static void _endSubPath(SwStroke& stroke) static void _getCounts(SwStrokeBorder* border, uint32_t& ptsCnt, uint32_t& cntrsCnt) { - assert(border); - auto count = border->ptsCnt; auto tags = border->tags; uint32_t _ptsCnt = 0; @@ -796,7 +774,6 @@ fail: static void _exportBorderOutline(SwStroke& stroke, SwOutline* outline, uint32_t side) { auto border = stroke.borders + side; - assert(border); if (!border->valid) return; @@ -850,8 +827,6 @@ void strokeFree(SwStroke* stroke) void strokeReset(SwStroke* stroke, const Shape* sdata, const Matrix* transform) { - assert(sdata); - if (transform) { stroke->sx = sqrt(pow(transform->e11, 2) + pow(transform->e21, 2)); stroke->sy = sqrt(pow(transform->e12, 2) + pow(transform->e22, 2)); @@ -941,16 +916,9 @@ SwOutline* strokeExportOutline(SwStroke* stroke) auto cntrsCnt = count2 + count4; auto outline = static_cast(calloc(1, sizeof(SwOutline))); - assert(outline); - outline->pts = static_cast(malloc(sizeof(SwPoint) * ptsCnt)); - assert(outline->pts); - outline->types = static_cast(malloc(sizeof(uint8_t) * ptsCnt)); - assert(outline->types); - outline->cntrs = static_cast(malloc(sizeof(uint32_t) * cntrsCnt)); - assert(outline->cntrs); _exportBorderOutline(*stroke, outline, 0); //left _exportBorderOutline(*stroke, outline, 1); //right diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 0c73b91..66e08bf 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -25,7 +25,6 @@ #include "config.h" #include -#include #include #include #include diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index 1ac5732..e1b5c3c 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -81,10 +81,7 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t unique_ptr GlCanvas::gen() noexcept { #ifdef THORVG_GL_RASTER_SUPPORT - auto canvas = unique_ptr(new GlCanvas); - assert(canvas); - - return canvas; + return unique_ptr(new GlCanvas); #endif return nullptr; } diff --git a/src/lib/tvgLinearGradient.cpp b/src/lib/tvgLinearGradient.cpp index 68a0d8a..bd2dbc1 100644 --- a/src/lib/tvgLinearGradient.cpp +++ b/src/lib/tvgLinearGradient.cpp @@ -76,10 +76,7 @@ Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const unique_ptr LinearGradient::gen() noexcept { - auto fill = unique_ptr(new LinearGradient); - assert(fill); - - return fill; + return unique_ptr(new LinearGradient); } #endif /* _TVG_LINEAR_GRADIENT_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgRadialGradient.cpp b/src/lib/tvgRadialGradient.cpp index 179c51e..9f123bf 100644 --- a/src/lib/tvgRadialGradient.cpp +++ b/src/lib/tvgRadialGradient.cpp @@ -73,10 +73,7 @@ Result RadialGradient::radial(float* cx, float* cy, float* radius) const noexcep unique_ptr RadialGradient::gen() noexcept { - auto fill = unique_ptr(new RadialGradient); - assert(fill); - - return fill; + return unique_ptr(new RadialGradient); } #endif /* _TVG_RADIAL_GRADIENT_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgRender.cpp b/src/lib/tvgRender.cpp index b1e8cf0..30bc906 100644 --- a/src/lib/tvgRender.cpp +++ b/src/lib/tvgRender.cpp @@ -107,8 +107,6 @@ RenderTransform::RenderTransform() RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs) { - assert(lhs && rhs); - m.e11 = lhs->m.e11 * rhs->m.e11 + lhs->m.e12 * rhs->m.e21 + lhs->m.e13 * rhs->m.e31; m.e12 = lhs->m.e11 * rhs->m.e12 + lhs->m.e12 * rhs->m.e22 + lhs->m.e13 * rhs->m.e32; m.e13 = lhs->m.e11 * rhs->m.e13 + lhs->m.e12 * rhs->m.e23 + lhs->m.e13 * rhs->m.e33; diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 3535bf4..c379d0e 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -76,7 +76,6 @@ struct RenderInitializer static bool init(RenderInitializer& renderInit, RenderMethod* engine) { - assert(engine); if (renderInit.pInst || renderInit.refCnt > 0) return false; renderInit.pInst = engine; renderInit.refCnt = 0; @@ -100,7 +99,6 @@ struct RenderInitializer static uint32_t unref(RenderInitializer& renderInit) { - assert(renderInit.refCnt > 0); --renderInit.refCnt; //engine has been requested to termination @@ -115,7 +113,6 @@ struct RenderInitializer static RenderMethod* inst(RenderInitializer& renderInit) { - assert(renderInit.pInst); return renderInit.pInst; } diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 1b85c07..612bfe3 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -144,8 +144,6 @@ struct Shape::Impl bool strokeDash(const float* pattern, uint32_t cnt) { - assert(pattern); - if (!stroke) stroke = new ShapeStroke(); if (!stroke) return false; @@ -155,7 +153,6 @@ struct Shape::Impl } if (!stroke->dashPattern) stroke->dashPattern = static_cast(malloc(sizeof(float) * cnt)); - assert(stroke->dashPattern); for (uint32_t i = 0; i < cnt; ++i) stroke->dashPattern[i] = pattern[i]; diff --git a/src/lib/tvgShapePath.h b/src/lib/tvgShapePath.h index 75c86ad..04934dc 100644 --- a/src/lib/tvgShapePath.h +++ b/src/lib/tvgShapePath.h @@ -50,7 +50,6 @@ struct ShapePath if (cmdCnt <= reservedCmdCnt) return; reservedCmdCnt = cmdCnt; cmds = static_cast(realloc(cmds, sizeof(PathCommand) * reservedCmdCnt)); - assert(cmds); } void reservePts(uint32_t ptsCnt) @@ -58,7 +57,6 @@ struct ShapePath if (ptsCnt <= reservedPtsCnt) return; reservedPtsCnt = ptsCnt; pts = static_cast(realloc(pts, sizeof(Point) * reservedPtsCnt)); - assert(pts); } void grow(uint32_t cmdCnt, uint32_t ptsCnt) diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index 755d422..5d280fd 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -80,10 +80,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t unique_ptr SwCanvas::gen() noexcept { #ifdef THORVG_SW_RASTER_SUPPORT - auto canvas = unique_ptr(new SwCanvas); - assert(canvas); - - return canvas; + return unique_ptr(new SwCanvas); #endif return nullptr; } -- 2.7.4 From 06d8d06993118b386a40b341db92a567d662068e Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 19 Aug 2020 18:32:32 +0900 Subject: [PATCH 11/16] sw_engine: replace rgba8888 with abgr8888 Actually Dali rendering system requires abgr8888. We could add more colorspaces if it's necessary. Change-Id: Ia42a6575d1313629e55efc3077e302992c47b6c0 --- inc/thorvg.h | 2 +- inc/thorvg_capi.h | 2 +- src/lib/sw_engine/tvgSwCommon.h | 14 +++++------ src/lib/sw_engine/tvgSwFill.cpp | 2 +- src/lib/sw_engine/tvgSwRaster.cpp | 52 +++++++++++++++++---------------------- 5 files changed, 33 insertions(+), 39 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 9ed5498..18013fa 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -311,7 +311,7 @@ class TVG_EXPORT SwCanvas final : public Canvas public: ~SwCanvas(); - enum Colorspace { RGBA8888 = 0, ARGB8888 }; + enum Colorspace { ABGR8888 = 0, ARGB8888 }; Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept; diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 2f1bf96..811c82e 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -23,7 +23,7 @@ typedef struct _Tvg_Gradient Tvg_Gradient; #define TVG_ENGINE_SW (1 << 1) #define TVG_ENGINE_GL (1 << 2) -#define TVG_COLORSPACE_RGBA8888 0 +#define TVG_COLORSPACE_ABGR8888 0 #define TVG_COLORSPACE_ARGB8888 1 typedef enum { diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index ee70599..a600cb9 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -229,17 +229,17 @@ static inline SwCoord TO_SWCOORD(float val) return SwCoord(val * 64); } -static inline uint32_t RGBA_ALPHA_BLEND(uint32_t rgba, uint32_t alpha) +static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a) { - return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) + - ((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff)); + return (((((c >> 8) & 0x00ff00ff) * a) & 0xff00ff00) + + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff)); } -static inline uint32_t RGBA_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rgba2, uint32_t b) +static inline uint32_t COLOR_INTERPOLATE(uint32_t c1, uint32_t a1, uint32_t c2, uint32_t a2) { - auto t = (((rgba1 & 0xff00ff) * a + (rgba2 & 0xff00ff) * b) >> 8) & 0xff00ff; - rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00; - return (rgba1 |= t); + auto t = (((c1 & 0xff00ff) * a1 + (c2 & 0xff00ff) * a2) >> 8) & 0xff00ff; + c1 = (((c1 >> 8) & 0xff00ff) * a1 + ((c2 >> 8) & 0xff00ff) * a2) & 0xff00ff00; + return (c1 |= t); } static inline uint8_t ALPHA_MULTIPLY(uint32_t c, uint32_t a) diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index ccc0574..72e702b 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -82,7 +82,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac auto t = (pos - curr->offset) * delta; auto dist = static_cast(256 * t); auto dist2 = 256 - dist; - fill->ctable[i] = RGBA_INTERPOLATE(rgba, dist2, rgba2, dist); + fill->ctable[i] = COLOR_INTERPOLATE(rgba, dist2, rgba2, dist); ++i; pos += inc; } diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 072c74c..3fec524 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -28,21 +28,15 @@ /* Internal Class Implementation */ /************************************************************************/ -static uint32_t _rgbaAlpha(uint32_t rgba) +static uint32_t _colorAlpha(uint32_t c) { - return rgba & 0x000000ff; + return (c >> 24) & 0xff; } -static uint32_t _argbAlpha(uint32_t argb) +static uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return (argb >> 24) & 0xff; -} - - -static uint32_t _rgbaJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - return (r << 24 | g << 16 | b << 8 | a); + return (a << 24 | b << 16 | g << 8 | r); } @@ -74,7 +68,7 @@ static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uin for (uint32_t y = 0; y < h; ++y) { auto dst = &buffer[y * surface->stride]; for (uint32_t x = 0; x < w; ++x) { - dst[x] = color + RGBA_ALPHA_BLEND(dst[x], ialpha); + dst[x] = color + ALPHA_BLEND(dst[x], ialpha); } } return true; @@ -103,11 +97,11 @@ static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t c for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface->buffer[span->y * surface->stride + span->x]; - if (span->coverage < 255) src = RGBA_ALPHA_BLEND(color, span->coverage); + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); else src = color; auto ialpha = 255 - surface->comp.alpha(src); for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha); + dst[i] = src + ALPHA_BLEND(dst[i], ialpha); } ++span; } @@ -126,10 +120,10 @@ static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color) rasterRGBA32(surface->buffer + span->y * surface->stride, color, span->x, span->len); } else { auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto src = RGBA_ALPHA_BLEND(color, span->coverage); + auto src = ALPHA_BLEND(color, span->coverage); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha); + dst[i] = src + ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -156,7 +150,7 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, auto dst = &buffer[y * surface->stride]; fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w); for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); + dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); } } //Opaque Gradient @@ -187,7 +181,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, auto dst = &buffer[y * surface->stride]; fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w); for (uint32_t x = 0; x < w; ++x) { - dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); + dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); } } //Opaque Gradient @@ -217,12 +211,12 @@ static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const S fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); if (span->coverage == 255) { for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); + dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); } } else { for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); + auto tmp = ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); } } ++span; @@ -237,7 +231,7 @@ static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const S fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = RGBA_ALPHA_BLEND(buf[i], span->coverage) + RGBA_ALPHA_BLEND(dst[i], ialpha); + dst[i] = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -263,12 +257,12 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S fillFetchRadial(fill, buf, span->y, span->x, span->len); if (span->coverage == 255) { for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); + dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); } } else { for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); + auto tmp = ALPHA_BLEND(buf[i], span->coverage); + dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); } } ++span; @@ -283,7 +277,7 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S fillFetchRadial(fill, buf, span->y, span->x, span->len); auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = RGBA_ALPHA_BLEND(buf[i], span->coverage) + RGBA_ALPHA_BLEND(dst[i], ialpha); + dst[i] = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -299,11 +293,11 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S bool rasterCompositor(SwSurface* surface) { - if (surface->cs == SwCanvas::RGBA8888) { - surface->comp.alpha = _rgbaAlpha; - surface->comp.join = _rgbaJoin; + if (surface->cs == SwCanvas::ABGR8888) { + surface->comp.alpha = _colorAlpha; + surface->comp.join = _abgrJoin; } else if (surface->cs == SwCanvas::ARGB8888) { - surface->comp.alpha = _argbAlpha; + surface->comp.alpha = _colorAlpha; surface->comp.join = _argbJoin; } else { //What Color Space ??? -- 2.7.4 From 9d58643a6c17ba4479734ef9a296d168d57ce153 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 12:18:51 +0900 Subject: [PATCH 12/16] sw_engine: fix loss of data when it's converting. if SwCoord type is determined to 4byte, it could lose remarkable value that occur stroking jiggling. This fixes the issue. Change-Id: Ib2fed2a3bfc9188a30522f35837439364d446a73 --- src/lib/sw_engine/tvgSwMath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index 5227d79..b3cf477 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -29,7 +29,7 @@ /* Internal Class Implementation */ /************************************************************************/ -constexpr SwCoord CORDIC_FACTOR = 0xDBD95B16UL; //the Cordic shrink factor 0.858785336480436 * 2^32 +constexpr SwFixed CORDIC_FACTOR = 0xDBD95B16UL; //the Cordic shrink factor 0.858785336480436 * 2^32 //this table was generated for SW_FT_PI = 180L << 16, i.e. degrees constexpr static auto ATAN_MAX = 23; -- 2.7.4 From 04c6295974b404dee9b8e89833acdd45bce64948 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 16:16:46 +0900 Subject: [PATCH 13/16] code refactoring remove unnecessary condition. implementation won't be included multiple times not like headers. Thus this condition is unnecessary. Change-Id: Id37e675c40ce7213a06c950da8e5ca17ff7245c9 --- src/lib/gl_engine/tvgGlRenderer.cpp | 8 +------- src/lib/sw_engine/tvgSwFill.cpp | 7 +------ src/lib/sw_engine/tvgSwMath.cpp | 6 +----- src/lib/sw_engine/tvgSwRaster.cpp | 7 +------ src/lib/sw_engine/tvgSwRenderer.cpp | 7 +------ src/lib/sw_engine/tvgSwRle.cpp | 7 +------ src/lib/sw_engine/tvgSwShape.cpp | 8 +------- src/lib/sw_engine/tvgSwStroke.cpp | 7 +------ src/lib/tvgBezier.cpp | 8 +------- src/lib/tvgCanvas.cpp | 7 +------ src/lib/tvgFill.cpp | 7 +------ src/lib/tvgGlCanvas.cpp | 8 +------- src/lib/tvgInitializer.cpp | 7 +------ src/lib/tvgLinearGradient.cpp | 7 +------ src/lib/tvgLoaderMgr.cpp | 7 +------ src/lib/tvgPaint.cpp | 7 +------ src/lib/tvgPicture.cpp | 7 +------ src/lib/tvgRadialGradient.cpp | 7 +------ src/lib/tvgRender.cpp | 7 +------ src/lib/tvgScene.cpp | 7 +------ src/lib/tvgShape.cpp | 8 +------- src/lib/tvgSwCanvas.cpp | 7 +------ src/loaders/svg/tvgSimpleXmlParser.cpp | 3 +-- src/loaders/svg/tvgSvgLoader.cpp | 7 +------ src/loaders/svg/tvgSvgPath.cpp | 8 +------- src/loaders/svg/tvgSvgSceneBuilder.cpp | 10 +--------- 26 files changed, 26 insertions(+), 160 deletions(-) diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index a295ed6..f6b31d4 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -19,10 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -#ifndef _TVG_GL_RENDERER_CPP_ -#define _TVG_GL_RENDERER_CPP_ - #include "tvgGlShaderSrc.h" #include "tvgGlGpuBuffer.h" #include "tvgGlGeometry.h" @@ -216,6 +212,4 @@ void GlRenderer::drawPrimitive(GlGeometry& geometry, float r, float g, float b, geometry.draw(mVertexAttrLoc, primitiveIndex, flag); geometry.disableVertex(mVertexAttrLoc); -} - -#endif /* _TVG_GL_RENDERER_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 72e702b..91a064d 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_FILL_CPP_ -#define _TVG_SW_FILL_CPP_ - #include "tvgSwCommon.h" @@ -314,6 +311,4 @@ void fillFree(SwFill* fill) if (fill->ctable) free(fill->ctable); free(fill); -} - -#endif /* _TVG_SW_FILL_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index b3cf477..56ce40f 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_MATH_H_ -#define _TVG_SW_MATH_H_ - #include "tvgSwCommon.h" @@ -417,5 +414,4 @@ SwFixed mathDiff(SwFixed angle1, SwFixed angle2) if (delta > SW_ANGLE_PI) delta -= SW_ANGLE_2PI; return delta; -} -#endif /* _TVG_SW_MATH_H_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 3fec524..7b5b986 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_RASTER_CPP_ -#define _TVG_SW_RASTER_CPP_ - #include "tvgSwCommon.h" /************************************************************************/ @@ -369,6 +366,4 @@ bool rasterClear(SwSurface* surface) } } return true; -} - -#endif /* _TVG_SW_RASTER_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index b173ce4..1a1e0bf 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_RENDERER_CPP_ -#define _TVG_SW_RENDERER_CPP_ - #include "tvgSwCommon.h" #include "tvgSwRenderer.h" @@ -185,6 +182,4 @@ SwRenderer* SwRenderer::inst() { //We know renderer type, avoid dynamic_cast for performance. return static_cast(RenderInitializer::inst(renderInit)); -} - -#endif /* _TVG_SW_RENDERER_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index c9aa6ae..37a860f 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_RLE_H_ -#define _TVG_SW_RLE_H_ - #include #include #include @@ -754,6 +751,4 @@ void rleFree(SwRleData* rle) if (!rle) return; if (rle->spans) free(rle->spans); free(rle); -} - -#endif /* _TVG_SW_RLE_H_ */ +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index f14d3b6..d0a8f96 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_SHAPE_H_ -#define _TVG_SW_SHAPE_H_ - #include "tvgSwCommon.h" /************************************************************************/ @@ -672,7 +669,4 @@ void shapeDelFill(SwShape* shape) if (!shape->fill) return; fillFree(shape->fill); shape->fill = nullptr; -} - - -#endif /* _TVG_SW_SHAPE_H_ */ +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index 8400237..08754f8 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_STROKER_H_ -#define _TVG_SW_STROKER_H_ - #include "tvgSwCommon.h" @@ -924,6 +921,4 @@ SwOutline* strokeExportOutline(SwStroke* stroke) _exportBorderOutline(*stroke, outline, 1); //right return outline; -} - -#endif /* _TVG_SW_STROKER_H_ */ +} \ No newline at end of file diff --git a/src/lib/tvgBezier.cpp b/src/lib/tvgBezier.cpp index 0ed4ed2..db4d58b 100644 --- a/src/lib/tvgBezier.cpp +++ b/src/lib/tvgBezier.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_BEZIER_CPP_ -#define _TVG_BEZIER_CPP_ - #include "tvgCommon.h" @@ -143,7 +140,4 @@ void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right) bezSplitLeft(right, t, left); } - -} - -#endif //_TVG_BEZIER_CPP_ +} \ No newline at end of file diff --git a/src/lib/tvgCanvas.cpp b/src/lib/tvgCanvas.cpp index 7e7250a..957940c 100644 --- a/src/lib/tvgCanvas.cpp +++ b/src/lib/tvgCanvas.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_CANVAS_CPP_ -#define _TVG_CANVAS_CPP_ - #include "tvgCommon.h" #include "tvgCanvasImpl.h" @@ -75,6 +72,4 @@ Result Canvas::sync() noexcept if (IMPL->renderer->flush()) return Result::Success; return Result::InsufficientCondition; -} - -#endif /* _TVG_CANVAS_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/tvgFill.cpp b/src/lib/tvgFill.cpp index d1240f0..cc1a13b 100644 --- a/src/lib/tvgFill.cpp +++ b/src/lib/tvgFill.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_FILL_CPP_ -#define _TVG_FILL_CPP_ - #include "tvgCommon.h" @@ -99,6 +96,4 @@ Result Fill::spread(FillSpread s) noexcept FillSpread Fill::spread() const noexcept { return IMPL->spread; -} - -#endif /* _TVG_FILL_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index e1b5c3c..7f267a4 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_GLCANVAS_CPP_ -#define _TVG_GLCANVAS_CPP_ - #include "tvgCommon.h" #include "tvgCanvasImpl.h" @@ -84,7 +81,4 @@ unique_ptr GlCanvas::gen() noexcept return unique_ptr(new GlCanvas); #endif return nullptr; -} - - -#endif /* _TVG_GLCANVAS_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 3367603..2185c0f 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_INITIALIZER_CPP_ -#define _TVG_INITIALIZER_CPP_ - #include "tvgCommon.h" #include "tvgLoaderMgr.h" @@ -107,6 +104,4 @@ Result Initializer::threads(uint32_t cnt) noexcept uint32_t Initializer::threads() noexcept { return threadCnt; -} - -#endif /* _TVG_INITIALIZER_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/tvgLinearGradient.cpp b/src/lib/tvgLinearGradient.cpp index bd2dbc1..a76239e 100644 --- a/src/lib/tvgLinearGradient.cpp +++ b/src/lib/tvgLinearGradient.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_LINEAR_GRADIENT_CPP_ -#define _TVG_LINEAR_GRADIENT_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -77,6 +74,4 @@ Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const unique_ptr LinearGradient::gen() noexcept { return unique_ptr(new LinearGradient); -} - -#endif /* _TVG_LINEAR_GRADIENT_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index 5e59a44..6ec3213 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_LOADER_MGR_CPP_ -#define _TVG_LOADER_MGR_CPP_ - #include "tvgCommon.h" #ifdef THORVG_SVG_LOADER_SUPPORT @@ -56,6 +53,4 @@ unique_ptr LoaderMgr::loader() return unique_ptr(new SvgLoader); #endif return nullptr; -} - -#endif //_TVG_LOADER_MGR_CPP_ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 7984ac0..3105e27 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_PAINT_CPP_ -#define _TVG_PAINT_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -74,6 +71,4 @@ Result Paint::bounds(float* x, float* y, float* w, float* h) const noexcept { if (IMPL->bounds(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; -} - -#endif //_TVG_PAINT_CPP_ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 7083692..7c20a37 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_PICTURE_CPP_ -#define _TVG_PICTURE_CPP_ - #include "tvgPictureImpl.h" /************************************************************************/ @@ -65,6 +62,4 @@ Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept { if (IMPL->viewbox(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; -} - -#endif /* _TVG_PICTURE_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgRadialGradient.cpp b/src/lib/tvgRadialGradient.cpp index 9f123bf..92e934e 100644 --- a/src/lib/tvgRadialGradient.cpp +++ b/src/lib/tvgRadialGradient.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_RADIAL_GRADIENT_CPP_ -#define _TVG_RADIAL_GRADIENT_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -74,6 +71,4 @@ Result RadialGradient::radial(float* cx, float* cy, float* radius) const noexcep unique_ptr RadialGradient::gen() noexcept { return unique_ptr(new RadialGradient); -} - -#endif /* _TVG_RADIAL_GRADIENT_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgRender.cpp b/src/lib/tvgRender.cpp index 30bc906..10a23e8 100644 --- a/src/lib/tvgRender.cpp +++ b/src/lib/tvgRender.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_RENDER_CPP_ -#define _TVG_RENDER_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -118,6 +115,4 @@ RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransfo m.e31 = lhs->m.e31 * rhs->m.e11 + lhs->m.e32 * rhs->m.e21 + lhs->m.e33 * rhs->m.e31; m.e32 = lhs->m.e31 * rhs->m.e12 + lhs->m.e32 * rhs->m.e22 + lhs->m.e33 * rhs->m.e32; m.e33 = lhs->m.e31 * rhs->m.e13 + lhs->m.e32 * rhs->m.e23 + lhs->m.e33 * rhs->m.e33; -} - -#endif //_TVG_RENDER_CPP_ +} \ No newline at end of file diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index 9120e00..df7362f 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SCENE_CPP_ -#define _TVG_SCENE_CPP_ - #include "tvgSceneImpl.h" /************************************************************************/ @@ -60,6 +57,4 @@ Result Scene::reserve(uint32_t size) noexcept IMPL->paints.reserve(size); return Result::Success; -} - -#endif /* _TVG_SCENE_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index c688ffc..8db945d 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SHAPE_CPP_ -#define _TVG_SHAPE_CPP_ - #include #include "tvgShapeImpl.h" @@ -405,7 +402,4 @@ StrokeJoin Shape::strokeJoin() const noexcept if (!IMPL->stroke) return StrokeJoin::Bevel; return IMPL->stroke->join; -} - - -#endif //_TVG_SHAPE_CPP_ +} \ No newline at end of file diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index 5d280fd..b56beb4 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SWCANVAS_CPP_ -#define _TVG_SWCANVAS_CPP_ - #include "tvgCommon.h" #include "tvgCanvasImpl.h" @@ -83,6 +80,4 @@ unique_ptr SwCanvas::gen() noexcept return unique_ptr(new SwCanvas); #endif return nullptr; -} - -#endif /* _TVG_SWCANVAS_CPP_ */ +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSimpleXmlParser.cpp b/src/loaders/svg/tvgSimpleXmlParser.cpp index 932d071..76200ae 100644 --- a/src/loaders/svg/tvgSimpleXmlParser.cpp +++ b/src/loaders/svg/tvgSimpleXmlParser.cpp @@ -364,5 +364,4 @@ const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength) } return nullptr; -} - +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index f1d9432..b174300 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SVG_LOADER_CPP_ -#define _TVG_SVG_LOADER_CPP_ - #include #include #include "tvgSvgLoader.h" @@ -2391,6 +2388,4 @@ bool SvgLoader::close() unique_ptr SvgLoader::data() { return move(root); -} - -#endif //_TVG_SVG_LOADER_CPP_ +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index 2d3b86a..c9b90fe 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -19,10 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -#ifndef __TVG_SVG_PATH_CPP_ -#define __TVG_SVG_PATH_CPP_ - #include "tvgSvgPath.h" @@ -500,6 +496,4 @@ tuple, vector> svgPathToTvgPath(const char* svgPath) if (curLocale) free(curLocale); return make_tuple(cmds, pts); -} - -#endif //__TVG_SVG_PATH_CPP_ +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index faea2ec..5496ae8 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -19,11 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -#ifndef _TVG_SVG_SCENE_BUILDER_CPP_ -#define _TVG_SVG_SCENE_BUILDER_CPP_ - - #include "tvgSvgSceneBuilder.h" unique_ptr _applyLinearGradientProperty(SvgStyleGradient* g, Shape* vg, float rx, float ry, float rw, float rh) @@ -374,7 +369,4 @@ unique_ptr SvgSceneBuilder::build(SvgNode* node) viewBox.h = node->node.doc.vh; preserveAspect = node->node.doc.preserveAspect; return _sceneBuildHelper(node, viewBox.x, viewBox.y, viewBox.w, viewBox.h, 255); -} - - -#endif //_TVG_SVG_SCENE_BUILDER_CPP_ +} \ No newline at end of file -- 2.7.4 From 5905c0c323f4768ba2298828c389109c6ecfd390 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Sun, 16 Aug 2020 15:23:42 +0200 Subject: [PATCH 14/16] svg path: changes in processing cmds T,Q,S Change-Id: I979bb8cbcbdd4fd1374205feac6acedc58bdd3e1 --- src/loaders/svg/tvgSvgPath.cpp | 47 +++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index c9b90fe..4efc009 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -239,7 +239,9 @@ static int _numberCount(char cmd) case 'M': case 'm': case 'L': - case 'l': { + case 'l': + case 'T': + case 't': { count = 2; break; } @@ -260,9 +262,7 @@ static int _numberCount(char cmd) case 'S': case 's': case 'Q': - case 'q': - case 'T': - case 't': { + case 'q': { count = 4; break; } @@ -278,7 +278,7 @@ static int _numberCount(char cmd) } -static void _processCommand(vector* cmds, vector* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl) +static void _processCommand(vector* cmds, vector* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, bool *isQuadratic) { int i; switch (cmd) { @@ -341,12 +341,14 @@ static void _processCommand(vector* cmds, vector* pts, char pts->push_back(p[2]); *curCtl = p[1]; *cur = p[2]; + *isQuadratic = false; break; } case 's': case 'S': { Point p[3], ctrl; - if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo)) { + if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo) && + !(*isQuadratic)) { ctrl.x = 2 * cur->x - curCtl->x; ctrl.y = 2 * cur->y - curCtl->y; } else { @@ -361,6 +363,7 @@ static void _processCommand(vector* cmds, vector* pts, char pts->push_back(p[2]); *curCtl = p[1]; *cur = p[2]; + *isQuadratic = false; break; } case 'q': @@ -377,16 +380,35 @@ static void _processCommand(vector* cmds, vector* pts, char pts->push_back(p[0]); pts->push_back(p[1]); pts->push_back(p[2]); - *curCtl = p[1]; + *curCtl = {arr[0], arr[1]}; *cur = p[2]; + *isQuadratic = true; break; } case 't': case 'T': { - Point p = {arr[0], arr[1]}; - cmds->push_back(PathCommand::MoveTo); - pts->push_back(p); - *cur = {arr[0] ,arr[1]}; + Point p[3], ctrl; + if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo) && + *isQuadratic) { + ctrl.x = 2 * cur->x - curCtl->x; + ctrl.y = 2 * cur->y - curCtl->y; + } else { + ctrl = *cur; + } + float ctrl_x0 = (cur->x + 2 * ctrl.x) * (1.0 / 3.0); + float ctrl_y0 = (cur->y + 2 * ctrl.y) * (1.0 / 3.0); + float ctrl_x1 = (arr[0] + 2 * ctrl.x) * (1.0 / 3.0); + float ctrl_y1 = (arr[1] + 2 * ctrl.y) * (1.0 / 3.0); + cmds->push_back(PathCommand::CubicTo); + p[0] = {ctrl_x0, ctrl_y0}; + p[1] = {ctrl_x1, ctrl_y1}; + p[2] = {arr[0], arr[1]}; + pts->push_back(p[0]); + pts->push_back(p[1]); + pts->push_back(p[2]); + *curCtl = {ctrl.x, ctrl.y}; + *cur = p[2]; + *isQuadratic = true; break; } case 'h': @@ -479,6 +501,7 @@ tuple, vector> svgPathToTvgPath(const char* svgPath) Point cur = { 0, 0 }; Point curCtl = { 0, 0 }; char cmd = 0; + bool isQuadratic = false; char* path = (char*)svgPath; char* curLocale; @@ -489,7 +512,7 @@ tuple, vector> svgPathToTvgPath(const char* svgPath) while ((path[0] != '\0')) { path = _nextCommand(path, &cmd, numberArray, &numberCount); if (!path) break; - _processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl); + _processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &isQuadratic); } setlocale(LC_NUMERIC, curLocale); -- 2.7.4 From 06cadc79f545d129a487b3b52a8092d866954d44 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 17:52:11 +0900 Subject: [PATCH 15/16] updated AUTHORS Change-Id: Ie0bb862f8ba20e682bf3bb7469455fa52a5d5498 --- AUTHORS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 1299d6b..a600a62 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,3 +3,5 @@ Prudhvi Raj Vasireddi Junsu Choi Pranay Samanta Mateusz Palkowski +Subhransu Mohanty +Mira Grudzinska -- 2.7.4 From 657e6daddb5dfe0aeeb694538f23a26857e0d6cf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 17:04:32 +0900 Subject: [PATCH 16/16] common taskscheduler: revise functionalities. initialization interfaces has been changed for threads count. if you want to set concrete threads count by system, please specify thread count with it. std threads: tvg::Initializer::init(tvg::CanvasEngine::Sw, std::thread::hardware_concurrency()); if your system provides designed threads info, you can use it. efl: tvg_engine_init(TVG_ENGINE_SW, eina_cpu_count()); I recommend to avoid max threads usage for better performance. Change-Id: I22cfa315768f73fa941be136956cdbb2cf837c20 --- inc/thorvg.h | 4 +- inc/thorvg_capi.h | 2 +- src/bindings/capi/tvgCapi.cpp | 10 +-- src/lib/meson.build | 3 +- src/lib/tvgCommon.h | 4 + src/lib/tvgInitializer.cpp | 21 ++--- src/lib/tvgShapePath.h | 6 +- src/lib/tvgTask.cpp | 156 ---------------------------------- src/lib/tvgTask.h | 72 ---------------- src/lib/tvgTaskScheduler.cpp | 189 +++++++++++++++++++++++++++++++++++++++++ src/lib/tvgTaskScheduler.h | 72 ++++++++++++++++ test/testArc.cpp | 5 +- test/testAsync.cpp | 5 +- test/testBlending.cpp | 5 +- test/testBoundary.cpp | 5 +- test/testCapi.c | 2 +- test/testCommon.h | 1 + test/testCustomTransform.cpp | 5 +- test/testDirectUpdate.cpp | 5 +- test/testGradientTransform.cpp | 39 +++++---- test/testLinearGradient.cpp | 5 +- test/testMultiShapes.cpp | 5 +- test/testPath.cpp | 5 +- test/testPathCopy.cpp | 5 +- test/testRadialGradient.cpp | 5 +- test/testScene.cpp | 6 +- test/testSceneTransform.cpp | 5 +- test/testShape.cpp | 5 +- test/testStroke.cpp | 5 +- test/testStrokeLine.cpp | 6 +- test/testSvg.cpp | 5 +- test/testSvg2.cpp | 5 +- test/testTransform.cpp | 5 +- test/testUpdate.cpp | 5 +- 34 files changed, 387 insertions(+), 296 deletions(-) delete mode 100644 src/lib/tvgTask.cpp delete mode 100644 src/lib/tvgTask.h create mode 100644 src/lib/tvgTaskScheduler.cpp create mode 100644 src/lib/tvgTaskScheduler.h diff --git a/inc/thorvg.h b/inc/thorvg.h index 18013fa..0de9bc0 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -366,10 +366,8 @@ public: * * @see ... */ - static Result init(CanvasEngine engine) noexcept; + static Result init(CanvasEngine engine, uint32_t threads) noexcept; static Result term(CanvasEngine engine) noexcept; - static Result threads(uint32_t cnt) noexcept; - static uint32_t threads() noexcept; _TVG_DISABLE_CTOR(Initializer); }; diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 811c82e..afc294a 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -88,7 +88,7 @@ typedef struct /************************************************************************/ /* Engine API */ /************************************************************************/ -TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method); +TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads); TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method); diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index ac8cdcb..0155196 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -50,13 +50,13 @@ struct _Tvg_Gradient /* Engine API */ /************************************************************************/ -TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) { +TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads) { Result ret = Result::Success; - if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw, threads); if (ret != Result::Success) return (Tvg_Result) ret; - if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl); + if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl, threads); return (Tvg_Result) ret; } @@ -64,10 +64,10 @@ TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) { TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) { Result ret = Result::Success; - if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::term(tvg::CanvasEngine::Sw); if (ret != Result::Success) return (Tvg_Result) ret; - if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl); + if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::term(tvg::CanvasEngine::Gl); return (Tvg_Result) ret; } diff --git a/src/lib/meson.build b/src/lib/meson.build index 503c35e..bc0d959 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -21,6 +21,7 @@ source_file = [ 'tvgSceneImpl.h', 'tvgShapePath.h', 'tvgShapeImpl.h', + 'tvgTaskScheduler.h', 'tvgBezier.cpp', 'tvgCanvas.cpp', 'tvgFill.cpp', @@ -35,7 +36,7 @@ source_file = [ 'tvgScene.cpp', 'tvgShape.cpp', 'tvgSwCanvas.cpp', - 'tvgTask.cpp', + 'tvgTaskScheduler.cpp', ] common_dep = declare_dependency( diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 66e08bf..c07a4ca 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -29,6 +29,9 @@ #include #include #include +#include +#include + #include "thorvg.h" using namespace std; @@ -46,5 +49,6 @@ using namespace tvg; #include "tvgLoaderMgr.h" #include "tvgRender.h" #include "tvgPaint.h" +#include "tvgTaskScheduler.h" #endif //_TVG_COMMON_H_ diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 2185c0f..17b91a0 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -35,13 +35,12 @@ /* Internal Class Implementation */ /************************************************************************/ -static uint32_t threadCnt = 0; /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -Result Initializer::init(CanvasEngine engine) noexcept +Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept { auto nonSupport = true; @@ -63,6 +62,8 @@ Result Initializer::init(CanvasEngine engine) noexcept if (!LoaderMgr::init()) return Result::Unknown; + TaskScheduler::init(threads); + return Result::Success; } @@ -87,21 +88,9 @@ Result Initializer::term(CanvasEngine engine) noexcept if (nonSupport) return Result::NonSupport; - if (!LoaderMgr::term()) return Result::Unknown; - - return Result::Success; -} - + TaskScheduler::term(); -Result Initializer::threads(uint32_t cnt) noexcept -{ - threadCnt = cnt; + if (!LoaderMgr::term()) return Result::Unknown; return Result::Success; -} - - -uint32_t Initializer::threads() noexcept -{ - return threadCnt; } \ No newline at end of file diff --git a/src/lib/tvgShapePath.h b/src/lib/tvgShapePath.h index 04934dc..f3e0ae5 100644 --- a/src/lib/tvgShapePath.h +++ b/src/lib/tvgShapePath.h @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SHAPE_PATH_CPP_ -#define _TVG_SHAPE_PATH_CPP_ +#ifndef _TVG_SHAPE_PATH_H_ +#define _TVG_SHAPE_PATH_H_ #include "tvgCommon.h" @@ -139,4 +139,4 @@ struct ShapePath } }; -#endif //_TVG_SHAPE_PATH_CPP_ +#endif //_TVG_SHAPE_PATH_H_ diff --git a/src/lib/tvgTask.cpp b/src/lib/tvgTask.cpp deleted file mode 100644 index 81ce22e..0000000 --- a/src/lib/tvgTask.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -template -class TaskQueue { - using lock_t = std::unique_lock; - std::deque _q; - bool _done{false}; - std::mutex _mutex; - std::condition_variable _ready; - -public: - bool try_pop(Task &task) - { - lock_t lock{_mutex, std::try_to_lock}; - if (!lock || _q.empty()) return false; - task = std::move(_q.front()); - _q.pop_front(); - return true; - } - - bool try_push(Task &&task) - { - { - lock_t lock{_mutex, std::try_to_lock}; - if (!lock) return false; - _q.push_back(std::move(task)); - } - _ready.notify_one(); - return true; - } - - void done() - { - { - lock_t lock{_mutex}; - _done = true; - } - _ready.notify_all(); - } - - bool pop(Task &task) - { - lock_t lock{_mutex}; - while (_q.empty() && !_done) _ready.wait(lock); - if (_q.empty()) return false; - task = std::move(_q.front()); - _q.pop_front(); - return true; - } - - void push(Task &&task) - { - { - lock_t lock{_mutex}; - _q.push_back(std::move(task)); - } - _ready.notify_one(); - } - -}; - -#include -#include - -namespace tvg -{ - -class Executor -{ - const unsigned _count{std::thread::hardware_concurrency()}; - std::vector _threads; - std::vector> _q{_count}; - std::atomic _index{0}; - void run(unsigned i) - { - // Task Loop - shared_task task; - while (true) { - bool success = false; - - for (unsigned n = 0; n != _count * 2; ++n) { - if (_q[(i + n) % _count].try_pop(task)) { - success = true; - break; - } - } - - if (!success && !_q[i].pop(task)) break; - - (*task)(); - } - } - - Executor() - { - for (unsigned n = 0; n != _count; ++n) { - _threads.emplace_back([&, n] { run(n); }); - } - } - ~Executor() - { - for (auto &e : _q) e.done(); - - for (auto &e : _threads) e.join(); - } - -public: - - static Executor& instance() { - static Executor singleton; - return singleton; - } - - void post(shared_task task) - { - task->prepare(); - - auto i = _index++; - - for (unsigned n = 0; n != _count; ++n) { - if (_q[(i + n) % _count].try_push(std::move(task))) return; - } - - if (_count > 0) { - _q[i % _count].push(std::move(task)); - } - } -}; - -void async(shared_task task) -{ - Executor::instance().post(std::move(task)); -} - -} - - diff --git a/src/lib/tvgTask.h b/src/lib/tvgTask.h deleted file mode 100644 index 9fb250e..0000000 --- a/src/lib/tvgTask.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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_TASK_H_ -#define _TVG_TASK_H_ - -#include -#include - -namespace tvg -{ - -/* - Task Interface. - Able to run a task in the thread pool. derive from the - task interface and implement run method. - - To get the result call task->get() which will return immidiately if the - task is already finishd otherwise will wait till task completion. - */ - -class Task -{ -public: - virtual ~Task() = default; - void get() { if (_receiver.valid()) _receiver.get(); } - -protected: - virtual void run() = 0; -private: - void operator()() - { - run(); - _sender.set_value(); - } - void prepare() - { - _sender = std::promise(); - _receiver = _sender.get_future(); - } - friend class Executor; - - std::promise _sender; - std::future _receiver; -}; - - -using shared_task = std::shared_ptr; - -/* - async() function takes a shared task and runs it in - a thread pool asyncronously. call get() on the shared_task - to get the ressult out of the shared_task. - */ -void async(shared_task task); - -} - -#endif //_TVG_TASK_H_ \ No newline at end of file diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp new file mode 100644 index 0000000..31b1e84 --- /dev/null +++ b/src/lib/tvgTaskScheduler.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include "tvgCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +namespace tvg { + +struct TaskQueue { + deque> taskDeque; + mutex mtx; + condition_variable ready; + bool done = false; + + bool tryPop(shared_ptr &task) + { + unique_lock lock{mtx, try_to_lock}; + if (!lock || taskDeque.empty()) return false; + task = move(taskDeque.front()); + taskDeque.pop_front(); + + return true; + } + + bool tryPush(shared_ptr &&task) + { + { + unique_lock lock{mtx, try_to_lock}; + if (!lock) return false; + taskDeque.push_back(move(task)); + } + + ready.notify_one(); + + return true; + } + + void complete() + { + { + unique_lock lock{mtx}; + done = true; + } + ready.notify_all(); + } + + bool pop(shared_ptr &task) + { + unique_lock lock{mtx}; + + while (taskDeque.empty() && !done) { + ready.wait(lock); + } + + if (taskDeque.empty()) return false; + + task = move(taskDeque.front()); + taskDeque.pop_front(); + + return true; + } + + void push(shared_ptr &&task) + { + { + unique_lock lock{mtx}; + taskDeque.push_back(move(task)); + } + + ready.notify_one(); + } + +}; + + +class TaskSchedulerImpl +{ +public: + unsigned threadCnt; + vector threads; + vector taskQueues{threadCnt}; + atomic idx{0}; + + TaskSchedulerImpl() + { + for (unsigned i = 0; i < threadCnt; ++i) { + threads.emplace_back([&, i] { run(i); }); + } + } + + ~TaskSchedulerImpl() + { + for (auto& queue : taskQueues) queue.complete(); + for (auto& thread : threads) thread.join(); + } + + void run(unsigned i) + { + shared_ptr task; + + //Thread Loop + while (true) { + auto success = false; + + for (unsigned i = 0; i < threadCnt * 2; ++i) { + if (taskQueues[(i + i) % threadCnt].tryPop(task)) { + success = true; + break; + } + } + + if (!success && !taskQueues[i].pop(task)) break; + + (*task)(); + } + } + + void request(shared_ptr task) + { + //Async + if (threadCnt > 0) { + task->prepare(); + auto i = idx++; + for (unsigned n = 0; n < threadCnt; ++n) { + if (taskQueues[(i + n) % threadCnt].tryPush(move(task))) return; + } + + taskQueues[i % threadCnt].push(move(task)); + + //Sync + } else { + task->run(); + } + } +}; + +} + +static TaskSchedulerImpl* inst = nullptr; + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +void TaskScheduler::init(unsigned threads) +{ + if (inst) return; + inst = new TaskSchedulerImpl; + inst->threadCnt = threads; +} + + +void TaskScheduler::term() +{ + if (!inst) return; + delete(inst); + inst = nullptr; +} + + +void TaskScheduler::request(shared_ptr task) +{ + if (inst) { + inst->request(move(task)); + } +} \ No newline at end of file diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h new file mode 100644 index 0000000..4380a9c --- /dev/null +++ b/src/lib/tvgTaskScheduler.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _TVG_TASK_SCHEDULER_H_ +#define _TVG_TASK_SCHEDULER_H_ + +#include "tvgCommon.h" + +namespace tvg +{ + +struct Task +{ +private: + std::promise sender; + std::future receiver; + +public: + virtual ~Task() = default; + + void get() + { + if (receiver.valid()) receiver.get(); + } + +protected: + virtual void run() = 0; + +private: + void operator()() + { + run(); + sender.set_value(); + } + + void prepare() + { + sender = std::promise(); + receiver = sender.get_future(); + } + + friend class TaskSchedulerImpl; +}; + +struct TaskScheduler +{ + static void init(unsigned threads); + static void term(); + static void request(shared_ptr task); +}; + +} + +#endif //_TVG_TASK_SCHEDULER_H_ \ No newline at end of file diff --git a/test/testArc.cpp b/test/testArc.cpp index 1f15812..9c307d4 100644 --- a/test/testArc.cpp +++ b/test/testArc.cpp @@ -148,8 +148,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testAsync.cpp b/test/testAsync.cpp index 608cefb..25e57ba 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -151,8 +151,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 743b1e0..68623dc 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -131,8 +131,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index 3830687..e2ed1c0 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -120,8 +120,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testCapi.c b/test/testCapi.c index c6df396..1b0018d 100644 --- a/test/testCapi.c +++ b/test/testCapi.c @@ -13,7 +13,7 @@ static uint32_t buffer[WIDTH * HEIGHT]; void testCapi() { - tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL); + tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL, 0); Tvg_Canvas* canvas = tvg_swcanvas_create(); tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888); diff --git a/test/testCommon.h b/test/testCommon.h index 13ac86a..a5f222e 100644 --- a/test/testCommon.h +++ b/test/testCommon.h @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 9daa6fc..50033f9 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -176,8 +176,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 8dcc474..69105c3 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -139,8 +139,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index 77d5f6a..45431e3 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -204,31 +204,34 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); } else { cout << "engine is not supported" << endl; diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index db11682..d1ed5fa 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -149,8 +149,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 12009bc..3db41b9 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -109,8 +109,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testPath.cpp b/test/testPath.cpp index de6ef60..a265d03 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -126,8 +126,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index fb1080b..b5d97cf 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -163,8 +163,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index 6e77291..a64e47b 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -149,8 +149,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testScene.cpp b/test/testScene.cpp index daa5d86..8c46428 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -156,8 +156,12 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { + elm_init(argc, argv); diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index e64fa9a..ef6c157 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -200,8 +200,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testShape.cpp b/test/testShape.cpp index af4d0c4..56acfd5 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -99,8 +99,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testStroke.cpp b/test/testStroke.cpp index 778d7c7..5ac2265 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -146,8 +146,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 1205bb1..8cc16d0 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -183,8 +183,12 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { + elm_init(argc, argv); diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 06fe350..ad72027 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -141,8 +141,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testSvg2.cpp b/test/testSvg2.cpp index 2300f21..c859b04 100644 --- a/test/testSvg2.cpp +++ b/test/testSvg2.cpp @@ -124,8 +124,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 5ef33f4..6cd9be6 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -167,8 +167,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 3ff6c24..6df8533 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -128,8 +128,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); -- 2.7.4