From 7b004363f9826faba339fee469e777423fa9c079 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 19:15:33 +0900 Subject: [PATCH 01/16] sw_engine renderer: initialize member data in default. static analizyer bothers us due to this. we'd rather initialize members for free of them. Change-Id: I23b769b94be7514a8bf6e6d683ddb90b3cd613c4 --- src/lib/sw_engine/tvgSwRenderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index b6c7a19..d34c83c 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -52,7 +52,7 @@ public: void doRender(); //Internally used for threading private: - Surface surface; + Surface surface = {nullptr, 0, 0, 0}; future progress; queue prepareTasks; queue renderTasks; -- 2.7.4 From 3dc3cfd8c0726ad2571a101747df724638cc8f14 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 19:27:02 +0900 Subject: [PATCH 02/16] sw_engine: fix data overflow case. Change-Id: I01f90a8a6b3bca38142c8c16d1990b5b1a09d081 --- src/lib/sw_engine/tvgSwStroke.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index edba638..70eb1ca 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -35,7 +35,7 @@ static constexpr auto SW_STROKE_TAG_END = 8; static inline SwFixed SIDE_TO_ROTATE(const int32_t s) { - return (SW_ANGLE_PI2 - (s) * SW_ANGLE_PI); + return (SW_ANGLE_PI2 - static_cast(s) * SW_ANGLE_PI); } -- 2.7.4 From 8abef404cf026d7740c835c393ca516d7d17d849 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 19:29:23 +0900 Subject: [PATCH 03/16] sw_engine: remove unnecessary assert() call Change-Id: I8cb249b6b7f32992f7ce9c86e408546c14856330 --- src/lib/sw_engine/tvgSwRle.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index 191e59e..6f1f2f2 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -571,21 +571,14 @@ static void _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2, static bool _decomposeOutline(RleWorker& rw) { auto outline = rw.outline; - assert(outline); - auto first = 0; //index of first point in contour for (uint32_t n = 0; n < outline->cntrsCnt; ++n) { auto last = outline->cntrs[n]; auto limit = outline->pts + last; - assert(limit); - auto start = UPSCALE(outline->pts[first]); - auto pt = outline->pts + first; - assert(pt); auto types = outline->types + first; - assert(types); /* A contour cannot start with a cubic control point! */ if (types[0] == SW_CURVE_TYPE_CUBIC) goto invalid_outline; @@ -593,8 +586,8 @@ static bool _decomposeOutline(RleWorker& rw) _moveTo(rw, UPSCALE(outline->pts[first])); while (pt < limit) { - assert(++pt); - assert(++types); + ++pt; + ++types; //emit a single line_to if (types[0] == SW_CURVE_TYPE_POINT) { -- 2.7.4 From 3b9bb51321bb9b6aa5aba78ac984915a8eb9d854 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 19:41:34 +0900 Subject: [PATCH 04/16] svg_loader: free allocated data properly. also renamed internal function for consistency. createNode() cloneNode() freeSVGNode() ? Change-Id: Ie9b22e92d5e918e947f8476ad0d4682fc7a3be65 --- src/loaders/svg_loader/tvgSvgLoader.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/loaders/svg_loader/tvgSvgLoader.cpp b/src/loaders/svg_loader/tvgSvgLoader.cpp index 0529ec8..205e8cb 100644 --- a/src/loaders/svg_loader/tvgSvgLoader.cpp +++ b/src/loaders/svg_loader/tvgSvgLoader.cpp @@ -33,7 +33,7 @@ typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength); typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength); - +static void _freeNode(SvgNode* node); static char* _skipSpace(const char* str, const char* end) { @@ -1459,6 +1459,8 @@ static void _cloneNode(SvgNode* from, SvgNode* parent) for (vector::iterator itrChild = from->child.begin(); itrChild != from->child.end(); itrChild++) { _cloneNode(*itrChild, newNode); } + + _freeNode(newNode); } @@ -2161,12 +2163,12 @@ static void _freeNodeStyle(SvgStyleProperty* style) free(style); } -static void _freeSvgNode(SvgNode* node) +static void _freeNode(SvgNode* node) { if (!node) return; for(vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { - _freeSvgNode(*itrChild); + _freeNode(*itrChild); } node->child.clear(); @@ -2187,7 +2189,7 @@ static void _freeSvgNode(SvgNode* node) break; } case SvgNodeType::Doc: { - _freeSvgNode(node->node.doc.defs); + _freeNode(node->node.doc.defs); break; } case SvgNodeType::Defs: { @@ -2360,7 +2362,7 @@ bool SvgLoader::close() free(loaderData.svgParse); loaderData.svgParse = nullptr; } - _freeSvgNode(loaderData.doc); + _freeNode(loaderData.doc); loaderData.doc = nullptr; return true; -- 2.7.4 From ac4405a4ec29ce5c7a324117c9b45c1f7d62fa09 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 19:50:46 +0900 Subject: [PATCH 05/16] sw_engine: fix potential data overflow. Change-Id: Ie800fda74d44ad3741f7a92f12681f7f753ee50c --- 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 3676048..5ac3912 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -377,7 +377,7 @@ SwFixed mathLength(SwPoint& pt) _polarize(v); v.x = _downscale(v.x); - if (shift > 0) return (v.x + (1 << (shift -1))) >> shift; + if (shift > 0) return (v.x + (static_cast(1) << (shift -1))) >> shift; return static_cast((uint32_t)v.x << -shift); } -- 2.7.4 From 3b22a25798167299c99119970676aa411186b7b4 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 19:59:01 +0900 Subject: [PATCH 06/16] gl_engine: engine should return shape data for resuing it. Change-Id: I45f7ecbdb707b0751894e01d273b149402e089af --- src/lib/gl_engine/tvgGlRenderer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 0276c8f..a295ed6 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -129,16 +129,16 @@ void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const Rende { //prepare shape data GlShape* sdata = static_cast(data); - if (!sdata) - { + if (!sdata) { sdata = new GlShape; - assert(sdata); + if (!sdata) return nullptr; } + sdata->viewWd = static_cast(surface.w); sdata->viewHt = static_cast(surface.h); sdata->updateFlag = flags; - if (sdata->updateFlag == RenderUpdateFlag::None) return nullptr; + if (sdata->updateFlag == RenderUpdateFlag::None) return sdata; initShaders(); -- 2.7.4 From 9dd3cc5edc8f43473cfa163b46e83a02a54eed00 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 13 Aug 2020 20:05:37 +0900 Subject: [PATCH 07/16] common: code refactoring. we can return nullptr directly here. Change-Id: Ic1d987f2701d20ff1b69af2854f9cfee7e2fe065 --- src/lib/tvgLoaderMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index 208ba79..a35dcd5 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -56,7 +56,7 @@ unique_ptr LoaderMgr::loader(const char* path) return unique_ptr(new SvgLoader); #endif cout << "Non supported format: " << path << endl; - return unique_ptr(nullptr); + return nullptr; } #endif //_TVG_LOADER_MGR_CPP_ \ 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 08/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 09/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 10/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 11/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 12/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 13/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 14/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 15/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 16/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