From 04c6295974b404dee9b8e89833acdd45bce64948 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 16:16:46 +0900 Subject: [PATCH 01/16] code refactoring remove unnecessary condition. implementation won't be included multiple times not like headers. Thus this condition is unnecessary. Change-Id: Id37e675c40ce7213a06c950da8e5ca17ff7245c9 --- src/lib/gl_engine/tvgGlRenderer.cpp | 8 +------- src/lib/sw_engine/tvgSwFill.cpp | 7 +------ src/lib/sw_engine/tvgSwMath.cpp | 6 +----- src/lib/sw_engine/tvgSwRaster.cpp | 7 +------ src/lib/sw_engine/tvgSwRenderer.cpp | 7 +------ src/lib/sw_engine/tvgSwRle.cpp | 7 +------ src/lib/sw_engine/tvgSwShape.cpp | 8 +------- src/lib/sw_engine/tvgSwStroke.cpp | 7 +------ src/lib/tvgBezier.cpp | 8 +------- src/lib/tvgCanvas.cpp | 7 +------ src/lib/tvgFill.cpp | 7 +------ src/lib/tvgGlCanvas.cpp | 8 +------- src/lib/tvgInitializer.cpp | 7 +------ src/lib/tvgLinearGradient.cpp | 7 +------ src/lib/tvgLoaderMgr.cpp | 7 +------ src/lib/tvgPaint.cpp | 7 +------ src/lib/tvgPicture.cpp | 7 +------ src/lib/tvgRadialGradient.cpp | 7 +------ src/lib/tvgRender.cpp | 7 +------ src/lib/tvgScene.cpp | 7 +------ src/lib/tvgShape.cpp | 8 +------- src/lib/tvgSwCanvas.cpp | 7 +------ src/loaders/svg/tvgSimpleXmlParser.cpp | 3 +-- src/loaders/svg/tvgSvgLoader.cpp | 7 +------ src/loaders/svg/tvgSvgPath.cpp | 8 +------- src/loaders/svg/tvgSvgSceneBuilder.cpp | 10 +--------- 26 files changed, 26 insertions(+), 160 deletions(-) diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index a295ed6..f6b31d4 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -19,10 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -#ifndef _TVG_GL_RENDERER_CPP_ -#define _TVG_GL_RENDERER_CPP_ - #include "tvgGlShaderSrc.h" #include "tvgGlGpuBuffer.h" #include "tvgGlGeometry.h" @@ -216,6 +212,4 @@ void GlRenderer::drawPrimitive(GlGeometry& geometry, float r, float g, float b, geometry.draw(mVertexAttrLoc, primitiveIndex, flag); geometry.disableVertex(mVertexAttrLoc); -} - -#endif /* _TVG_GL_RENDERER_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 72e702b..91a064d 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_FILL_CPP_ -#define _TVG_SW_FILL_CPP_ - #include "tvgSwCommon.h" @@ -314,6 +311,4 @@ void fillFree(SwFill* fill) if (fill->ctable) free(fill->ctable); free(fill); -} - -#endif /* _TVG_SW_FILL_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index b3cf477..56ce40f 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_MATH_H_ -#define _TVG_SW_MATH_H_ - #include "tvgSwCommon.h" @@ -417,5 +414,4 @@ SwFixed mathDiff(SwFixed angle1, SwFixed angle2) if (delta > SW_ANGLE_PI) delta -= SW_ANGLE_2PI; return delta; -} -#endif /* _TVG_SW_MATH_H_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 3fec524..7b5b986 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_RASTER_CPP_ -#define _TVG_SW_RASTER_CPP_ - #include "tvgSwCommon.h" /************************************************************************/ @@ -369,6 +366,4 @@ bool rasterClear(SwSurface* surface) } } return true; -} - -#endif /* _TVG_SW_RASTER_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index b173ce4..1a1e0bf 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_RENDERER_CPP_ -#define _TVG_SW_RENDERER_CPP_ - #include "tvgSwCommon.h" #include "tvgSwRenderer.h" @@ -185,6 +182,4 @@ SwRenderer* SwRenderer::inst() { //We know renderer type, avoid dynamic_cast for performance. return static_cast(RenderInitializer::inst(renderInit)); -} - -#endif /* _TVG_SW_RENDERER_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index c9aa6ae..37a860f 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_RLE_H_ -#define _TVG_SW_RLE_H_ - #include #include #include @@ -754,6 +751,4 @@ void rleFree(SwRleData* rle) if (!rle) return; if (rle->spans) free(rle->spans); free(rle); -} - -#endif /* _TVG_SW_RLE_H_ */ +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index f14d3b6..d0a8f96 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_SHAPE_H_ -#define _TVG_SW_SHAPE_H_ - #include "tvgSwCommon.h" /************************************************************************/ @@ -672,7 +669,4 @@ void shapeDelFill(SwShape* shape) if (!shape->fill) return; fillFree(shape->fill); shape->fill = nullptr; -} - - -#endif /* _TVG_SW_SHAPE_H_ */ +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index 8400237..08754f8 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SW_STROKER_H_ -#define _TVG_SW_STROKER_H_ - #include "tvgSwCommon.h" @@ -924,6 +921,4 @@ SwOutline* strokeExportOutline(SwStroke* stroke) _exportBorderOutline(*stroke, outline, 1); //right return outline; -} - -#endif /* _TVG_SW_STROKER_H_ */ +} \ No newline at end of file diff --git a/src/lib/tvgBezier.cpp b/src/lib/tvgBezier.cpp index 0ed4ed2..db4d58b 100644 --- a/src/lib/tvgBezier.cpp +++ b/src/lib/tvgBezier.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_BEZIER_CPP_ -#define _TVG_BEZIER_CPP_ - #include "tvgCommon.h" @@ -143,7 +140,4 @@ void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right) bezSplitLeft(right, t, left); } - -} - -#endif //_TVG_BEZIER_CPP_ +} \ No newline at end of file diff --git a/src/lib/tvgCanvas.cpp b/src/lib/tvgCanvas.cpp index 7e7250a..957940c 100644 --- a/src/lib/tvgCanvas.cpp +++ b/src/lib/tvgCanvas.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_CANVAS_CPP_ -#define _TVG_CANVAS_CPP_ - #include "tvgCommon.h" #include "tvgCanvasImpl.h" @@ -75,6 +72,4 @@ Result Canvas::sync() noexcept if (IMPL->renderer->flush()) return Result::Success; return Result::InsufficientCondition; -} - -#endif /* _TVG_CANVAS_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/tvgFill.cpp b/src/lib/tvgFill.cpp index d1240f0..cc1a13b 100644 --- a/src/lib/tvgFill.cpp +++ b/src/lib/tvgFill.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_FILL_CPP_ -#define _TVG_FILL_CPP_ - #include "tvgCommon.h" @@ -99,6 +96,4 @@ Result Fill::spread(FillSpread s) noexcept FillSpread Fill::spread() const noexcept { return IMPL->spread; -} - -#endif /* _TVG_FILL_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index e1b5c3c..7f267a4 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_GLCANVAS_CPP_ -#define _TVG_GLCANVAS_CPP_ - #include "tvgCommon.h" #include "tvgCanvasImpl.h" @@ -84,7 +81,4 @@ unique_ptr GlCanvas::gen() noexcept return unique_ptr(new GlCanvas); #endif return nullptr; -} - - -#endif /* _TVG_GLCANVAS_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 3367603..2185c0f 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_INITIALIZER_CPP_ -#define _TVG_INITIALIZER_CPP_ - #include "tvgCommon.h" #include "tvgLoaderMgr.h" @@ -107,6 +104,4 @@ Result Initializer::threads(uint32_t cnt) noexcept uint32_t Initializer::threads() noexcept { return threadCnt; -} - -#endif /* _TVG_INITIALIZER_CPP_ */ +} \ No newline at end of file diff --git a/src/lib/tvgLinearGradient.cpp b/src/lib/tvgLinearGradient.cpp index bd2dbc1..a76239e 100644 --- a/src/lib/tvgLinearGradient.cpp +++ b/src/lib/tvgLinearGradient.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_LINEAR_GRADIENT_CPP_ -#define _TVG_LINEAR_GRADIENT_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -77,6 +74,4 @@ Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const unique_ptr LinearGradient::gen() noexcept { return unique_ptr(new LinearGradient); -} - -#endif /* _TVG_LINEAR_GRADIENT_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoaderMgr.cpp index 5e59a44..6ec3213 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoaderMgr.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_LOADER_MGR_CPP_ -#define _TVG_LOADER_MGR_CPP_ - #include "tvgCommon.h" #ifdef THORVG_SVG_LOADER_SUPPORT @@ -56,6 +53,4 @@ unique_ptr LoaderMgr::loader() return unique_ptr(new SvgLoader); #endif return nullptr; -} - -#endif //_TVG_LOADER_MGR_CPP_ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 7984ac0..3105e27 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_PAINT_CPP_ -#define _TVG_PAINT_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -74,6 +71,4 @@ Result Paint::bounds(float* x, float* y, float* w, float* h) const noexcept { if (IMPL->bounds(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; -} - -#endif //_TVG_PAINT_CPP_ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 7083692..7c20a37 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_PICTURE_CPP_ -#define _TVG_PICTURE_CPP_ - #include "tvgPictureImpl.h" /************************************************************************/ @@ -65,6 +62,4 @@ Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept { if (IMPL->viewbox(x, y, w, h)) return Result::Success; return Result::InsufficientCondition; -} - -#endif /* _TVG_PICTURE_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgRadialGradient.cpp b/src/lib/tvgRadialGradient.cpp index 9f123bf..92e934e 100644 --- a/src/lib/tvgRadialGradient.cpp +++ b/src/lib/tvgRadialGradient.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_RADIAL_GRADIENT_CPP_ -#define _TVG_RADIAL_GRADIENT_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -74,6 +71,4 @@ Result RadialGradient::radial(float* cx, float* cy, float* radius) const noexcep unique_ptr RadialGradient::gen() noexcept { return unique_ptr(new RadialGradient); -} - -#endif /* _TVG_RADIAL_GRADIENT_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgRender.cpp b/src/lib/tvgRender.cpp index 30bc906..10a23e8 100644 --- a/src/lib/tvgRender.cpp +++ b/src/lib/tvgRender.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_RENDER_CPP_ -#define _TVG_RENDER_CPP_ - #include "tvgCommon.h" /************************************************************************/ @@ -118,6 +115,4 @@ RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransfo m.e31 = lhs->m.e31 * rhs->m.e11 + lhs->m.e32 * rhs->m.e21 + lhs->m.e33 * rhs->m.e31; m.e32 = lhs->m.e31 * rhs->m.e12 + lhs->m.e32 * rhs->m.e22 + lhs->m.e33 * rhs->m.e32; m.e33 = lhs->m.e31 * rhs->m.e13 + lhs->m.e32 * rhs->m.e23 + lhs->m.e33 * rhs->m.e33; -} - -#endif //_TVG_RENDER_CPP_ +} \ No newline at end of file diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index 9120e00..df7362f 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SCENE_CPP_ -#define _TVG_SCENE_CPP_ - #include "tvgSceneImpl.h" /************************************************************************/ @@ -60,6 +57,4 @@ Result Scene::reserve(uint32_t size) noexcept IMPL->paints.reserve(size); return Result::Success; -} - -#endif /* _TVG_SCENE_CPP_ */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index c688ffc..8db945d 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SHAPE_CPP_ -#define _TVG_SHAPE_CPP_ - #include #include "tvgShapeImpl.h" @@ -405,7 +402,4 @@ StrokeJoin Shape::strokeJoin() const noexcept if (!IMPL->stroke) return StrokeJoin::Bevel; return IMPL->stroke->join; -} - - -#endif //_TVG_SHAPE_CPP_ +} \ No newline at end of file diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index 5d280fd..b56beb4 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SWCANVAS_CPP_ -#define _TVG_SWCANVAS_CPP_ - #include "tvgCommon.h" #include "tvgCanvasImpl.h" @@ -83,6 +80,4 @@ unique_ptr SwCanvas::gen() noexcept return unique_ptr(new SwCanvas); #endif return nullptr; -} - -#endif /* _TVG_SWCANVAS_CPP_ */ +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSimpleXmlParser.cpp b/src/loaders/svg/tvgSimpleXmlParser.cpp index 932d071..76200ae 100644 --- a/src/loaders/svg/tvgSimpleXmlParser.cpp +++ b/src/loaders/svg/tvgSimpleXmlParser.cpp @@ -364,5 +364,4 @@ const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength) } return nullptr; -} - +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index f1d9432..b174300 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -19,9 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SVG_LOADER_CPP_ -#define _TVG_SVG_LOADER_CPP_ - #include #include #include "tvgSvgLoader.h" @@ -2391,6 +2388,4 @@ bool SvgLoader::close() unique_ptr SvgLoader::data() { return move(root); -} - -#endif //_TVG_SVG_LOADER_CPP_ +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index 2d3b86a..c9b90fe 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -19,10 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -#ifndef __TVG_SVG_PATH_CPP_ -#define __TVG_SVG_PATH_CPP_ - #include "tvgSvgPath.h" @@ -500,6 +496,4 @@ tuple, vector> svgPathToTvgPath(const char* svgPath) if (curLocale) free(curLocale); return make_tuple(cmds, pts); -} - -#endif //__TVG_SVG_PATH_CPP_ +} \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index faea2ec..5496ae8 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -19,11 +19,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -#ifndef _TVG_SVG_SCENE_BUILDER_CPP_ -#define _TVG_SVG_SCENE_BUILDER_CPP_ - - #include "tvgSvgSceneBuilder.h" unique_ptr _applyLinearGradientProperty(SvgStyleGradient* g, Shape* vg, float rx, float ry, float rw, float rh) @@ -374,7 +369,4 @@ unique_ptr SvgSceneBuilder::build(SvgNode* node) viewBox.h = node->node.doc.vh; preserveAspect = node->node.doc.preserveAspect; return _sceneBuildHelper(node, viewBox.x, viewBox.y, viewBox.w, viewBox.h, 255); -} - - -#endif //_TVG_SVG_SCENE_BUILDER_CPP_ +} \ No newline at end of file -- 2.7.4 From 5905c0c323f4768ba2298828c389109c6ecfd390 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Sun, 16 Aug 2020 15:23:42 +0200 Subject: [PATCH 02/16] svg path: changes in processing cmds T,Q,S Change-Id: I979bb8cbcbdd4fd1374205feac6acedc58bdd3e1 --- src/loaders/svg/tvgSvgPath.cpp | 47 +++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index c9b90fe..4efc009 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -239,7 +239,9 @@ static int _numberCount(char cmd) case 'M': case 'm': case 'L': - case 'l': { + case 'l': + case 'T': + case 't': { count = 2; break; } @@ -260,9 +262,7 @@ static int _numberCount(char cmd) case 'S': case 's': case 'Q': - case 'q': - case 'T': - case 't': { + case 'q': { count = 4; break; } @@ -278,7 +278,7 @@ static int _numberCount(char cmd) } -static void _processCommand(vector* cmds, vector* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl) +static void _processCommand(vector* cmds, vector* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, bool *isQuadratic) { int i; switch (cmd) { @@ -341,12 +341,14 @@ static void _processCommand(vector* cmds, vector* pts, char pts->push_back(p[2]); *curCtl = p[1]; *cur = p[2]; + *isQuadratic = false; break; } case 's': case 'S': { Point p[3], ctrl; - if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo)) { + if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo) && + !(*isQuadratic)) { ctrl.x = 2 * cur->x - curCtl->x; ctrl.y = 2 * cur->y - curCtl->y; } else { @@ -361,6 +363,7 @@ static void _processCommand(vector* cmds, vector* pts, char pts->push_back(p[2]); *curCtl = p[1]; *cur = p[2]; + *isQuadratic = false; break; } case 'q': @@ -377,16 +380,35 @@ static void _processCommand(vector* cmds, vector* pts, char pts->push_back(p[0]); pts->push_back(p[1]); pts->push_back(p[2]); - *curCtl = p[1]; + *curCtl = {arr[0], arr[1]}; *cur = p[2]; + *isQuadratic = true; break; } case 't': case 'T': { - Point p = {arr[0], arr[1]}; - cmds->push_back(PathCommand::MoveTo); - pts->push_back(p); - *cur = {arr[0] ,arr[1]}; + Point p[3], ctrl; + if ((cmds->size() > 1) && (cmds->at(cmds->size() - 1) == PathCommand::CubicTo) && + *isQuadratic) { + ctrl.x = 2 * cur->x - curCtl->x; + ctrl.y = 2 * cur->y - curCtl->y; + } else { + ctrl = *cur; + } + float ctrl_x0 = (cur->x + 2 * ctrl.x) * (1.0 / 3.0); + float ctrl_y0 = (cur->y + 2 * ctrl.y) * (1.0 / 3.0); + float ctrl_x1 = (arr[0] + 2 * ctrl.x) * (1.0 / 3.0); + float ctrl_y1 = (arr[1] + 2 * ctrl.y) * (1.0 / 3.0); + cmds->push_back(PathCommand::CubicTo); + p[0] = {ctrl_x0, ctrl_y0}; + p[1] = {ctrl_x1, ctrl_y1}; + p[2] = {arr[0], arr[1]}; + pts->push_back(p[0]); + pts->push_back(p[1]); + pts->push_back(p[2]); + *curCtl = {ctrl.x, ctrl.y}; + *cur = p[2]; + *isQuadratic = true; break; } case 'h': @@ -479,6 +501,7 @@ tuple, vector> svgPathToTvgPath(const char* svgPath) Point cur = { 0, 0 }; Point curCtl = { 0, 0 }; char cmd = 0; + bool isQuadratic = false; char* path = (char*)svgPath; char* curLocale; @@ -489,7 +512,7 @@ tuple, vector> svgPathToTvgPath(const char* svgPath) while ((path[0] != '\0')) { path = _nextCommand(path, &cmd, numberArray, &numberCount); if (!path) break; - _processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl); + _processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &isQuadratic); } setlocale(LC_NUMERIC, curLocale); -- 2.7.4 From 06cadc79f545d129a487b3b52a8092d866954d44 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 17:52:11 +0900 Subject: [PATCH 03/16] updated AUTHORS Change-Id: Ie0bb862f8ba20e682bf3bb7469455fa52a5d5498 --- AUTHORS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 1299d6b..a600a62 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,3 +3,5 @@ Prudhvi Raj Vasireddi Junsu Choi Pranay Samanta Mateusz Palkowski +Subhransu Mohanty +Mira Grudzinska -- 2.7.4 From 657e6daddb5dfe0aeeb694538f23a26857e0d6cf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 20 Aug 2020 17:04:32 +0900 Subject: [PATCH 04/16] common taskscheduler: revise functionalities. initialization interfaces has been changed for threads count. if you want to set concrete threads count by system, please specify thread count with it. std threads: tvg::Initializer::init(tvg::CanvasEngine::Sw, std::thread::hardware_concurrency()); if your system provides designed threads info, you can use it. efl: tvg_engine_init(TVG_ENGINE_SW, eina_cpu_count()); I recommend to avoid max threads usage for better performance. Change-Id: I22cfa315768f73fa941be136956cdbb2cf837c20 --- inc/thorvg.h | 4 +- inc/thorvg_capi.h | 2 +- src/bindings/capi/tvgCapi.cpp | 10 +-- src/lib/meson.build | 3 +- src/lib/tvgCommon.h | 4 + src/lib/tvgInitializer.cpp | 21 ++--- src/lib/tvgShapePath.h | 6 +- src/lib/tvgTask.cpp | 156 ---------------------------------- src/lib/tvgTask.h | 72 ---------------- src/lib/tvgTaskScheduler.cpp | 189 +++++++++++++++++++++++++++++++++++++++++ src/lib/tvgTaskScheduler.h | 72 ++++++++++++++++ test/testArc.cpp | 5 +- test/testAsync.cpp | 5 +- test/testBlending.cpp | 5 +- test/testBoundary.cpp | 5 +- test/testCapi.c | 2 +- test/testCommon.h | 1 + test/testCustomTransform.cpp | 5 +- test/testDirectUpdate.cpp | 5 +- test/testGradientTransform.cpp | 39 +++++---- test/testLinearGradient.cpp | 5 +- test/testMultiShapes.cpp | 5 +- test/testPath.cpp | 5 +- test/testPathCopy.cpp | 5 +- test/testRadialGradient.cpp | 5 +- test/testScene.cpp | 6 +- test/testSceneTransform.cpp | 5 +- test/testShape.cpp | 5 +- test/testStroke.cpp | 5 +- test/testStrokeLine.cpp | 6 +- test/testSvg.cpp | 5 +- test/testSvg2.cpp | 5 +- test/testTransform.cpp | 5 +- test/testUpdate.cpp | 5 +- 34 files changed, 387 insertions(+), 296 deletions(-) delete mode 100644 src/lib/tvgTask.cpp delete mode 100644 src/lib/tvgTask.h create mode 100644 src/lib/tvgTaskScheduler.cpp create mode 100644 src/lib/tvgTaskScheduler.h diff --git a/inc/thorvg.h b/inc/thorvg.h index 18013fa..0de9bc0 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -366,10 +366,8 @@ public: * * @see ... */ - static Result init(CanvasEngine engine) noexcept; + static Result init(CanvasEngine engine, uint32_t threads) noexcept; static Result term(CanvasEngine engine) noexcept; - static Result threads(uint32_t cnt) noexcept; - static uint32_t threads() noexcept; _TVG_DISABLE_CTOR(Initializer); }; diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 811c82e..afc294a 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -88,7 +88,7 @@ typedef struct /************************************************************************/ /* Engine API */ /************************************************************************/ -TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method); +TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads); TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method); diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index ac8cdcb..0155196 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -50,13 +50,13 @@ struct _Tvg_Gradient /* Engine API */ /************************************************************************/ -TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) { +TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads) { Result ret = Result::Success; - if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw, threads); if (ret != Result::Success) return (Tvg_Result) ret; - if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl); + if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl, threads); return (Tvg_Result) ret; } @@ -64,10 +64,10 @@ TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) { TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) { Result ret = Result::Success; - if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw); + if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::term(tvg::CanvasEngine::Sw); if (ret != Result::Success) return (Tvg_Result) ret; - if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl); + if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::term(tvg::CanvasEngine::Gl); return (Tvg_Result) ret; } diff --git a/src/lib/meson.build b/src/lib/meson.build index 503c35e..bc0d959 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -21,6 +21,7 @@ source_file = [ 'tvgSceneImpl.h', 'tvgShapePath.h', 'tvgShapeImpl.h', + 'tvgTaskScheduler.h', 'tvgBezier.cpp', 'tvgCanvas.cpp', 'tvgFill.cpp', @@ -35,7 +36,7 @@ source_file = [ 'tvgScene.cpp', 'tvgShape.cpp', 'tvgSwCanvas.cpp', - 'tvgTask.cpp', + 'tvgTaskScheduler.cpp', ] common_dep = declare_dependency( diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 66e08bf..c07a4ca 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -29,6 +29,9 @@ #include #include #include +#include +#include + #include "thorvg.h" using namespace std; @@ -46,5 +49,6 @@ using namespace tvg; #include "tvgLoaderMgr.h" #include "tvgRender.h" #include "tvgPaint.h" +#include "tvgTaskScheduler.h" #endif //_TVG_COMMON_H_ diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 2185c0f..17b91a0 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -35,13 +35,12 @@ /* Internal Class Implementation */ /************************************************************************/ -static uint32_t threadCnt = 0; /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -Result Initializer::init(CanvasEngine engine) noexcept +Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept { auto nonSupport = true; @@ -63,6 +62,8 @@ Result Initializer::init(CanvasEngine engine) noexcept if (!LoaderMgr::init()) return Result::Unknown; + TaskScheduler::init(threads); + return Result::Success; } @@ -87,21 +88,9 @@ Result Initializer::term(CanvasEngine engine) noexcept if (nonSupport) return Result::NonSupport; - if (!LoaderMgr::term()) return Result::Unknown; - - return Result::Success; -} - + TaskScheduler::term(); -Result Initializer::threads(uint32_t cnt) noexcept -{ - threadCnt = cnt; + if (!LoaderMgr::term()) return Result::Unknown; return Result::Success; -} - - -uint32_t Initializer::threads() noexcept -{ - return threadCnt; } \ No newline at end of file diff --git a/src/lib/tvgShapePath.h b/src/lib/tvgShapePath.h index 04934dc..f3e0ae5 100644 --- a/src/lib/tvgShapePath.h +++ b/src/lib/tvgShapePath.h @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SHAPE_PATH_CPP_ -#define _TVG_SHAPE_PATH_CPP_ +#ifndef _TVG_SHAPE_PATH_H_ +#define _TVG_SHAPE_PATH_H_ #include "tvgCommon.h" @@ -139,4 +139,4 @@ struct ShapePath } }; -#endif //_TVG_SHAPE_PATH_CPP_ +#endif //_TVG_SHAPE_PATH_H_ diff --git a/src/lib/tvgTask.cpp b/src/lib/tvgTask.cpp deleted file mode 100644 index 81ce22e..0000000 --- a/src/lib/tvgTask.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include - -template -class TaskQueue { - using lock_t = std::unique_lock; - std::deque _q; - bool _done{false}; - std::mutex _mutex; - std::condition_variable _ready; - -public: - bool try_pop(Task &task) - { - lock_t lock{_mutex, std::try_to_lock}; - if (!lock || _q.empty()) return false; - task = std::move(_q.front()); - _q.pop_front(); - return true; - } - - bool try_push(Task &&task) - { - { - lock_t lock{_mutex, std::try_to_lock}; - if (!lock) return false; - _q.push_back(std::move(task)); - } - _ready.notify_one(); - return true; - } - - void done() - { - { - lock_t lock{_mutex}; - _done = true; - } - _ready.notify_all(); - } - - bool pop(Task &task) - { - lock_t lock{_mutex}; - while (_q.empty() && !_done) _ready.wait(lock); - if (_q.empty()) return false; - task = std::move(_q.front()); - _q.pop_front(); - return true; - } - - void push(Task &&task) - { - { - lock_t lock{_mutex}; - _q.push_back(std::move(task)); - } - _ready.notify_one(); - } - -}; - -#include -#include - -namespace tvg -{ - -class Executor -{ - const unsigned _count{std::thread::hardware_concurrency()}; - std::vector _threads; - std::vector> _q{_count}; - std::atomic _index{0}; - void run(unsigned i) - { - // Task Loop - shared_task task; - while (true) { - bool success = false; - - for (unsigned n = 0; n != _count * 2; ++n) { - if (_q[(i + n) % _count].try_pop(task)) { - success = true; - break; - } - } - - if (!success && !_q[i].pop(task)) break; - - (*task)(); - } - } - - Executor() - { - for (unsigned n = 0; n != _count; ++n) { - _threads.emplace_back([&, n] { run(n); }); - } - } - ~Executor() - { - for (auto &e : _q) e.done(); - - for (auto &e : _threads) e.join(); - } - -public: - - static Executor& instance() { - static Executor singleton; - return singleton; - } - - void post(shared_task task) - { - task->prepare(); - - auto i = _index++; - - for (unsigned n = 0; n != _count; ++n) { - if (_q[(i + n) % _count].try_push(std::move(task))) return; - } - - if (_count > 0) { - _q[i % _count].push(std::move(task)); - } - } -}; - -void async(shared_task task) -{ - Executor::instance().post(std::move(task)); -} - -} - - diff --git a/src/lib/tvgTask.h b/src/lib/tvgTask.h deleted file mode 100644 index 9fb250e..0000000 --- a/src/lib/tvgTask.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef _TVG_TASK_H_ -#define _TVG_TASK_H_ - -#include -#include - -namespace tvg -{ - -/* - Task Interface. - Able to run a task in the thread pool. derive from the - task interface and implement run method. - - To get the result call task->get() which will return immidiately if the - task is already finishd otherwise will wait till task completion. - */ - -class Task -{ -public: - virtual ~Task() = default; - void get() { if (_receiver.valid()) _receiver.get(); } - -protected: - virtual void run() = 0; -private: - void operator()() - { - run(); - _sender.set_value(); - } - void prepare() - { - _sender = std::promise(); - _receiver = _sender.get_future(); - } - friend class Executor; - - std::promise _sender; - std::future _receiver; -}; - - -using shared_task = std::shared_ptr; - -/* - async() function takes a shared task and runs it in - a thread pool asyncronously. call get() on the shared_task - to get the ressult out of the shared_task. - */ -void async(shared_task task); - -} - -#endif //_TVG_TASK_H_ \ No newline at end of file diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp new file mode 100644 index 0000000..31b1e84 --- /dev/null +++ b/src/lib/tvgTaskScheduler.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include "tvgCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +namespace tvg { + +struct TaskQueue { + deque> taskDeque; + mutex mtx; + condition_variable ready; + bool done = false; + + bool tryPop(shared_ptr &task) + { + unique_lock lock{mtx, try_to_lock}; + if (!lock || taskDeque.empty()) return false; + task = move(taskDeque.front()); + taskDeque.pop_front(); + + return true; + } + + bool tryPush(shared_ptr &&task) + { + { + unique_lock lock{mtx, try_to_lock}; + if (!lock) return false; + taskDeque.push_back(move(task)); + } + + ready.notify_one(); + + return true; + } + + void complete() + { + { + unique_lock lock{mtx}; + done = true; + } + ready.notify_all(); + } + + bool pop(shared_ptr &task) + { + unique_lock lock{mtx}; + + while (taskDeque.empty() && !done) { + ready.wait(lock); + } + + if (taskDeque.empty()) return false; + + task = move(taskDeque.front()); + taskDeque.pop_front(); + + return true; + } + + void push(shared_ptr &&task) + { + { + unique_lock lock{mtx}; + taskDeque.push_back(move(task)); + } + + ready.notify_one(); + } + +}; + + +class TaskSchedulerImpl +{ +public: + unsigned threadCnt; + vector threads; + vector taskQueues{threadCnt}; + atomic idx{0}; + + TaskSchedulerImpl() + { + for (unsigned i = 0; i < threadCnt; ++i) { + threads.emplace_back([&, i] { run(i); }); + } + } + + ~TaskSchedulerImpl() + { + for (auto& queue : taskQueues) queue.complete(); + for (auto& thread : threads) thread.join(); + } + + void run(unsigned i) + { + shared_ptr task; + + //Thread Loop + while (true) { + auto success = false; + + for (unsigned i = 0; i < threadCnt * 2; ++i) { + if (taskQueues[(i + i) % threadCnt].tryPop(task)) { + success = true; + break; + } + } + + if (!success && !taskQueues[i].pop(task)) break; + + (*task)(); + } + } + + void request(shared_ptr task) + { + //Async + if (threadCnt > 0) { + task->prepare(); + auto i = idx++; + for (unsigned n = 0; n < threadCnt; ++n) { + if (taskQueues[(i + n) % threadCnt].tryPush(move(task))) return; + } + + taskQueues[i % threadCnt].push(move(task)); + + //Sync + } else { + task->run(); + } + } +}; + +} + +static TaskSchedulerImpl* inst = nullptr; + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +void TaskScheduler::init(unsigned threads) +{ + if (inst) return; + inst = new TaskSchedulerImpl; + inst->threadCnt = threads; +} + + +void TaskScheduler::term() +{ + if (!inst) return; + delete(inst); + inst = nullptr; +} + + +void TaskScheduler::request(shared_ptr task) +{ + if (inst) { + inst->request(move(task)); + } +} \ No newline at end of file diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h new file mode 100644 index 0000000..4380a9c --- /dev/null +++ b/src/lib/tvgTaskScheduler.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _TVG_TASK_SCHEDULER_H_ +#define _TVG_TASK_SCHEDULER_H_ + +#include "tvgCommon.h" + +namespace tvg +{ + +struct Task +{ +private: + std::promise sender; + std::future receiver; + +public: + virtual ~Task() = default; + + void get() + { + if (receiver.valid()) receiver.get(); + } + +protected: + virtual void run() = 0; + +private: + void operator()() + { + run(); + sender.set_value(); + } + + void prepare() + { + sender = std::promise(); + receiver = sender.get_future(); + } + + friend class TaskSchedulerImpl; +}; + +struct TaskScheduler +{ + static void init(unsigned threads); + static void term(); + static void request(shared_ptr task); +}; + +} + +#endif //_TVG_TASK_SCHEDULER_H_ \ No newline at end of file diff --git a/test/testArc.cpp b/test/testArc.cpp index 1f15812..9c307d4 100644 --- a/test/testArc.cpp +++ b/test/testArc.cpp @@ -148,8 +148,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testAsync.cpp b/test/testAsync.cpp index 608cefb..25e57ba 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -151,8 +151,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 743b1e0..68623dc 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -131,8 +131,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index 3830687..e2ed1c0 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -120,8 +120,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testCapi.c b/test/testCapi.c index c6df396..1b0018d 100644 --- a/test/testCapi.c +++ b/test/testCapi.c @@ -13,7 +13,7 @@ static uint32_t buffer[WIDTH * HEIGHT]; void testCapi() { - tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL); + tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL, 0); Tvg_Canvas* canvas = tvg_swcanvas_create(); tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888); diff --git a/test/testCommon.h b/test/testCommon.h index 13ac86a..a5f222e 100644 --- a/test/testCommon.h +++ b/test/testCommon.h @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 9daa6fc..50033f9 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -176,8 +176,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 8dcc474..69105c3 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -139,8 +139,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index 77d5f6a..45431e3 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -204,31 +204,34 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { - elm_init(argc, argv); + elm_init(argc, argv); - Elm_Transit *transit = elm_transit_add(); + Elm_Transit *transit = elm_transit_add(); - if (tvgEngine == tvg::CanvasEngine::Sw) { - auto view = createSwView(); - elm_transit_effect_add(transit, transitSwCb, view, nullptr); - } else { - auto view = createGlView(); - elm_transit_effect_add(transit, transitGlCb, view, nullptr); - } + if (tvgEngine == tvg::CanvasEngine::Sw) { + auto view = createSwView(); + elm_transit_effect_add(transit, transitSwCb, view, nullptr); + } else { + auto view = createGlView(); + elm_transit_effect_add(transit, transitGlCb, view, nullptr); + } - elm_transit_duration_set(transit, 2); - elm_transit_repeat_times_set(transit, -1); - elm_transit_auto_reverse_set(transit, EINA_TRUE); - elm_transit_go(transit); + elm_transit_duration_set(transit, 2); + elm_transit_repeat_times_set(transit, -1); + elm_transit_auto_reverse_set(transit, EINA_TRUE); + elm_transit_go(transit); - elm_run(); - elm_shutdown(); + elm_run(); + elm_shutdown(); - //Terminate ThorVG Engine - tvg::Initializer::term(tvgEngine); + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); } else { cout << "engine is not supported" << endl; diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index db11682..d1ed5fa 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -149,8 +149,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 12009bc..3db41b9 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -109,8 +109,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testPath.cpp b/test/testPath.cpp index de6ef60..a265d03 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -126,8 +126,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index fb1080b..b5d97cf 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -163,8 +163,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index 6e77291..a64e47b 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -149,8 +149,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testScene.cpp b/test/testScene.cpp index daa5d86..8c46428 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -156,8 +156,12 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { + elm_init(argc, argv); diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index e64fa9a..ef6c157 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -200,8 +200,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testShape.cpp b/test/testShape.cpp index af4d0c4..56acfd5 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -99,8 +99,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testStroke.cpp b/test/testStroke.cpp index 778d7c7..5ac2265 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -146,8 +146,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 1205bb1..8cc16d0 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -183,8 +183,12 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { + elm_init(argc, argv); diff --git a/test/testSvg.cpp b/test/testSvg.cpp index 06fe350..ad72027 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -141,8 +141,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testSvg2.cpp b/test/testSvg2.cpp index 2300f21..c859b04 100644 --- a/test/testSvg2.cpp +++ b/test/testSvg2.cpp @@ -124,8 +124,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 5ef33f4..6cd9be6 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -167,8 +167,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 3ff6c24..6df8533 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -128,8 +128,11 @@ int main(int argc, char **argv) cout << "tvg engine: opengl" << endl; } + //Threads Count + auto threads = std::thread::hardware_concurrency(); + //Initialize ThorVG Engine - if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) { + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { elm_init(argc, argv); -- 2.7.4 From 8efef7714c17dc615b1dc13537b9c423ac6b9ec0 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 21 Aug 2020 15:56:04 +0900 Subject: [PATCH 05/16] common initializer: don't try initialize engine duplicatedly. Change-Id: I58c715745b8db40fe759582545082f2e6e10626a --- inc/thorvg.h | 2 +- src/lib/tvgInitializer.cpp | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 0de9bc0..16252fe 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -56,7 +56,7 @@ enum class TVG_EXPORT PathCommand { Close = 0, MoveTo, LineTo, CubicTo }; enum class TVG_EXPORT StrokeCap { Square = 0, Round, Butt }; enum class TVG_EXPORT StrokeJoin { Bevel = 0, Round, Miter }; enum class TVG_EXPORT FillSpread { Pad = 0, Reflect, Repeat }; -enum class TVG_EXPORT CanvasEngine { Sw = 0, Gl }; +enum class TVG_EXPORT CanvasEngine { Sw = (1 << 1), Gl = (1 << 2)}; struct Point diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index 17b91a0..7dcc8b9 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -34,7 +34,7 @@ /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ - +static bool initialized = false; /************************************************************************/ /* External Class Implementation */ @@ -42,14 +42,16 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept { + if (initialized) return Result::InsufficientCondition; + auto nonSupport = true; - if (engine == CanvasEngine::Sw) { + if (static_cast(engine) & static_cast(CanvasEngine::Sw)) { #ifdef THORVG_SW_RASTER_SUPPORT if (!SwRenderer::init()) return Result::InsufficientCondition; nonSupport = false; #endif - } else if (engine == CanvasEngine::Gl) { + } else if (static_cast(engine) & static_cast(CanvasEngine::Gl)) { #ifdef THORVG_GL_RASTER_SUPPORT if (!GlRenderer::init()) return Result::InsufficientCondition; nonSupport = false; @@ -64,20 +66,24 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept TaskScheduler::init(threads); + initialized = true; + return Result::Success; } Result Initializer::term(CanvasEngine engine) noexcept { + if (!initialized) return Result::InsufficientCondition; + auto nonSupport = true; - if (engine == CanvasEngine::Sw) { + if (static_cast(engine) & static_cast(CanvasEngine::Sw)) { #ifdef THORVG_SW_RASTER_SUPPORT if (!SwRenderer::term()) return Result::InsufficientCondition; nonSupport = false; #endif - } else if (engine == CanvasEngine::Gl) { + } else if (static_cast(engine) & static_cast(CanvasEngine::Gl)) { #ifdef THORVG_GL_RASTER_SUPPORT if (!GlRenderer::term()) return Result::InsufficientCondition; nonSupport = false; @@ -92,5 +98,7 @@ Result Initializer::term(CanvasEngine engine) noexcept if (!LoaderMgr::term()) return Result::Unknown; + initialized = false; + return Result::Success; } \ No newline at end of file -- 2.7.4 From 2dca9703cf433885c352bc01fb86f8174fdb3672 Mon Sep 17 00:00:00 2001 From: Subhransu Mohanty Date: Fri, 21 Aug 2020 16:53:56 +0900 Subject: [PATCH 06/16] meson: added compiler flags to optimize binary size this reduced library size from 153KB to 119KB. Change-Id: Ie70e5412b42d864fbaa827eec21b3cbc1e8f26af --- src/meson.build | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/meson.build b/src/meson.build index 40d85ce..1fb8989 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,6 +6,9 @@ if (cc.get_id() != 'msvc') compiler_flags += ['-mavx'] message('Enable Advanced Vector Extension') endif + compiler_flags += ['-fno-exceptions', '-fno-rtti', + '-fno-unwind-tables' , '-fno-asynchronous-unwind-tables', + '-Woverloaded-virtual', '-Wno-unused-parameter'] endif -- 2.7.4 From 74e03c0699b5029458aa9e886ca1d01901d67fb8 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 24 Aug 2020 14:45:36 +0900 Subject: [PATCH 07/16] Update README.md update gitter channel address. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aac7ad0..8a6037e 100644 --- a/README.md +++ b/README.md @@ -59,4 +59,4 @@ Lastly, you can acquire the rendered image in buffer memory. [Back to contents](#contents) # ## Issues or Feature Requests? -For immidiate assistant or support please reach us in [Gitter](https://gitter.im/thorvg-dev/community#) +For immidiate assistant or support please reach us in [Gitter](https://gitter.im/thorvg/community) -- 2.7.4 From edb770aa1ae9a791c20a027d7c3373bb2dad8530 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Mon, 24 Aug 2020 17:06:26 +0900 Subject: [PATCH 08/16] taskscheduler: initialize member correctly This patch will fix runtime crash caused by incorrect init variables. --- src/lib/tvgTaskScheduler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp index 31b1e84..e7df53a 100644 --- a/src/lib/tvgTaskScheduler.cpp +++ b/src/lib/tvgTaskScheduler.cpp @@ -101,11 +101,12 @@ class TaskSchedulerImpl public: unsigned threadCnt; vector threads; - vector taskQueues{threadCnt}; + vector taskQueues; atomic idx{0}; - TaskSchedulerImpl() + TaskSchedulerImpl(unsigned count) : taskQueues(count) { + threadCnt = count; for (unsigned i = 0; i < threadCnt; ++i) { threads.emplace_back([&, i] { run(i); }); } @@ -168,8 +169,7 @@ static TaskSchedulerImpl* inst = nullptr; void TaskScheduler::init(unsigned threads) { if (inst) return; - inst = new TaskSchedulerImpl; - inst->threadCnt = threads; + inst = new TaskSchedulerImpl(threads); } -- 2.7.4 From 8da6aa424ffc79956d76fc1eb4f9764aa7d3cdbc Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 21 Aug 2020 21:13:39 +0900 Subject: [PATCH 09/16] svg_loader: applied asynchronous threads tasks for optimal performance. Change-Id: I6575a6a6302c0ae52d1256a5f79f4c080002a4aa --- src/lib/tvgTaskScheduler.cpp | 43 ++++++++++++-------------- src/lib/tvgTaskScheduler.h | 12 ++++---- src/loaders/svg/tvgSvgLoader.cpp | 65 +++++++++++++++++++++------------------- src/loaders/svg/tvgSvgLoader.h | 12 ++++++-- test/testSvg.cpp | 15 +++++++++- 5 files changed, 85 insertions(+), 62 deletions(-) diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp index e7df53a..bdf6edc 100644 --- a/src/lib/tvgTaskScheduler.cpp +++ b/src/lib/tvgTaskScheduler.cpp @@ -30,27 +30,27 @@ namespace tvg { struct TaskQueue { - deque> taskDeque; + deque taskDeque; mutex mtx; condition_variable ready; bool done = false; - bool tryPop(shared_ptr &task) + bool tryPop(Task** task) { unique_lock lock{mtx, try_to_lock}; if (!lock || taskDeque.empty()) return false; - task = move(taskDeque.front()); + *task = taskDeque.front(); taskDeque.pop_front(); return true; } - bool tryPush(shared_ptr &&task) + bool tryPush(Task* task) { { unique_lock lock{mtx, try_to_lock}; if (!lock) return false; - taskDeque.push_back(move(task)); + taskDeque.push_back(task); } ready.notify_one(); @@ -67,7 +67,7 @@ struct TaskQueue { ready.notify_all(); } - bool pop(shared_ptr &task) + bool pop(Task** task) { unique_lock lock{mtx}; @@ -77,17 +77,17 @@ struct TaskQueue { if (taskDeque.empty()) return false; - task = move(taskDeque.front()); + *task = taskDeque.front(); taskDeque.pop_front(); return true; } - void push(shared_ptr &&task) + void push(Task* task) { { unique_lock lock{mtx}; - taskDeque.push_back(move(task)); + taskDeque.push_back(task); } ready.notify_one(); @@ -104,9 +104,8 @@ public: vector taskQueues; atomic idx{0}; - TaskSchedulerImpl(unsigned count) : taskQueues(count) + TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt) { - threadCnt = count; for (unsigned i = 0; i < threadCnt; ++i) { threads.emplace_back([&, i] { run(i); }); } @@ -120,37 +119,33 @@ public: void run(unsigned i) { - shared_ptr task; + Task* task; //Thread Loop while (true) { auto success = false; - for (unsigned i = 0; i < threadCnt * 2; ++i) { - if (taskQueues[(i + i) % threadCnt].tryPop(task)) { + if (taskQueues[(i + i) % threadCnt].tryPop(&task)) { success = true; break; } } - if (!success && !taskQueues[i].pop(task)) break; - + if (!success && !taskQueues[i].pop(&task)) break; (*task)(); } } - void request(shared_ptr task) + void request(Task* task) { //Async if (threadCnt > 0) { task->prepare(); auto i = idx++; for (unsigned n = 0; n < threadCnt; ++n) { - if (taskQueues[(i + n) % threadCnt].tryPush(move(task))) return; + if (taskQueues[(i + n) % threadCnt].tryPush(task)) return; } - - taskQueues[i % threadCnt].push(move(task)); - + taskQueues[i % threadCnt].push(task); //Sync } else { task->run(); @@ -181,9 +176,9 @@ void TaskScheduler::term() } -void TaskScheduler::request(shared_ptr task) +void TaskScheduler::request(Task* task) { if (inst) { - inst->request(move(task)); + inst->request(task); } -} \ No newline at end of file +} diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h index 4380a9c..1b1cc12 100644 --- a/src/lib/tvgTaskScheduler.h +++ b/src/lib/tvgTaskScheduler.h @@ -30,15 +30,17 @@ namespace tvg struct Task { private: - std::promise sender; - std::future receiver; + promise sender; + future receiver; public: virtual ~Task() = default; void get() { - if (receiver.valid()) receiver.get(); + if (receiver.valid()) { + receiver.get(); + } } protected: @@ -53,7 +55,7 @@ private: void prepare() { - sender = std::promise(); + sender = promise(); receiver = sender.get_future(); } @@ -64,7 +66,7 @@ struct TaskScheduler { static void init(unsigned threads); static void term(); - static void request(shared_ptr task); + static void request(Task* task); }; } diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index b174300..341dc55 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -2263,12 +2263,36 @@ static bool _svgLoaderParserForValidCheck(void* data, SimpleXMLType type, const return res; } + +void SvgTask::run() +{ + if (!simpleXmlParse(loader->content, loader->size, true, _svgLoaderParser, &(loader->loaderData))) return; + + if (loader->loaderData.doc) { + _updateStyle(loader->loaderData.doc, nullptr); + auto 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(); + } + } + } + loader->root = loader->builder.build(loader->loaderData.doc); +}; + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -SvgLoader::SvgLoader() +SvgLoader::SvgLoader() : task(new SvgTask) { + task->loader = this; } @@ -2339,34 +2363,7 @@ bool SvgLoader::read() { if (!content || size == 0) return false; - loaderData = {vector(), - nullptr, - nullptr, - vector(), - nullptr, - nullptr, - 0, - false}; - - loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); - - if (!simpleXmlParse(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(); - } - } - } - - root = builder.build(loaderData.doc); + TaskScheduler::request(task); return true; } @@ -2374,6 +2371,12 @@ bool SvgLoader::read() bool SvgLoader::close() { + if (task) { + task->get(); + delete(task); + task = nullptr; + } + if (loaderData.svgParse) { free(loaderData.svgParse); loaderData.svgParse = nullptr; @@ -2387,5 +2390,7 @@ bool SvgLoader::close() unique_ptr SvgLoader::data() { - return move(root); + if (task) task->get(); + if (root) return move(root); + else return nullptr; } \ No newline at end of file diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index e85582b..451583f 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -25,10 +25,18 @@ #include "tvgSvgLoaderCommon.h" #include "tvgSvgSceneBuilder.h" +class SvgLoader; + +struct SvgTask : Task +{ + SvgLoader* loader = nullptr; + void run() override; +}; + class SvgLoader : public Loader { -private: +public: string filePath; const char* content = nullptr; uint32_t size = 0; @@ -36,8 +44,8 @@ private: SvgLoaderData loaderData; SvgSceneBuilder builder; unique_ptr root; + SvgTask* task = nullptr; -public: SvgLoader(); ~SvgLoader(); diff --git a/test/testSvg.cpp b/test/testSvg.cpp index ad72027..7e3d775 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -1,3 +1,4 @@ +#include #include "testCommon.h" /************************************************************************/ @@ -9,6 +10,8 @@ static int count = 0; +static std::vector> pictures; + void svgDirCallback(const char* name, const char* path, void* data) { tvg::Canvas* canvas = static_cast(data); @@ -40,7 +43,7 @@ void svgDirCallback(const char* name, const char* path, void* data) picture->translate((count % NUM_PER_LINE) * SIZE - x, SIZE * (count / NUM_PER_LINE) - y); - canvas->push(move(picture)); + pictures.push_back(move(picture)); cout << "SVG: " << buf << endl; @@ -59,6 +62,16 @@ void tvgDrawCmds(tvg::Canvas* canvas) if (canvas->push(move(shape)) != tvg::Result::Success) return; eina_file_dir_list("./svgs", EINA_TRUE, svgDirCallback, canvas); + + /* This showcase shows you asynchrounous loading of svg. + For this, pushing pictures at a certian sync time. + This means it earns the time to finish loading svg resources, + otherwise you can push pictures immediately. */ + for (auto& paint : pictures) { + canvas->push(move(paint)); + } + + pictures.clear(); } -- 2.7.4 From dd85eea19c6987389cee1b77302c6d491063eb8b Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Mon, 24 Aug 2020 23:31:50 +0200 Subject: [PATCH 10/16] SwRenderer: fixing unnecessary nesting in prepare() Validating the above by adding shape/canvas update to testCapi.cpp Change-Id: I7db8d014f4aff7b5b2884c2dca5af119329e9d43 --- src/lib/sw_engine/tvgSwRenderer.cpp | 40 ++++++++++++++++++------------------- test/testCapi.c | 17 ++++++++++++++-- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 1a1e0bf..28ddf63 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -127,28 +127,28 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* if (!shapeGenRle(shape, &sdata, clip, antiAlias)) return shape; } } - //Fill - if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { - auto fill = sdata.fill(); - if (fill) { - auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; - if (ctable) shapeResetFill(shape); - if (!shapeGenFillColors(shape, fill, matrix, surface, ctable)) return shape; - } else { - shapeDelFill(shape); - } + } + //Fill + if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { + auto fill = sdata.fill(); + if (fill) { + auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; + if (ctable) shapeResetFill(shape); + if (!shapeGenFillColors(shape, fill, matrix, surface, ctable)) return shape; + } else { + shapeDelFill(shape); } - //Stroke - if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { - if (strokeAlpha > 0) { - shapeResetStroke(shape, &sdata, matrix); - if (!shapeGenStrokeRle(shape, &sdata, matrix, clip)) return shape; - } else { - shapeDelStroke(shape); - } + } + //Stroke + if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { + if (strokeAlpha > 0) { + shapeResetStroke(shape, &sdata, matrix); + if (!shapeGenStrokeRle(shape, &sdata, matrix, clip)) return shape; + } else { + shapeDelStroke(shape); } - shapeDelOutline(shape); } + shapeDelOutline(shape); return shape; } @@ -182,4 +182,4 @@ SwRenderer* SwRenderer::inst() { //We know renderer type, avoid dynamic_cast for performance. return static_cast(RenderInitializer::inst(renderInit)); -} \ No newline at end of file +} diff --git a/test/testCapi.c b/test/testCapi.c index 1b0018d..e31db67 100644 --- a/test/testCapi.c +++ b/test/testCapi.c @@ -32,7 +32,6 @@ void testCapi() {.offset=1.0, .r=0, .g=0, .b=255, .a=255} }; - Tvg_Paint *shape1 = tvg_shape_new(); tvg_shape_append_rect(shape1, 500, 500, 100, 100, 30, 30); Tvg_Gradient* grad1 = tvg_radial_gradient_new(); @@ -103,9 +102,23 @@ void testCapi() }; tvg_gradient_color_stops(grad5, color_stops5, 2); tvg_shape_linear_gradient_set(shape4, grad5); - tvg_canvas_push(canvas, shape4); + Tvg_Gradient* grad6 = tvg_radial_gradient_new(); + tvg_radial_gradient_set(grad6, 550, 550, 50); + Tvg_Color_Stop color_stops6[2] = + { + {.offset=0.0, .r=0, .g=125, .b=0, .a=255}, + {.offset=1, .r=125, .g=0, .b=125, .a=255}, + }; + tvg_gradient_color_stops(grad6, color_stops6, 2); + tvg_shape_radial_gradient_set(shape1, grad6); + tvg_canvas_update(canvas); + + tvg_shape_set_stroke_width(shape,3); + tvg_shape_set_stroke_color(shape, 125, 0, 125, 255); + tvg_canvas_update_paint(canvas, shape); + tvg_canvas_draw(canvas); tvg_canvas_sync(canvas); -- 2.7.4 From 858bb9b9f175c9acb64c92cfd6466e7dee61be8a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 26 Aug 2020 16:39:10 +0900 Subject: [PATCH 11/16] sw_engine: applied async rasterizing based on task scheduler. Now, we have 2 points for asynchronous behaviors. 1. update shapes: Each shape update will be performed by async when you push shape to canvas. Meaning, if you have time gap between update and rendering in process main-loop, you can have a benefit by this. 2. rasterization by canvas: Canvas.draw() will be performed asynchnously until you call canvas.sync(); Meaing, if you can trigger tvg rendering eariler than composition time. You can have a benefit by this. If these 1, 2 points might not work for your program, You can just toggle off async by setting threads number zero at initialization. Or if you could apply either point of them for your program, It might be good for performance. But the best approach is to make both async properly. Though this might need to fine-grained tuning integration between your program & tvg, You could achieve the best peformance by parallelzing tasks as possible without any jobs delaying. Change-Id: I04f9a61ebb426fd897624f5b24c83841737e6b5b --- src/lib/sw_engine/tvgSwCommon.h | 10 +- src/lib/sw_engine/tvgSwRenderer.cpp | 195 +++++++++++++++++++++++------------- src/lib/sw_engine/tvgSwRenderer.h | 8 +- src/lib/tvgTaskScheduler.h | 5 + 4 files changed, 141 insertions(+), 77 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index a600cb9..256c4bb 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -203,11 +203,11 @@ struct SwFill struct SwShape { - SwOutline* outline; - SwStroke* stroke; - SwFill* fill; - SwRleData* rle; - SwRleData* strokeRle; + SwOutline* outline = nullptr; + SwStroke* stroke = nullptr; + SwFill* fill = nullptr; + SwRleData* rle = nullptr; + SwRleData* strokeRle = nullptr; SwBBox bbox; bool rect; //Fast Track: Othogonal rectangle? diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 28ddf63..0d77d38 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -27,6 +27,63 @@ /************************************************************************/ static RenderInitializer renderInit; +struct SwTask : Task +{ + SwShape shape; + const Shape* sdata = nullptr; + Matrix* transform = nullptr; + SwSurface* surface = nullptr; + RenderUpdateFlag flags = RenderUpdateFlag::None; + + void run() override + { + //Valid Stroking? + uint8_t strokeAlpha = 0; + auto strokeWidth = sdata->strokeWidth(); + if (strokeWidth > FLT_EPSILON) { + sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha); + } + + SwSize clip = {static_cast(surface->w), static_cast(surface->h)}; + + //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, transform)) return; + if (renderShape) { + auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true; + if (!shapeGenRle(&shape, sdata, clip, antiAlias)) return; + } + } + } + //Fill + if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { + auto fill = sdata->fill(); + if (fill) { + auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; + if (ctable) shapeResetFill(&shape); + if (!shapeGenFillColors(&shape, fill, transform, surface, ctable)) return; + } else { + shapeDelFill(&shape); + } + } + //Stroke + if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { + if (strokeAlpha > 0) { + shapeResetStroke(&shape, sdata, transform); + if (!shapeGenStrokeRle(&shape, sdata, transform, clip)) return; + } else { + shapeDelStroke(&shape); + } + } + shapeDelOutline(&shape); + } +}; + /************************************************************************/ /* External Class Implementation */ @@ -34,10 +91,30 @@ static RenderInitializer renderInit; SwRenderer::~SwRenderer() { + flush(); if (surface) delete(surface); } +bool SwRenderer::clear() +{ + if (this->valid() || tasks.size() > 0) return false; + + return flush(); +} + + +bool SwRenderer::flush() +{ + this->get(); //complete rendering + + for (auto task : tasks) task->get(); + tasks.clear(); + + return true; +} + + 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; @@ -59,98 +136,76 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t bool SwRenderer::preRender() { - return rasterClear(surface); -} + //before we start rendering, we should finish all preparing tasks + for (auto task : tasks) task->get(); + TaskScheduler::request(this); -bool SwRenderer::render(const Shape& sdata, TVG_UNUSED void *data) -{ - auto shape = static_cast(data); - if (!shape) return false; + return true; +} - uint8_t r, g, b, a; - 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); +void SwRenderer::run() +{ + rasterClear(surface); + + for (auto task : tasks) { + 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); } - sdata.strokeColor(&r, &g, &b, &a); - if (a > 0) rasterStroke(surface, shape, r, g, b, a); - - return true; -} + tasks.clear(); +}; bool SwRenderer::dispose(TVG_UNUSED const Shape& sdata, void *data) { - auto shape = static_cast(data); - if (!shape) return false; - shapeFree(shape); + auto task = static_cast(data); + if (!task) return true; + + task->get(); + shapeFree(&task->shape); + if (task->transform) free(task->transform); + delete(task); + return true; } void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags) { - //prepare shape data - auto shape = static_cast(data); - if (!shape) { - shape = static_cast(calloc(1, sizeof(SwShape))); - if (!shape) return nullptr; + //prepare task + auto task = static_cast(data); + if (!task) { + task = new SwTask; + if (!task) return nullptr; } - if (flags == RenderUpdateFlag::None) return shape; + if (flags == RenderUpdateFlag::None || task->valid()) return task; - SwSize clip = {static_cast(surface->w), static_cast(surface->h)}; + task->sdata = &sdata; - //Valid Stroking? - uint8_t strokeAlpha = 0; - auto strokeWidth = sdata.strokeWidth(); - if (strokeWidth > FLT_EPSILON) { - sdata.strokeColor(nullptr, nullptr, nullptr, &strokeAlpha); + if (transform) { + if (!task->transform) task->transform = static_cast(malloc(sizeof(Matrix))); + *task->transform = transform->m; + } else { + if (task->transform) free(task->transform); + task->transform = nullptr; } - 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 (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { - auto fill = sdata.fill(); - if (fill) { - auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; - if (ctable) shapeResetFill(shape); - if (!shapeGenFillColors(shape, fill, matrix, surface, ctable)) return shape; - } else { - shapeDelFill(shape); - } - } - //Stroke - if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { - if (strokeAlpha > 0) { - shapeResetStroke(shape, &sdata, matrix); - if (!shapeGenStrokeRle(shape, &sdata, matrix, clip)) return shape; - } else { - shapeDelStroke(shape); - } - } - shapeDelOutline(shape); + task->surface = surface; + task->flags = flags; + + tasks.push_back(task); + TaskScheduler::request(task); - return shape; + return task; } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 2185f34..67d2f15 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -23,20 +23,23 @@ #define _TVG_SW_RENDERER_H_ struct SwSurface; +struct SwTask; namespace tvg { -class SwRenderer : public RenderMethod +class SwRenderer : public RenderMethod, public Task { public: void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override; 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, uint32_t cs); + bool clear() override; + bool flush() override; uint32_t ref() override; uint32_t unref() override; + void run() override; static SwRenderer* inst(); static int init(); @@ -44,6 +47,7 @@ public: private: SwSurface* surface = nullptr; + vector tasks; SwRenderer(){}; ~SwRenderer(); diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h index 1b1cc12..31d1ee1 100644 --- a/src/lib/tvgTaskScheduler.h +++ b/src/lib/tvgTaskScheduler.h @@ -43,6 +43,11 @@ public: } } + bool valid() + { + return receiver.valid(); + } + protected: virtual void run() = 0; -- 2.7.4 From 627195ffad7214a523d3bf9906714ccc333e8388 Mon Sep 17 00:00:00 2001 From: Mateusz Palkowski Date: Wed, 26 Aug 2020 11:26:40 +0200 Subject: [PATCH 12/16] tvgShape: fixed missing check in Shape::fill Without this check, setting same fill twice results in crash later. Change-Id: I38e7026c52a250f65923c4e3008868ed471bf885 --- src/lib/tvgShape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 8db945d..8d0beb8 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -290,7 +290,7 @@ Result Shape::fill(unique_ptr f) noexcept auto p = f.release(); if (!p) return Result::MemoryCorruption; - if (impl->fill) delete(impl->fill); + if (impl->fill && impl->fill != p) delete(impl->fill); impl->fill = p; impl->flag |= RenderUpdateFlag::Gradient; -- 2.7.4 From 8a432b3515a3a7bb174004c5d10af09cce212e1d Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 28 Aug 2020 11:28:59 +0900 Subject: [PATCH 13/16] sw_engine: + exceptional handling for safety Change-Id: I3ee6ca40590c5af5fd7243f419eaf96197ba757b --- src/lib/sw_engine/tvgSwShape.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index d0a8f96..d2687de 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -344,6 +344,7 @@ SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform) const float* pattern; dash.cnt = sdata->strokeDash(&pattern); + if (dash.cnt == 0) return nullptr; //Is it safe to mutual exclusive? dash.pattern = const_cast(pattern); -- 2.7.4 From e7621ee4ab7e9c4633d57690e84905904efd85cf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 28 Aug 2020 18:55:03 +0900 Subject: [PATCH 14/16] capi: fix memory leak. Here canvas type should be explicitly defined, it deleted its instance as a Canvas. Change-Id: I85664462cad675ba537a3e79f02ccd6f263f613b --- src/bindings/capi/tvgCapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 0155196..370eee5 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -83,7 +83,7 @@ TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create() TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas) { - delete(canvas); + delete(reinterpret_cast(canvas)); return TVG_RESULT_SUCCESS; } -- 2.7.4 From ad7a57cd3289193d857b86e6e96c84c4540a0b76 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 28 Aug 2020 19:16:01 +0900 Subject: [PATCH 15/16] sw_engine: fix memory leak. free dash outline stroke data memory properly. Change-Id: I25bebc38c2d6d7f69d04f6288a5b6863324b70d6 --- src/lib/sw_engine/tvgSwShape.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index d2687de..b738f89 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -618,11 +618,13 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip) { SwOutline* shapeOutline = nullptr; + bool freeOutline = false; //Dash Style Stroke if (sdata->strokeDash(nullptr) > 0) { shapeOutline = _genDashOutline(sdata, transform); if (!shapeOutline) return false; + freeOutline = true; //Normal Style stroke } else { if (!shape->outline) { @@ -643,6 +645,7 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo shape->strokeRle = rleRender(strokeOutline, bbox, clip, true); + if (freeOutline) _delOutline(shapeOutline); _delOutline(strokeOutline); return true; -- 2.7.4 From 21a0cd71003547de81071ad1d71b614f3df104b6 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 1 Sep 2020 15:42:33 +0900 Subject: [PATCH 16/16] svg_loader: code refactoring revise code for simple & better readibility. Change-Id: Idb20ac6c05b8dcd451a1627d796bf422f6d9d39f --- src/loaders/svg/tvgSvgLoader.cpp | 51 +++++++++++++----------------------- src/loaders/svg/tvgSvgLoaderCommon.h | 8 +++--- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 341dc55..fedf8a9 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -1454,8 +1454,8 @@ static void _cloneNode(SvgNode* from, SvgNode* parent) newNode = _createNode(parent, from->type); _copyAttr(newNode, from); - for (vector::iterator itrChild = from->child.begin(); itrChild != from->child.end(); itrChild++) { - _cloneNode(*itrChild, newNode); + for (auto child : from->child) { + _cloneNode(child, newNode); } _freeNode(newNode); @@ -1489,13 +1489,6 @@ static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const cha return loader->svgParse->node; } - -#define TAG_DEF(Name, Name1) \ - { \ -#Name, sizeof(#Name), _create##Name1##Node \ - } - - //TODO: Implement 'text' primitive static constexpr struct { @@ -1503,14 +1496,14 @@ static constexpr struct int sz; FactoryMethod tagHandler; } graphicsTags[] = { - TAG_DEF(use, Use), - TAG_DEF(circle, Circle), - TAG_DEF(ellipse, Ellipse), - TAG_DEF(path, Path), - TAG_DEF(polygon, Polygon), - TAG_DEF(rect, Rect), - TAG_DEF(polyline, Polyline), - TAG_DEF(line, Line), + {"use", sizeof("use"), _createUseNode}, + {"circle", sizeof("circle"), _createCircleNode}, + {"ellipse", sizeof("ellipse"), _createEllipseNode}, + {"path", sizeof("path"), _createPathNode}, + {"polygon", sizeof("polygon"), _createPolygonNode}, + {"rect", sizeof("rect"), _createRectNode}, + {"polyline", sizeof("polyline"), _createPolylineNode}, + {"line", sizeof("line"), _createLineNode} }; @@ -1520,9 +1513,9 @@ static constexpr struct int sz; FactoryMethod tagHandler; } groupTags[] = { - TAG_DEF(defs, Defs), - TAG_DEF(g, G), - TAG_DEF(svg, Svg), + {"defs", sizeof("defs"), _createDefsNode}, + {"g", sizeof("g"), _createGNode}, + {"svg", sizeof("svg"), _createSvgNode} }; @@ -1895,20 +1888,14 @@ static GradientFactoryMethod _findGradientFactory(const char* name) } -#define POP_TAG(Tag) \ - { \ -#Tag, sizeof(#Tag) \ - } - - static constexpr struct { const char* tag; size_t sz; } popArray[] = { - POP_TAG(g), - POP_TAG(svg), - POP_TAG(defs) + {"g", sizeof("g")}, + {"svg", sizeof("svg")}, + {"defs", sizeof("defs")} }; @@ -2165,8 +2152,8 @@ static void _freeNode(SvgNode* node) { if (!node) return; - for(vector::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) { - _freeNode(*itrChild); + for(auto child : node->child) { + _freeNode(child); } node->child.clear(); @@ -2200,7 +2187,6 @@ static void _freeNode(SvgNode* node) break; } } - if (!node->child.empty()) node->child.clear(); free(node); } @@ -2376,7 +2362,6 @@ bool SvgLoader::close() delete(task); task = nullptr; } - if (loaderData.svgParse) { free(loaderData.svgParse); loaderData.svgParse = nullptr; diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 5bf8333..bba9523 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -116,8 +116,8 @@ enum class SvgParserLengthType Other }; -typedef struct _SvgNode SvgNode; -typedef struct _SvgStyleGradient SvgStyleGradient; +struct SvgNode; +struct SvgStyleGradient; struct SvgDocNode { @@ -231,7 +231,7 @@ struct SvgDash float gap; }; -struct _SvgStyleGradient +struct SvgStyleGradient { SvgGradientType type; string *id; @@ -277,7 +277,7 @@ struct SvgStyleProperty uint8_t b; }; -struct _SvgNode +struct SvgNode { SvgNodeType type; SvgNode* parent; -- 2.7.4