From 29cea11b6480372f04ea78f1bd9fa5b5c688972b Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Verschelde?= Date: Mon, 23 May 2022 18:35:10 +0200 Subject: [PATCH 01/16] Format code files with dos2unix, ensure newline at EOF Change-Id: I08dab1f492d295fdb9d9a4fb451578778be5b77a --- src/examples/Accessor.cpp | 2 +- src/examples/ImageScaleDown.cpp | 2 +- src/examples/ImageScaleUp.cpp | 2 +- src/lib/gl_engine/tvgGlCommon.h | 130 +++++++++---------- src/lib/gl_engine/tvgGlGpuBuffer.cpp | 2 +- src/lib/sw_engine/tvgSwCommon.h | 2 +- src/lib/sw_engine/tvgSwFill.cpp | 2 +- src/lib/sw_engine/tvgSwMath.cpp | 4 +- src/lib/sw_engine/tvgSwMemPool.cpp | 2 +- src/lib/sw_engine/tvgSwRaster.cpp | 2 +- src/lib/sw_engine/tvgSwRasterC.h | 2 +- src/lib/sw_engine/tvgSwRasterTexmap.h | 2 +- src/lib/sw_engine/tvgSwRle.cpp | 2 +- src/lib/sw_engine/tvgSwStroke.cpp | 2 +- src/lib/tvgAccessor.cpp | 2 +- src/lib/tvgFill.cpp | 2 +- src/lib/tvgPicture.cpp | 2 +- src/lib/tvgRadialGradient.cpp | 2 +- src/lib/tvgRender.cpp | 2 +- src/lib/tvgScene.cpp | 2 +- src/lib/tvgShape.cpp | 2 +- src/lib/tvgSwCanvas.cpp | 2 +- src/loaders/jpg/tvgJpgLoader.cpp | 2 +- src/loaders/png/tvgLodePng.cpp | 2 +- src/loaders/png/tvgLodePng.h | 2 +- src/loaders/tvg/tvgTvgCommon.h | 2 +- test/capi/capiScene.cpp | 230 +++++++++++++++++----------------- test/testInitializer.cpp | 2 +- test/testPaint.cpp | 2 +- test/testShape.cpp | 2 +- 30 files changed, 209 insertions(+), 209 deletions(-) diff --git a/src/examples/Accessor.cpp b/src/examples/Accessor.cpp index 3469bd9..89dcbf4 100644 --- a/src/examples/Accessor.cpp +++ b/src/examples/Accessor.cpp @@ -164,4 +164,4 @@ int main(int argc, char **argv) cout << "engine is not supported" << endl; } return 0; -} \ No newline at end of file +} diff --git a/src/examples/ImageScaleDown.cpp b/src/examples/ImageScaleDown.cpp index 7ed41bd..1a867f7 100644 --- a/src/examples/ImageScaleDown.cpp +++ b/src/examples/ImageScaleDown.cpp @@ -187,4 +187,4 @@ int main(int argc, char **argv) cout << "engine is not supported" << endl; } return 0; -} \ No newline at end of file +} diff --git a/src/examples/ImageScaleUp.cpp b/src/examples/ImageScaleUp.cpp index 7b420ef..ebcc90b 100644 --- a/src/examples/ImageScaleUp.cpp +++ b/src/examples/ImageScaleUp.cpp @@ -187,4 +187,4 @@ int main(int argc, char **argv) cout << "engine is not supported" << endl; } return 0; -} \ No newline at end of file +} diff --git a/src/lib/gl_engine/tvgGlCommon.h b/src/lib/gl_engine/tvgGlCommon.h index 11cc7c9..165103d 100644 --- a/src/lib/gl_engine/tvgGlCommon.h +++ b/src/lib/gl_engine/tvgGlCommon.h @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2020 - 2022 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_GL_COMMON_H_ -#define _TVG_GL_COMMON_H_ - -#include -#include -#include "tvgCommon.h" -#include "tvgRender.h" - - -#define GL_CHECK(x) \ - x; \ - do { \ - GLenum glError = glGetError(); \ - if(glError != GL_NO_ERROR) { \ - TVGERR("GL_ENGINE", "glGetError() = %i (0x%.8x)", glError, glError); \ - assert(0); \ - } \ - } while(0) - -#define EGL_CHECK(x) \ - x; \ - do { \ - EGLint eglError = eglGetError(); \ - if(eglError != EGL_SUCCESS) { \ - TVGERR("GL_ENGINE", "eglGetError() = %i (0x%.8x)", eglError, eglError); \ - assert(0); \ - } \ - } while(0) - - -class GlGeometry; - -struct GlShape -{ - const Shape* shape = nullptr; - float viewWd; - float viewHt; - RenderUpdateFlag updateFlag = None; - unique_ptr geometry; -}; - - -#endif /* _TVG_GL_COMMON_H_ */ +/* + * Copyright (c) 2020 - 2022 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_GL_COMMON_H_ +#define _TVG_GL_COMMON_H_ + +#include +#include +#include "tvgCommon.h" +#include "tvgRender.h" + + +#define GL_CHECK(x) \ + x; \ + do { \ + GLenum glError = glGetError(); \ + if(glError != GL_NO_ERROR) { \ + TVGERR("GL_ENGINE", "glGetError() = %i (0x%.8x)", glError, glError); \ + assert(0); \ + } \ + } while(0) + +#define EGL_CHECK(x) \ + x; \ + do { \ + EGLint eglError = eglGetError(); \ + if(eglError != EGL_SUCCESS) { \ + TVGERR("GL_ENGINE", "eglGetError() = %i (0x%.8x)", eglError, eglError); \ + assert(0); \ + } \ + } while(0) + + +class GlGeometry; + +struct GlShape +{ + const Shape* shape = nullptr; + float viewWd; + float viewHt; + RenderUpdateFlag updateFlag = None; + unique_ptr geometry; +}; + + +#endif /* _TVG_GL_COMMON_H_ */ diff --git a/src/lib/gl_engine/tvgGlGpuBuffer.cpp b/src/lib/gl_engine/tvgGlGpuBuffer.cpp index 12ee24d..6f5b2e8 100644 --- a/src/lib/gl_engine/tvgGlGpuBuffer.cpp +++ b/src/lib/gl_engine/tvgGlGpuBuffer.cpp @@ -52,4 +52,4 @@ void GlGpuBuffer::updateBufferData(Target target, uint32_t size, const void* dat void GlGpuBuffer::unbind(Target target) { GL_CHECK(glBindBuffer(static_cast(target), 0)); -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 157fdb8..47b0cb8 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 04014a9..bba6f26 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index 7f13609..ced66ae 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -499,4 +499,4 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S renderRegion.max.y = (yMax + 63) >> 6; } return mathClipBBox(clipRegion, renderRegion); -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwMemPool.cpp b/src/lib/sw_engine/tvgSwMemPool.cpp index 3ab0b60..d2962e6 100644 --- a/src/lib/sw_engine/tvgSwMemPool.cpp +++ b/src/lib/sw_engine/tvgSwMemPool.cpp @@ -153,4 +153,4 @@ bool mpoolTerm(SwMpool* mpool) free(mpool); return true; -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 156ce55..810df8d 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/lib/sw_engine/tvgSwRasterC.h b/src/lib/sw_engine/tvgSwRasterC.h index d479ede..de6b35f 100644 --- a/src/lib/sw_engine/tvgSwRasterC.h +++ b/src/lib/sw_engine/tvgSwRasterC.h @@ -61,4 +61,4 @@ static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& regi } } return true; -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwRasterTexmap.h b/src/lib/sw_engine/tvgSwRasterTexmap.h index 1faedd6..abb57d7 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmap.h +++ b/src/lib/sw_engine/tvgSwRasterTexmap.h @@ -599,4 +599,4 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const _rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans); return _apply(surface, aaSpans); -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index aa97586..63e7fc9 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -1040,4 +1040,4 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip) _replaceClipSpan(rle, spans, spansEnd - spans); TVGLOG("SW_ENGINE", "Using ClipRect!"); -} \ No newline at end of file +} diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index fa213cc..be43927 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved. * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/lib/tvgAccessor.cpp b/src/lib/tvgAccessor.cpp index 9fd564d..092c8b0 100644 --- a/src/lib/tvgAccessor.cpp +++ b/src/lib/tvgAccessor.cpp @@ -81,4 +81,4 @@ Accessor::Accessor() unique_ptr Accessor::gen() noexcept { return unique_ptr(new Accessor); -} \ No newline at end of file +} diff --git a/src/lib/tvgFill.cpp b/src/lib/tvgFill.cpp index 0c0581a..eecf239 100644 --- a/src/lib/tvgFill.cpp +++ b/src/lib/tvgFill.cpp @@ -112,4 +112,4 @@ Fill* Fill::duplicate() const noexcept uint32_t Fill::identifier() const noexcept { return pImpl->id; -} \ No newline at end of file +} diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 1125b1e..1e04e25 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -118,4 +118,4 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept } if (pImpl->surface) return pImpl->surface->buffer; else return nullptr; -} \ No newline at end of file +} diff --git a/src/lib/tvgRadialGradient.cpp b/src/lib/tvgRadialGradient.cpp index 7aba550..7f4e1d7 100644 --- a/src/lib/tvgRadialGradient.cpp +++ b/src/lib/tvgRadialGradient.cpp @@ -94,4 +94,4 @@ unique_ptr RadialGradient::gen() noexcept uint32_t RadialGradient::identifier() noexcept { return TVG_CLASS_ID_RADIAL; -} \ No newline at end of file +} diff --git a/src/lib/tvgRender.cpp b/src/lib/tvgRender.cpp index 145f974..90f0917 100644 --- a/src/lib/tvgRender.cpp +++ b/src/lib/tvgRender.cpp @@ -70,4 +70,4 @@ RenderTransform::RenderTransform() RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs) { m = mathMultiply(&lhs->m, &rhs->m); -} \ No newline at end of file +} diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index ff43d3c..0beec47 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -73,4 +73,4 @@ Result Scene::clear(bool free) noexcept pImpl->clear(free); return Result::Success; -} \ No newline at end of file +} diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 3a3af5f..e57f2ea 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -424,4 +424,4 @@ Result Shape::fill(FillRule r) noexcept FillRule Shape::fillRule() const noexcept { return pImpl->rule; -} \ No newline at end of file +} diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index 8c9de8c..b5cae42 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -102,4 +102,4 @@ unique_ptr SwCanvas::gen() noexcept return unique_ptr(new SwCanvas); #endif return nullptr; -} \ No newline at end of file +} diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index 7b90b4a..ffdef30 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -134,4 +134,4 @@ void JpgLoader::run(unsigned tid) image = nullptr; } image = jpgdDecompress(decoder); -} \ No newline at end of file +} diff --git a/src/loaders/png/tvgLodePng.cpp b/src/loaders/png/tvgLodePng.cpp index 5c01c5a..eaed025 100644 --- a/src/loaders/png/tvgLodePng.cpp +++ b/src/loaders/png/tvgLodePng.cpp @@ -2644,4 +2644,4 @@ void lodepng_state_cleanup(LodePNGState* state) { lodepng_color_mode_cleanup(&state->info_raw); lodepng_info_cleanup(&state->info_png); -} \ No newline at end of file +} diff --git a/src/loaders/png/tvgLodePng.h b/src/loaders/png/tvgLodePng.h index c9f0e56..0cdac7c 100644 --- a/src/loaders/png/tvgLodePng.h +++ b/src/loaders/png/tvgLodePng.h @@ -171,4 +171,4 @@ void lodepng_state_cleanup(LodePNGState* state); unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, LodePNGState* state, const unsigned char* in, size_t insize); unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, const unsigned char* in, size_t insize); -#endif //_TVG_LODEPNG_H_ \ No newline at end of file +#endif //_TVG_LODEPNG_H_ diff --git a/src/loaders/tvg/tvgTvgCommon.h b/src/loaders/tvg/tvgTvgCommon.h index 6218160..a0762d0 100644 --- a/src/loaders/tvg/tvgTvgCommon.h +++ b/src/loaders/tvg/tvgTvgCommon.h @@ -51,4 +51,4 @@ public: }; -#endif //_TVG_TVG_COMMON_H_ \ No newline at end of file +#endif //_TVG_TVG_COMMON_H_ diff --git a/test/capi/capiScene.cpp b/test/capi/capiScene.cpp index 92120c7..38235d4 100644 --- a/test/capi/capiScene.cpp +++ b/test/capi/capiScene.cpp @@ -1,115 +1,115 @@ -/* - * Copyright (c) 2021 - 2022 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 "../catch.hpp" - -TEST_CASE("Create a Scene", "[capiScene]") -{ - Tvg_Paint* scene = tvg_scene_new(); - REQUIRE(scene); - - REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); -} - -TEST_CASE("Paints Into a Scene", "[capiScene]") -{ - Tvg_Paint* scene = tvg_scene_new(); - REQUIRE(scene); - - //Pushing Paints - REQUIRE(tvg_scene_push(scene, tvg_shape_new()) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_scene_push(scene, tvg_picture_new()) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_scene_push(scene, tvg_scene_new()) == TVG_RESULT_SUCCESS); - - //Pushing Null Pointer - REQUIRE(tvg_scene_push(scene, NULL) == TVG_RESULT_INVALID_ARGUMENT); - REQUIRE(tvg_scene_push(NULL, NULL) == TVG_RESULT_INVALID_ARGUMENT); - - REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); -} - -TEST_CASE("Scene Reservation", "[capiScene]") -{ - Tvg_Paint* scene = tvg_scene_new(); - REQUIRE(scene); - - //Check Growth / Reduction - REQUIRE(tvg_scene_reserve(scene, 100) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_scene_reserve(scene, 1000) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_scene_reserve(scene, 100) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_scene_reserve(scene, 0) == TVG_RESULT_SUCCESS); - - //Invalid scene - REQUIRE(tvg_scene_reserve(NULL, 1) == TVG_RESULT_INVALID_ARGUMENT); - - REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); -} - -TEST_CASE("Clear the Scene", "[capiScene]") -{ - Tvg_Paint* scene = tvg_scene_new(); - REQUIRE(scene); - - REQUIRE(tvg_scene_push(scene, tvg_shape_new()) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_scene_clear(scene, true) == TVG_RESULT_SUCCESS); - - //Invalid scene - REQUIRE(tvg_scene_clear(NULL, false) == TVG_RESULT_INVALID_ARGUMENT); - - REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); -} - -TEST_CASE("Scene reusing paints", "[capiScene]") -{ - REQUIRE(tvg_engine_init(TVG_ENGINE_SW, 0) == TVG_RESULT_SUCCESS); - - Tvg_Canvas* canvas = tvg_swcanvas_create(); - REQUIRE(canvas); - - uint32_t* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 200 * 200); - REQUIRE(buffer); - - REQUIRE(tvg_swcanvas_set_target(canvas, buffer, 200, 200, 200, TVG_COLORSPACE_ARGB8888) == TVG_RESULT_SUCCESS); - - Tvg_Paint* scene = tvg_scene_new(); - REQUIRE(scene); - - Tvg_Paint* shape = tvg_shape_new(); - REQUIRE(shape); - - REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_canvas_push(canvas, scene) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_canvas_update(canvas) == TVG_RESULT_SUCCESS); - - //No deallocate shape. - REQUIRE(tvg_scene_clear(scene, false) == TVG_RESULT_SUCCESS); - - //Reuse shape. - REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); - - REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); - - REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); - - free(buffer); -} +/* + * Copyright (c) 2021 - 2022 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 "../catch.hpp" + +TEST_CASE("Create a Scene", "[capiScene]") +{ + Tvg_Paint* scene = tvg_scene_new(); + REQUIRE(scene); + + REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); +} + +TEST_CASE("Paints Into a Scene", "[capiScene]") +{ + Tvg_Paint* scene = tvg_scene_new(); + REQUIRE(scene); + + //Pushing Paints + REQUIRE(tvg_scene_push(scene, tvg_shape_new()) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_push(scene, tvg_picture_new()) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_push(scene, tvg_scene_new()) == TVG_RESULT_SUCCESS); + + //Pushing Null Pointer + REQUIRE(tvg_scene_push(scene, NULL) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_scene_push(NULL, NULL) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); +} + +TEST_CASE("Scene Reservation", "[capiScene]") +{ + Tvg_Paint* scene = tvg_scene_new(); + REQUIRE(scene); + + //Check Growth / Reduction + REQUIRE(tvg_scene_reserve(scene, 100) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_reserve(scene, 1000) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_reserve(scene, 100) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_reserve(scene, 0) == TVG_RESULT_SUCCESS); + + //Invalid scene + REQUIRE(tvg_scene_reserve(NULL, 1) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); +} + +TEST_CASE("Clear the Scene", "[capiScene]") +{ + Tvg_Paint* scene = tvg_scene_new(); + REQUIRE(scene); + + REQUIRE(tvg_scene_push(scene, tvg_shape_new()) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_clear(scene, true) == TVG_RESULT_SUCCESS); + + //Invalid scene + REQUIRE(tvg_scene_clear(NULL, false) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); +} + +TEST_CASE("Scene reusing paints", "[capiScene]") +{ + REQUIRE(tvg_engine_init(TVG_ENGINE_SW, 0) == TVG_RESULT_SUCCESS); + + Tvg_Canvas* canvas = tvg_swcanvas_create(); + REQUIRE(canvas); + + uint32_t* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 200 * 200); + REQUIRE(buffer); + + REQUIRE(tvg_swcanvas_set_target(canvas, buffer, 200, 200, 200, TVG_COLORSPACE_ARGB8888) == TVG_RESULT_SUCCESS); + + Tvg_Paint* scene = tvg_scene_new(); + REQUIRE(scene); + + Tvg_Paint* shape = tvg_shape_new(); + REQUIRE(shape); + + REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_push(canvas, scene) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_update(canvas) == TVG_RESULT_SUCCESS); + + //No deallocate shape. + REQUIRE(tvg_scene_clear(scene, false) == TVG_RESULT_SUCCESS); + + //Reuse shape. + REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); + + free(buffer); +} diff --git a/test/testInitializer.cpp b/test/testInitializer.cpp index 6d8bf96..826229c 100644 --- a/test/testInitializer.cpp +++ b/test/testInitializer.cpp @@ -51,4 +51,4 @@ TEST_CASE("Negative termination", "[tvgInitializer]") TEST_CASE("Invalid engine", "[tvgInitializer]") { REQUIRE(Initializer::init(CanvasEngine(0), 0) == Result::InvalidArguments); -} \ No newline at end of file +} diff --git a/test/testPaint.cpp b/test/testPaint.cpp index 39c1213..1ef05f1 100644 --- a/test/testPaint.cpp +++ b/test/testPaint.cpp @@ -213,4 +213,4 @@ TEST_CASE("Composition", "[tvgPaint]") REQUIRE(shape->composite(&pComp2) == CompositeMethod::InvAlphaMask); REQUIRE(pComp == pComp2); -} \ No newline at end of file +} diff --git a/test/testShape.cpp b/test/testShape.cpp index f5c8dd9..0e4bfc3 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -206,4 +206,4 @@ TEST_CASE("Shape Filling", "[tvgShape]") REQUIRE(shape->fillRule() == FillRule::Winding); REQUIRE(shape->fill(FillRule::EvenOdd) == Result::Success); REQUIRE(shape->fillRule() == FillRule::EvenOdd); -} \ No newline at end of file +} -- 2.7.4 From ee0a663a873ec1ca7bdd1fbbccf359ff10191bbc Mon Sep 17 00:00:00 2001 From: jykeon Date: Thu, 9 Mar 2023 14:56:00 +0900 Subject: [PATCH 02/16] Bump Up 0.8.2 Change-Id: I185d1dc28c6c5d43af3694bdd9b8b50dd3482cdb Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 5e88a02..577d65d 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.8.1 +Version: 0.8.2 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From c2ec32e04e87cd7ce331851be84a5fc28748e7fc Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Sat, 11 Jun 2022 12:18:48 +0200 Subject: [PATCH 03/16] fix OpenBSD compile issue Linux seems the only system AFAICS to have alloca.h. All the BSDs have the declaration in stdlib.h Change-Id: I82d18c5ca92bb788eb175a2ce9acf418ac19053c --- src/lib/sw_engine/tvgSwRaster.cpp | 6 +++--- src/loaders/svg/tvgXmlParser.cpp | 6 +++--- src/loaders/tvg/tvgTvgBinInterpreter.cpp | 6 +++--- src/savers/tvg/tvgTvgSaver.cpp | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 810df8d..14e26e4 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -22,10 +22,10 @@ #ifdef _WIN32 #include -#elif defined(__FreeBSD__) - #include -#else +#elif defined(__linux__) #include +#else + #include #endif #include "tvgMath.h" diff --git a/src/loaders/svg/tvgXmlParser.cpp b/src/loaders/svg/tvgXmlParser.cpp index a644306..231badd 100644 --- a/src/loaders/svg/tvgXmlParser.cpp +++ b/src/loaders/svg/tvgXmlParser.cpp @@ -26,10 +26,10 @@ #ifdef _WIN32 #include -#elif defined(__FreeBSD__) - #include -#else +#elif defined(__linux__) #include +#else + #include #endif #include "tvgXmlParser.h" diff --git a/src/loaders/tvg/tvgTvgBinInterpreter.cpp b/src/loaders/tvg/tvgTvgBinInterpreter.cpp index 66de860..01a39b6 100644 --- a/src/loaders/tvg/tvgTvgBinInterpreter.cpp +++ b/src/loaders/tvg/tvgTvgBinInterpreter.cpp @@ -23,10 +23,10 @@ #ifdef _WIN32 #include -#elif defined(__FreeBSD__) - #include -#else +#elif defined(__linux__) #include +#else + #include #endif #include "tvgTvgCommon.h" diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index fca313b..57a21dc 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -28,10 +28,10 @@ #ifdef _WIN32 #include -#elif defined(__FreeBSD__) - #include -#else +#elif defined(__linux__) #include +#else + #include #endif static FILE* _fopen(const char* filename, const char* mode) -- 2.7.4 From 693d5bcac25370f79119d9b1d5c91bfdaa20723c Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 4 Aug 2022 16:54:37 +0900 Subject: [PATCH 04/16] loaders raw: fix a compiler warnings on Windows. fix the invalid conversion from float to uint32_t. @Issue: https://github.com/Samsung/thorvg/issues/1229 Change-Id: Ibd48c94e23661704ebf6efadfd0b1d098fa87c6a --- src/loaders/raw/tvgRawLoader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp index 2da399d..889f130 100644 --- a/src/loaders/raw/tvgRawLoader.cpp +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -78,9 +78,9 @@ unique_ptr RawLoader::bitmap() auto surface = static_cast(malloc(sizeof(Surface))); surface->buffer = (uint32_t*)(content); - surface->stride = w; - surface->w = w; - surface->h = h; + surface->stride = (uint32_t)w; + surface->w = (uint32_t)w; + surface->h = (uint32_t)h; surface->cs = SwCanvas::ARGB8888; return unique_ptr(surface); -- 2.7.4 From b2049b09159f582672e4ba3e7e7a91dfdbf5265a Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Wed, 17 Aug 2022 12:17:21 +0200 Subject: [PATCH 05/16] Windows: use _fullpath() instead of fullpath(). Fix compilation error Change-Id: Ic55f5da51f834e986d5005e835eb437bc0d3f318 --- src/bin/svg2png/svg2png.cpp | 2 +- src/bin/svg2tvg/svg2tvg.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/svg2png/svg2png.cpp b/src/bin/svg2png/svg2png.cpp index 849ed47..0699545 100644 --- a/src/bin/svg2png/svg2png.cpp +++ b/src/bin/svg2png/svg2png.cpp @@ -279,7 +279,7 @@ private: { //real path #ifdef _WIN32 - path = fullpath(full, path, PATH_MAX); + path = _fullpath(full, path, PATH_MAX); #else path = realpath(path, full); #endif diff --git a/src/bin/svg2tvg/svg2tvg.cpp b/src/bin/svg2tvg/svg2tvg.cpp index 4f313a5..c2788f3 100644 --- a/src/bin/svg2tvg/svg2tvg.cpp +++ b/src/bin/svg2tvg/svg2tvg.cpp @@ -70,7 +70,7 @@ char* getpath(const char* input) { static char buf[PATH_MAX]; #ifdef _WIN32 - return fullpath(buf, input, PATH_MAX); + return _fullpath(buf, input, PATH_MAX); #else return realpath(input, buf); #endif -- 2.7.4 From 79116e61214eab3e163921e1979308ce55d816a3 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Fri, 19 Aug 2022 14:09:50 +0900 Subject: [PATCH 06/16] sw_engine: Fix uninitialized variable warning message [35/42] Compiling C++ object src/libthorvg-0.dll.p/lib_sw_engine_tvgSwRaster.cpp.obj In file included from ../src/lib/sw_engine/tvgSwRasterTexmap.h:96, from ../src/lib/sw_engine/tvgSwRaster.cpp:83: ../src/lib/sw_engine/tvgSwRasterTexmapInternal.h: In function 'void _rasterPolygonImageSegment(SwSurface*, const SwImage*, const SwBBox*, int, int, uint32_t (*)(uint32_t), AASpans*)': ../src/lib/sw_engine/tvgSwRasterTexmapInternal.h:76:9: warning: 'maxx' may be used uninitialized [-Wmaybe-uninitialized] 76 | if (x2 > maxx) x2 = maxx; | ^~ ../src/lib/sw_engine/tvgSwRasterTexmapInternal.h:33:19: note: 'maxx' was declared here 33 | int32_t minx, maxx; | ^~~~ ../src/lib/sw_engine/tvgSwRasterTexmapInternal.h:75:9: warning: 'minx' may be used uninitialized [-Wmaybe-uninitialized] 75 | if (x1 < minx) x1 = minx; | ^~ ../src/lib/sw_engine/tvgSwRasterTexmapInternal.h:33:13: note: 'minx' was declared here 33 | int32_t minx, maxx; | ^~~~ Change-Id: If2f71a4de21d013dc2519d15802889dc2d4d1174 --- src/lib/sw_engine/tvgSwRasterTexmapInternal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h index f31ea1e..5053629 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h +++ b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h @@ -30,7 +30,7 @@ int32_t dw = surface->stride; int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; int32_t vv = 0, uu = 0; - int32_t minx, maxx; + int32_t minx = INT32_MAX, maxx = INT32_MIN; float dx, u, v, iptr; uint32_t* buf; SwSpan* span = nullptr; //used only when rle based. -- 2.7.4 From 014fc591073bd2aa00f27dea58181b7439859c6d Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Fri, 19 Aug 2022 05:49:00 +0200 Subject: [PATCH 07/16] Windows: set TVG_EXPORT to dllexport also for mingw In addition, remove TVG_EXPORT from enum class. They are types not symbols Change-Id: Ia435f86f8bba34093418d7f5699fdc2934f4a21d --- inc/thorvg.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index b08356d..7e8988a 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -18,7 +18,7 @@ #include #ifdef TVG_BUILD - #if defined(_MSC_VER) && !defined(__clang__) + #if defined(_WIN32) && !defined(__clang__) #define TVG_EXPORT __declspec(dllexport) #define TVG_DEPRECATED __declspec(deprecated) #else @@ -74,7 +74,7 @@ class Accessor; /** * @brief Enumeration specifying the result from the APIs. */ -enum class TVG_EXPORT Result +enum class Result { Success = 0, ///< The value returned in case of a correct request execution. InvalidArguments, ///< The value returned in the event of a problem with the arguments given to the API - e.g. empty paths or null pointers. @@ -91,7 +91,7 @@ enum class TVG_EXPORT Result * Not to be confused with the path commands from the svg path element (like M, L, Q, H and many others). * TVG interprets all of them and translates to the ones from the PathCommand values. */ -enum class TVG_EXPORT PathCommand +enum class PathCommand { Close = 0, ///< Ends the current sub-path and connects it with its initial point. This command doesn't expect any points. MoveTo, ///< Sets a new initial point of the sub-path and a new current point. This command expects 1 point: the starting position. @@ -102,7 +102,7 @@ enum class TVG_EXPORT PathCommand /** * @brief Enumeration determining the ending type of a stroke in the open sub-paths. */ -enum class TVG_EXPORT StrokeCap +enum class StrokeCap { Square = 0, ///< The stroke is extended in both end-points of a sub-path by a rectangle, with the width equal to the stroke width and the length equal to the half of the stroke width. For zero length sub-paths the square is rendered with the size of the stroke width. Round, ///< The stroke is extended in both end-points of a sub-path by a half circle, with a radius equal to the half of a stroke width. For zero length sub-paths a full circle is rendered. @@ -112,7 +112,7 @@ enum class TVG_EXPORT StrokeCap /** * @brief Enumeration determining the style used at the corners of joined stroked path segments. */ -enum class TVG_EXPORT StrokeJoin +enum class StrokeJoin { Bevel = 0, ///< The outer corner of the joined path segments is bevelled at the join point. The triangular region of the corner is enclosed by a straight line between the outer corners of each stroke. Round, ///< The outer corner of the joined path segments is rounded. The circular region is centered at the join point. @@ -122,7 +122,7 @@ enum class TVG_EXPORT StrokeJoin /** * @brief Enumeration specifying how to fill the area outside the gradient bounds. */ -enum class TVG_EXPORT FillSpread +enum class FillSpread { Pad = 0, ///< The remaining area is filled with the closest stop color. Reflect, ///< The gradient pattern is reflected outside the gradient area until the expected region is filled. @@ -132,7 +132,7 @@ enum class TVG_EXPORT FillSpread /** * @brief Enumeration specifying the algorithm used to establish which parts of the shape are treated as the inside of the shape. */ -enum class TVG_EXPORT FillRule +enum class FillRule { Winding = 0, ///< A line from the point to a location outside the shape is drawn. The intersections of the line with the path segment of the shape are counted. Starting from zero, if the path segment of the shape crosses the line clockwise, one is added, otherwise one is subtracted. If the resulting sum is non zero, the point is inside the shape. EvenOdd ///< A line from the point to a location outside the shape is drawn and its intersections with the path segments of the shape are counted. If the number of intersections is an odd number, the point is inside the shape. @@ -141,7 +141,7 @@ enum class TVG_EXPORT FillRule /** * @brief Enumeration indicating the method used in the composition of two objects - the target and the source. */ -enum class TVG_EXPORT CompositeMethod +enum class CompositeMethod { None = 0, ///< No composition is applied. ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered. @@ -153,7 +153,7 @@ enum class TVG_EXPORT CompositeMethod /** * @brief Enumeration specifying the engine type used for the graphics backend. For multiple backends bitwise operation is allowed. */ -enum class TVG_EXPORT CanvasEngine +enum class CanvasEngine { Sw = (1 << 1), ///< CPU rasterizer. Gl = (1 << 2) ///< OpenGL rasterizer. -- 2.7.4 From 8b64b8c8e284dde23e0e431e70151108a316c9f9 Mon Sep 17 00:00:00 2001 From: projectitis Date: Fri, 19 Aug 2022 19:56:43 +1200 Subject: [PATCH 08/16] common picture: support image mesh feature Tvg Picture newly provides mesh() api to support texture mapping. These apis allows to have a coarse triangle list which have polygon coordinates and texture uvs those are used for traditional polygon texture mapping. Note that these apis are beta version. @API Additions: Result mesh(const Polygon* triangles, const uint32_t triangleCount) noexcept uint32_t mesh(const Polygon** triangles) const noexcept @Examples: //Mapping with two polygons Polygon polygon[2]; //First polygon polygon[0].vertex[0].pt = {0, 0}; polygon[0].vertex[1].pt = {100, 0}; polygon[0].vertex[2].pt = {0, 100}; polygon[0].vertex[0].uv = {0, 0}; polygon[0].vertex[1].uv = {1, 0}; polygon[0].vertex[2].uv = {0, 1}; //Second polygon polygon[1].vertex[0].pt = {100, 0}; polygon[1].vertex[1].pt = {100, 100}; polygon[1].vertex[2].pt = {0, 100}; polygon[1].vertex[0].uv = {1, 0}; polygon[1].vertex[1].uv = {1, 1}; polygon[1].vertex[2].uv = {0, 1}; //Apply polygons to the picture picture->mesh(polygon, 2); @Issues: https://github.com/Samsung/thorvg/issues/1218 Change-Id: I8400a654b392d1d01e01727e0bc0d829cd155080 --- inc/thorvg.h | 63 ++++++++++++++++++++++++ src/lib/gl_engine/tvgGlRenderer.cpp | 6 +++ src/lib/gl_engine/tvgGlRenderer.h | 1 + src/lib/sw_engine/tvgSwCommon.h | 3 +- src/lib/sw_engine/tvgSwImage.cpp | 53 +++++++++++++++++--- src/lib/sw_engine/tvgSwRaster.cpp | 28 +++++++++++ src/lib/sw_engine/tvgSwRasterTexmap.h | 93 ++++++++++++++++++++++++++--------- src/lib/sw_engine/tvgSwRenderer.cpp | 36 +++++++++----- src/lib/sw_engine/tvgSwRenderer.h | 3 +- src/lib/tvgPicture.cpp | 14 ++++++ src/lib/tvgPictureImpl.h | 69 +++++++++++++++++++++++--- src/lib/tvgRender.h | 3 +- 12 files changed, 321 insertions(+), 51 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 7e8988a..efba938 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -183,6 +183,33 @@ struct Matrix float e31, e32, e33; }; +/** + * @brief A data structure representing a texture mesh vertex + * + * @param pt The vertex coordinate + * @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0) + * + * @BETA_API + */ +struct Vertex +{ + Point pt; + Point uv; +}; + + +/** + * @brief A data structure representing a triange in a texture mesh + * + * @param vertex The three vertices that make up the polygon + * + * @BETA_API + */ +struct Polygon +{ + Vertex vertex[3]; +}; + /** * @class Paint @@ -1178,6 +1205,42 @@ public: Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept; /** + * @brief Sets or removes the triangle mesh to deform the image. + * + * If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the + * image data will be used as the texture. + * + * If triangles is null, or triangleCount is 0, the mesh will be removed. + * + * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support + * mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh. + * + * @param[in] triangles An array of Polygon objects (triangles) that make up the mesh, or null to remove the mesh + * @param[in] triangleCount The number of Polygon objects (triangles) provided, or 0 to remove the mesh + * + * @retval Result::Success When succeed. + * @retval Result::Unknown If fails + * + * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect. + * + * @BETA_API + */ + Result mesh(const Polygon* triangles, const uint32_t triangleCount) noexcept; + + /** + * @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh. + * + * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh + * + * @return uint32_t The number of polygons in the array + * + * @note Modifying the triangles returned by this method will modify them directly within the mesh + * + * @BETA_API + */ + uint32_t mesh(const Polygon** triangles) const noexcept; + + /** * @brief Gets the position and the size of the loaded SVG picture. * * @warning Please do not use it, this API is not official one. It could be modified in the next version. diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 4384d52..8fbcd39 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -129,6 +129,12 @@ bool GlRenderer::renderImage(TVG_UNUSED void* data) } +bool GlRenderer::renderImageMesh(TVG_UNUSED void* data) +{ + return false; +} + + bool GlRenderer::renderShape(RenderData data) { auto sdata = static_cast(data); diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index e0e8cce..7767a62 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -35,6 +35,7 @@ public: bool preRender() override; bool renderShape(RenderData data) override; bool renderImage(RenderData data) override; + bool renderImageMesh(RenderData data) override; bool postRender() override; bool dispose(RenderData data) override;; RenderRegion region(RenderData data) override; diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 47b0cb8..888f4fd 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -321,7 +321,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid); void strokeFree(SwStroke* stroke); -bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); +bool imagePrepare(SwImage* image, Polygon* triangles, uint32_t triangleCount, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias); void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid); void imageReset(SwImage* image); @@ -351,6 +351,7 @@ bool rasterCompositor(SwSurface* surface); bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity); +bool rasterImageMesh(SwSurface* surface, SwImage* image, const Polygon* triangles, const uint32_t triangleCount, const Matrix* transform, const SwBBox& bbox, uint32_t opacity); bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id); bool rasterClear(SwSurface* surface); diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp index c02e28b..a1b8960 100644 --- a/src/lib/sw_engine/tvgSwImage.cpp +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -33,7 +33,7 @@ static inline bool _onlyShifted(const Matrix* m) } -static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, unsigned tid) +static bool _genOutline(SwImage* image, Polygon* triangles, uint32_t triangleCount, const Matrix* transform, SwMpool* mpool, unsigned tid) { image->outline = mpoolReqOutline(mpool, tid); auto outline = image->outline; @@ -51,10 +51,49 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, outline->closed[0] = true; } - auto w = static_cast(image->w); - auto h = static_cast(image->h); - - Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}}; + Point to[4]; + if (triangleCount > 0) { + // TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple + // places. We should be able to re-use one we have already done? Also see: + // tvgPictureImpl.h --> bounds + // tvgSwRasterTexmap.h --> _rasterTexmapPolygonMesh + // + // TODO: Should we calculate the exact path(s) of the triangle mesh instead? + // i.e. copy tvgSwShape.capp -> _genOutline? + // + // TODO: Cntrs? + Point min = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; + Point max = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; + + for (uint32_t i = 0; i < triangleCount; ++i) { + if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x; + else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x; + if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y; + else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y; + + if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x; + else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x; + if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y; + else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y; + + if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x; + else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x; + if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y; + else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y; + } + + to[0] = {min.x, min.y}; + to[1] = {max.x, min.y}; + to[2] = {max.x, max.y}; + to[3] = {min.x, max.y}; + } else { + auto w = static_cast(image->w); + auto h = static_cast(image->h); + to[0] = {0, 0}; + to[1] = {w, 0}; + to[2] = {w, h}; + to[3] = {0, h}; + } for (int i = 0; i < 4; i++) { outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform); outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT; @@ -78,7 +117,7 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, /* External Class Implementation */ /************************************************************************/ -bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) +bool imagePrepare(SwImage* image, Polygon* triangles, uint32_t triangleCount, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) { image->direct = _onlyShifted(transform); @@ -96,7 +135,7 @@ bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipReg else image->scaled = false; } - if (!_genOutline(image, transform, mpool, tid)) return false; + if (!_genOutline(image, triangles, triangleCount, transform, mpool, tid)) return false; return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion, image->direct); } diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 14e26e4..7512efc 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -687,6 +687,22 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons return false; } +static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image, const Polygon* triangles, const uint32_t count, const Matrix* transform, const SwBBox* region, uint32_t opacity) +{ + if (_compositing(surface)) { + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _rasterTexmapPolygonMesh(surface, image, triangles, count, transform, region, opacity, _alpha); + } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _rasterTexmapPolygonMesh(surface, image, triangles, count, transform, region, opacity, _ialpha); + } else if (surface->compositor->method == CompositeMethod::LumaMask) { + return _rasterTexmapPolygonMesh(surface, image, triangles, count, transform, region, opacity, surface->blender.lumaValue); + } + } else { + return _rasterTexmapPolygonMesh(surface, image, triangles, count, transform, region, opacity, nullptr); + } + return false; +} + /************************************************************************/ /*Scaled RGBA Image */ @@ -1556,3 +1572,15 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co //TODO: case: _rasterAlphaImage() return _rasterRGBAImage(surface, image, transform, bbox, opacity); } + +bool rasterImageMesh(SwSurface* surface, SwImage* image, const Polygon* triangles, const uint32_t count, const Matrix* transform, const SwBBox& bbox, uint32_t opacity) +{ + //Verify Boundary + if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast(surface->w) || bbox.min.y >= static_cast(surface->h)) return false; + + //TOOD: switch (image->format) + //TODO: case: _rasterRGBImageMesh() + //TODO: case: _rasterGrayscaleImageMesh() + //TODO: case: _rasterAlphaImageMesh() + return _transformedRGBAImageMesh(surface, image, triangles, count, transform, &bbox, opacity); +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRasterTexmap.h b/src/lib/sw_engine/tvgSwRasterTexmap.h index abb57d7..32a772e 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmap.h +++ b/src/lib/sw_engine/tvgSwRasterTexmap.h @@ -20,17 +20,6 @@ * SOFTWARE. */ -struct Vertex -{ - Point pt; - Point uv; -}; - -struct Polygon -{ - Vertex vertex[3]; -}; - struct AALine { int32_t x[2]; @@ -287,18 +276,10 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const } -static AASpans* _AASpans(const Vertex* vertices, const SwImage* image, const SwBBox* region) +static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwBBox* region) { - //Initialize Y range - float ys = FLT_MAX, ye = -1.0f; - - for (int i = 0; i < 4; i++) { - if (vertices[i].pt.y < ys) ys = vertices[i].pt.y; - if (vertices[i].pt.y > ye) ye = vertices[i].pt.y; - } - - auto yStart = static_cast(ys); - auto yEnd = static_cast(ye); + auto yStart = static_cast(ymin); + auto yEnd = static_cast(ymax); if (!_arrange(image, region, yStart, yEnd)) return nullptr; @@ -577,9 +558,15 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}}; vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}}; - for (int i = 0; i < 4; i++) mathMultiply(&vertices[i].pt, transform); + float ys = FLT_MAX, ye = -1.0f; + for (int i = 0; i < 4; i++) { + mathMultiply(&vertices[i].pt, transform); + + if (vertices[i].pt.y < ys) ys = vertices[i].pt.y; + if (vertices[i].pt.y > ye) ye = vertices[i].pt.y; + } - auto aaSpans = _AASpans(vertices, image, region); + auto aaSpans = _AASpans(ys, ye, image, region); if (!aaSpans) return true; Polygon polygon; @@ -600,3 +587,61 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const return _apply(surface, aaSpans); } + + +/* + Provide any number of triangles to draw a mesh using the supplied image. + Indexes are not used, so each triangle (Polygon) vertex has to be defined, even if they copy the previous one. + Example: + + 0 -- 1 0 -- 1 0 + | / | --> | / / | + | / | | / / | + 2 -- 3 2 1 -- 2 + + Should provide two Polygons, one for each triangle. + // TODO: region? +*/ +static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const Polygon* triangles, const uint32_t triangleCount, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) +{ + //Exceptions: No dedicated drawing area? + if (!region && image->rle->size == 0) return false; + + // Step polygons once to transform + auto transformedTris = (Polygon*)malloc(sizeof(Polygon) * triangleCount); + float ys = FLT_MAX, ye = -1.0f; + for (uint32_t i = 0; i < triangleCount; i++) { + transformedTris[i] = triangles[i]; + mathMultiply(&transformedTris[i].vertex[0].pt, transform); + mathMultiply(&transformedTris[i].vertex[1].pt, transform); + mathMultiply(&transformedTris[i].vertex[2].pt, transform); + + if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y; + else if (transformedTris[i].vertex[0].pt.y > ye) ye = transformedTris[i].vertex[0].pt.y; + if (transformedTris[i].vertex[1].pt.y < ys) ys = transformedTris[i].vertex[1].pt.y; + else if (transformedTris[i].vertex[1].pt.y > ye) ye = transformedTris[i].vertex[1].pt.y; + if (transformedTris[i].vertex[2].pt.y < ys) ys = transformedTris[i].vertex[2].pt.y; + else if (transformedTris[i].vertex[2].pt.y > ye) ye = transformedTris[i].vertex[2].pt.y; + + // Convert normalized UV coordinates to image coordinates + transformedTris[i].vertex[0].uv.x *= (float)image->w; + transformedTris[i].vertex[0].uv.y *= (float)image->h; + transformedTris[i].vertex[1].uv.x *= (float)image->w; + transformedTris[i].vertex[1].uv.y *= (float)image->h; + transformedTris[i].vertex[2].uv.x *= (float)image->w; + transformedTris[i].vertex[2].uv.y *= (float)image->h; + } + + // Get AA spans and step polygons again to draw + auto aaSpans = _AASpans(ys, ye, image, region); + if (aaSpans) { + for (uint32_t i = 0; i < triangleCount; i++) { + _rasterPolygonImage(surface, image, region, opacity, transformedTris[i], blendMethod, aaSpans); + } + // Apply to surface (note: frees the AA spans) + _apply(surface, aaSpans); + } + free(transformedTris); + + return true; +} diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index c3872f3..692d592 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -181,6 +181,8 @@ struct SwShapeTask : SwTask struct SwImageTask : SwTask { SwImage image; + Polygon* triangles; + uint32_t triangleCount; void run(unsigned tid) override { @@ -191,9 +193,10 @@ struct SwImageTask : SwTask imageReset(&image); if (!image.data || image.w == 0 || image.h == 0) goto end; - if (!imagePrepare(&image, transform, clipRegion, bbox, mpool, tid)) goto end; + if (!imagePrepare(&image, triangles, triangleCount, transform, clipRegion, bbox, mpool, tid)) goto end; - if (clips.count > 0) { + // TODO: How do we clip the triangle mesh? Only clip non-meshed images for now + if (triangleCount == 0 && clips.count > 0) { if (!imageGenRle(&image, bbox, false)) goto end; if (image.rle) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { @@ -356,6 +359,17 @@ bool SwRenderer::renderImage(RenderData data) } +bool SwRenderer::renderImageMesh(RenderData data) +{ + auto task = static_cast(data); + task->done(); + + if (task->opacity == 0) return true; + + return rasterImageMesh(surface, &task->image, task->triangles, task->triangleCount, task->transform, task->bbox, task->opacity); +} + + bool SwRenderer::renderShape(RenderData data) { auto task = static_cast(data); @@ -610,18 +624,18 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, } -RenderData SwRenderer::prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) +RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t triangleCount, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) { //prepare task auto task = static_cast(data); - if (!task) { - task = new SwImageTask; - if (flags & RenderUpdateFlag::Image) { - task->image.data = image->buffer; - task->image.w = image->w; - task->image.h = image->h; - task->image.stride = image->stride; - } + if (!task) task = new SwImageTask; + if (flags & RenderUpdateFlag::Image) { + task->image.data = image->buffer; + task->image.w = image->w; + task->image.h = image->h; + task->image.stride = image->stride; + task->triangles = triangles; + task->triangleCount = triangleCount; } return prepareCommon(task, transform, opacity, clips, flags); } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 574d9d4..9bc1c83 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -36,10 +36,11 @@ class SwRenderer : public RenderMethod { public: RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; - RenderData prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; + RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; bool preRender() override; bool renderShape(RenderData data) override; bool renderImage(RenderData data) override; + bool renderImageMesh(RenderData data) override; bool postRender() override; bool dispose(RenderData data) override; RenderRegion region(RenderData data) override; diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 1e04e25..4449d2d 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -119,3 +119,17 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept if (pImpl->surface) return pImpl->surface->buffer; else return nullptr; } + + +Result Picture::mesh(const Polygon* triangles, const uint32_t triangleCount) noexcept +{ + if (pImpl->mesh(triangles, triangleCount)) return Result::Success; + return Result::Unknown; +} + + +uint32_t Picture::mesh(const Polygon** triangles) const noexcept +{ + if (triangles) *triangles = pImpl->triangles; + return pImpl->triangleCount; +} diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index b2e097d..d8aaec0 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -63,6 +63,8 @@ struct Picture::Impl Paint* paint = nullptr; //vector picture uses Surface* surface = nullptr; //bitmap picture uses + Polygon* triangles = nullptr; //mesh data + uint32_t triangleCount = 0; //mesh triangle count void* rdata = nullptr; //engine data float w = 0, h = 0; bool resizing = false; @@ -70,6 +72,7 @@ struct Picture::Impl ~Impl() { if (paint) delete(paint); + free(triangles); free(surface); } @@ -128,7 +131,7 @@ struct Picture::Impl if (surface) { auto transform = resizeTransform(pTransform); - rdata = renderer.prepare(surface, rdata, &transform, opacity, clips, static_cast(pFlag | flag)); + rdata = renderer.prepare(surface, triangles, triangleCount, rdata, &transform, opacity, clips, static_cast(pFlag | flag)); } else if (paint) { if (resizing) { loader->resize(paint, w, h); @@ -141,7 +144,10 @@ struct Picture::Impl bool render(RenderMethod &renderer) { - if (surface) return renderer.renderImage(rdata); + if (surface) { + if (triangles) return renderer.renderImageMesh(rdata); + else return renderer.renderImage(rdata); + } else if (paint) return paint->pImpl->render(renderer); return false; } @@ -166,10 +172,41 @@ struct Picture::Impl bool bounds(float* x, float* y, float* w, float* h) { - if (x) *x = 0; - if (y) *y = 0; - if (w) *w = this->w; - if (h) *h = this->h; + if (triangleCount > 0) { + + Point min = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; + Point max = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; + + for (uint32_t i = 0; i < triangleCount; ++i) { + if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x; + else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x; + if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y; + else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y; + + if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x; + else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x; + if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y; + else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y; + + if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x; + else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x; + if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y; + else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y; + } + + if (x) *x = min.x; + if (y) *y = min.y; + if (w) *w = max.x - min.x; + if (h) *h = max.y - min.y; + + } else { + + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = this->w; + if (h) *h = this->h; + + } return true; } @@ -220,6 +257,20 @@ struct Picture::Impl return Result::Success; } + bool mesh(const Polygon* triangles, const uint32_t triangleCount) + { + if (triangles && triangleCount > 0) { + this->triangleCount = triangleCount; + this->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCount); + for (uint32_t i = 0; i < triangleCount; i++) this->triangles[i] = triangles[i]; + } else { + free(this->triangles); + this->triangles = nullptr; + this->triangleCount = 0; + } + return true; + } + Paint* duplicate() { reload(); @@ -238,6 +289,12 @@ struct Picture::Impl dup->h = h; dup->resizing = resizing; + if (triangleCount > 0) { + dup->triangleCount = triangleCount; + dup->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCount); + for (uint32_t i = 0; i < triangleCount; i++) dup->triangles[i] = triangles[i]; + } + return ret.release(); } diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index ed66f39..54ca524 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -90,10 +90,11 @@ class RenderMethod public: virtual ~RenderMethod() {} virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; - virtual RenderData prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; + virtual RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; virtual bool preRender() = 0; virtual bool renderShape(RenderData data) = 0; virtual bool renderImage(RenderData data) = 0; + virtual bool renderImageMesh(RenderData data) = 0; virtual bool postRender() = 0; virtual bool dispose(RenderData data) = 0; virtual RenderRegion region(RenderData data) = 0; -- 2.7.4 From 6a0aaf187158b5623262aab45956fcb0d74d510e Mon Sep 17 00:00:00 2001 From: projectitis Date: Sat, 20 Aug 2022 12:32:31 +1200 Subject: [PATCH 09/16] Fix compiler warnings on windows Change-Id: I86897d1fea2d1b69813bf08b173a11685408cd2a --- src/loaders/jpg/tvgJpgLoader.cpp | 6 +++--- src/loaders/jpg/tvgJpgd.cpp | 2 +- src/loaders/png/tvgPngLoader.cpp | 6 +++--- test/testScene.cpp | 8 ++++---- test/testSwCanvas.cpp | 2 +- test/testSwCanvasBase.cpp | 22 +++++++++++----------- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index ffdef30..d11dfc1 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -118,9 +118,9 @@ unique_ptr JpgLoader::bitmap() auto surface = static_cast(malloc(sizeof(Surface))); surface->buffer = (uint32_t*)(image); - surface->stride = w; - surface->w = w; - surface->h = h; + surface->stride = static_cast(w); + surface->w = static_cast(w); + surface->h = static_cast(h); surface->cs = SwCanvas::ARGB8888; return unique_ptr(surface); diff --git a/src/loaders/jpg/tvgJpgd.cpp b/src/loaders/jpg/tvgJpgd.cpp index dacd45e..56b40ac 100644 --- a/src/loaders/jpg/tvgJpgd.cpp +++ b/src/loaders/jpg/tvgJpgd.cpp @@ -808,7 +808,7 @@ inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits) // Tables and macro used to fully decode the DPCM differences. static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; -static const unsigned int s_extend_offset[16] = { 0, ((-1u)<<1) + 1, ((-1u)<<2) + 1, ((-1u)<<3) + 1, ((-1u)<<4) + 1, ((-1u)<<5) + 1, ((-1u)<<6) + 1, ((-1u)<<7) + 1, ((-1u)<<8) + 1, ((-1u)<<9) + 1, ((-1u)<<10) + 1, ((-1u)<<11) + 1, ((-1u)<<12) + 1, ((-1u)<<13) + 1, ((-1u)<<14) + 1, ((-1u)<<15) + 1 }; +static const unsigned int s_extend_offset[16] = { 0, ((~0u)<<1) + 1, ((~0u)<<2) + 1, ((~0u)<<3) + 1, ((~0u)<<4) + 1, ((~0u)<<5) + 1, ((~0u)<<6) + 1, ((~0u)<<7) + 1, ((~0u)<<8) + 1, ((~0u)<<9) + 1, ((~0u)<<10) + 1, ((~0u)<<11) + 1, ((~0u)<<12) + 1, ((~0u)<<13) + 1, ((~0u)<<14) + 1, ((~0u)<<15) + 1 }; // The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this) #define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x)) diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index 3e29317..8f2362c 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -170,9 +170,9 @@ unique_ptr PngLoader::bitmap() auto surface = static_cast(malloc(sizeof(Surface))); surface->buffer = (uint32_t*)(image); - surface->stride = w; - surface->w = w; - surface->h = h; + surface->stride = static_cast(w); + surface->w = static_cast(w); + surface->h = static_cast(h); surface->cs = SwCanvas::ARGB8888; return unique_ptr(surface); diff --git a/test/testScene.cpp b/test/testScene.cpp index ae4be5f..a80d37e 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -41,9 +41,9 @@ TEST_CASE("Pushing Paints Into Scene", "[tvgScene]") REQUIRE(scene); //Pushing Paints - REQUIRE(scene->push(move(Shape::gen())) == Result::Success); - REQUIRE(scene->push(move(Picture::gen())) == Result::Success); - REQUIRE(scene->push(move(Scene::gen())) == Result::Success); + REQUIRE(scene->push(Shape::gen()) == Result::Success); + REQUIRE(scene->push(Picture::gen()) == Result::Success); + REQUIRE(scene->push(Scene::gen()) == Result::Success); //Pushing Null Pointer REQUIRE(scene->push(nullptr) == Result::MemoryCorruption); @@ -70,7 +70,7 @@ TEST_CASE("Scene Clear", "[tvgScene]") auto scene = Scene::gen(); REQUIRE(scene); - REQUIRE(scene->push(move(Shape::gen())) == Result::Success); + REQUIRE(scene->push(Shape::gen()) == Result::Success); REQUIRE(scene->clear() == Result::Success); } diff --git a/test/testSwCanvas.cpp b/test/testSwCanvas.cpp index ffaa15f..111d34c 100644 --- a/test/testSwCanvas.cpp +++ b/test/testSwCanvas.cpp @@ -88,7 +88,7 @@ TEST_CASE("Memory Pool", "[tvgSwCanvas]") REQUIRE(canvas2->mempool(SwCanvas::MempoolPolicy::Shareable) == Result::Success); REQUIRE(canvas2->mempool(SwCanvas::MempoolPolicy::Shareable) == Result::Success); - REQUIRE(canvas2->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas2->push(Shape::gen()) == Result::Success); REQUIRE(canvas2->mempool(SwCanvas::MempoolPolicy::Individual) == Result::InsufficientCondition); REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); diff --git a/test/testSwCanvasBase.cpp b/test/testSwCanvasBase.cpp index 7b0bc3a..32e5f51 100644 --- a/test/testSwCanvasBase.cpp +++ b/test/testSwCanvasBase.cpp @@ -53,19 +53,19 @@ TEST_CASE("Pushing Paints", "[tvgSwCanvasBase]") REQUIRE(canvas->target(buffer, 100, 100, 100, SwCanvas::Colorspace::ARGB8888) == Result::Success); //Try all types of paints. - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); - REQUIRE(canvas->push(move(Picture::gen())) == Result::Success); - REQUIRE(canvas->push(move(Scene::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); + REQUIRE(canvas->push(Picture::gen()) == Result::Success); + REQUIRE(canvas->push(Scene::gen()) == Result::Success); //Cases by contexts. REQUIRE(canvas->update() == Result::Success); - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); REQUIRE(canvas->clear() == Result::Success); - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); //Negative case 1 REQUIRE(canvas->push(nullptr) == Result::MemoryCorruption); @@ -75,9 +75,9 @@ TEST_CASE("Pushing Paints", "[tvgSwCanvasBase]") REQUIRE(canvas->push(move(shape6)) == Result::MemoryCorruption); //Negative case 3 - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); REQUIRE(canvas->draw() == Result::Success); - REQUIRE(canvas->push(move(Shape::gen())) == Result::InsufficientCondition); + REQUIRE(canvas->push(Shape::gen()) == Result::InsufficientCondition); REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); } @@ -104,7 +104,7 @@ TEST_CASE("Clear", "[tvgSwCanvasBase]") //Try 1: Push -> Clear for (int i = 0; i < 5; ++i) { - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); auto shape2 = Shape::gen(); REQUIRE(shape2); @@ -123,7 +123,7 @@ TEST_CASE("Clear", "[tvgSwCanvasBase]") //Try 2: Push -> Update -> Clear for (int i = 0; i < 5; ++i) { - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); auto shape2 = Shape::gen(); REQUIRE(shape2); @@ -157,7 +157,7 @@ TEST_CASE("Update", "[tvgSwCanvasBase]") REQUIRE(canvas->update() == Result::InsufficientCondition); - REQUIRE(canvas->push(move(Shape::gen())) == Result::Success); + REQUIRE(canvas->push(Shape::gen()) == Result::Success); //No pushed shape auto shape = Shape::gen(); -- 2.7.4 From 7dd2b281abe03d3437feab6fa77707a4e4e9aa51 Mon Sep 17 00:00:00 2001 From: jykeon Date: Fri, 10 Mar 2023 14:39:24 +0900 Subject: [PATCH 10/16] Bump up 0.8.3 Change-Id: I18e1dfa786e799e8d128046ab60a66569b4e689c Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 577d65d..6550177 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.8.2 +Version: 0.8.3 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From e946d4dbddcf954d35123e4eb4330932992f6592 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 20 Aug 2022 13:25:27 +0900 Subject: [PATCH 11/16] Update CONTRIBUTING.md Change-Id: Ifd9ca62af21cdf6094a00feb1bdc1b1e9dc4f53c --- CONTRIBUTING.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cded7f0..8205ff5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,14 +4,11 @@ We always appreciate your contribution. ThorVG doesn't expect perfect patch cont Hermet Park (hermet) is the lead maintainer. Also there are designated maintainers you can request your pull-request for separate modules. common: Junsu Choi (JSUYA)
-sw_engine: Junsu Choi (JSUYA), Mira Grudzinska (mgrudzinska), Michal Szczecinski (mihashco)
-svg_loader: Junsu Choi (JSUYA), Mira Grudzinska (mgrudzinska), Michal Maciola (mmaciola)
-jpg_loader: Michal Maciola (mmaciola)
-tvg_loader: Michal Maciola (mmaciola)
+sw_engine: Junsu Choi (JSUYA), Mira Grudzinska (mgrudzinska), Peter Vullings (projectitis)
+svg_loader: Junsu Choi (JSUYA), Mira Grudzinska (mgrudzinska)
tvg_saver: Mira Grudzinska (mgrudzinska)
-wasm: Shinwoo Kim (kimcinoo), Michal Maciola (mmaciola)
-svg2png: Junsu Choi (JSUYA), Michal Maciola (mmaciola)
-capi: Michal Szczecinski (mihashco), Mira Grudzinska (mgrudzinska)
+svg2png: Junsu Choi (JSUYA)
+capi: Mira Grudzinska (mgrudzinska)

## Self Test & Verification -- 2.7.4 From 254e4c689e8f624cd5815f2a7575f4de6f54063f Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 20 Aug 2022 14:27:11 +0900 Subject: [PATCH 12/16] apis: removed BETA_API tag for identifiers and Accessor. These apis are promoted to the official apis, released in v0.9 Change-Id: I677a125a0bf37e953842164e0e640946f52622b6 --- inc/thorvg.h | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index efba938..a63e964 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -368,8 +368,6 @@ public: * This method can be called for checking the current concrete instance type. * * @return The type id of the Paint instance. - * - * @BETA_API */ uint32_t identifier() const noexcept; @@ -476,8 +474,6 @@ public: * This method can be called for checking the current concrete instance type. * * @return The type id of the Fill instance. - * - * @BETA_API */ uint32_t identifier() const noexcept; @@ -643,8 +639,6 @@ public: * This method can be referred for identifying the LinearGradient class type. * * @return The type id of the LinearGradient class. - * - * @BETA_API */ static uint32_t identifier() noexcept; @@ -702,8 +696,6 @@ public: * This method can be referred for identifying the RadialGradient class type. * * @return The type id of the RadialGradient class. - * - * @BETA_API */ static uint32_t identifier() noexcept; @@ -1087,8 +1079,6 @@ public: * This method can be referred for identifying the Shape class type. * * @return The type id of the Shape class. - * - * @BETA_API */ static uint32_t identifier() noexcept; @@ -1212,16 +1202,17 @@ public: * * If triangles is null, or triangleCount is 0, the mesh will be removed. * - * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support + * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support. * mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh. * - * @param[in] triangles An array of Polygon objects (triangles) that make up the mesh, or null to remove the mesh - * @param[in] triangleCount The number of Polygon objects (triangles) provided, or 0 to remove the mesh + * @param[in] triangles An array of Polygon objects (triangles) that make up the mesh, or null to remove the mesh. + * @param[in] triangleCount The number of Polygon objects (triangles) provided, or 0 to remove the mesh. * * @retval Result::Success When succeed. * @retval Result::Unknown If fails * * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect. + * @warning Please do not use it, this API is not official one. It could be modified in the next version. * * @BETA_API */ @@ -1230,11 +1221,12 @@ public: /** * @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh. * - * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh + * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh. * - * @return uint32_t The number of polygons in the array + * @return uint32_t The number of polygons in the array. * - * @note Modifying the triangles returned by this method will modify them directly within the mesh + * @note Modifying the triangles returned by this method will modify them directly within the mesh. + * @warning Please do not use it, this API is not official one. It could be modified in the next version. * * @BETA_API */ @@ -1262,8 +1254,6 @@ public: * This method can be referred for identifying the Picture class type. * * @return The type id of the Picture class. - * - * @BETA_API */ static uint32_t identifier() noexcept; @@ -1342,8 +1332,6 @@ public: * This method can be referred for identifying the Scene class type. * * @return The type id of the Scene class. - * - * @BETA_API */ static uint32_t identifier() noexcept; @@ -1608,8 +1596,6 @@ public: * The Accessor helps you search specific nodes to read the property information, figure out the structure of the scene tree and its size. * * @warning We strongly warn you not to change the paints of a scene unless you really know the design-structure. - * - * @BETA_API */ class TVG_EXPORT Accessor final { @@ -1625,8 +1611,6 @@ public: * @return Return the given @p picture instance. * * @note The bitmap based picture might not have the scene-tree. - * - * @BETA_API */ std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint)) noexcept; @@ -1634,8 +1618,6 @@ public: * @brief Creates a new Accessor object. * * @return A new Accessor object. - * - * @BETA_API */ static std::unique_ptr gen() noexcept; -- 2.7.4 From 2a9a180f171df3d4db7c4654872105a0a8972f41 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 20 Aug 2022 14:44:20 +0900 Subject: [PATCH 13/16] common picture: code refactoring. ++ neat & clean Change-Id: I40a28efd77c5bd1dc680fb9a774196a263397e91 --- src/lib/tvgPictureImpl.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index d8aaec0..ac274df 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -193,21 +193,16 @@ struct Picture::Impl if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y; else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y; } - if (x) *x = min.x; if (y) *y = min.y; if (w) *w = max.x - min.x; if (h) *h = max.y - min.y; - } else { - if (x) *x = 0; if (y) *y = 0; if (w) *w = this->w; if (h) *h = this->h; - } - return true; } @@ -262,7 +257,7 @@ struct Picture::Impl if (triangles && triangleCount > 0) { this->triangleCount = triangleCount; this->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCount); - for (uint32_t i = 0; i < triangleCount; i++) this->triangles[i] = triangles[i]; + memcpy(this->triangles, triangles, sizeof(Polygon) * triangleCount); } else { free(this->triangles); this->triangles = nullptr; @@ -292,7 +287,7 @@ struct Picture::Impl if (triangleCount > 0) { dup->triangleCount = triangleCount; dup->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCount); - for (uint32_t i = 0; i < triangleCount; i++) dup->triangles[i] = triangles[i]; + memcpy(dup->triangles, triangles, sizeof(Polygon) * triangleCount); } return ret.release(); -- 2.7.4 From 6fd83c4acf170df76e30aacef1cfffa4e74d0958 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 20 Aug 2022 15:21:31 +0900 Subject: [PATCH 14/16] common picture: code refactoring. keep api parameter naming consistency. ptsCnt, cmdCnt, triangleCnt ... Change-Id: Ie2b6c7e7781877700dd446a838c254ef73d02413 --- inc/thorvg.h | 8 ++++---- src/lib/sw_engine/tvgSwRenderer.cpp | 12 ++++++------ src/lib/tvgPicture.cpp | 6 +++--- src/lib/tvgPictureImpl.h | 28 ++++++++++++++-------------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index a63e964..0ab99e5 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1200,13 +1200,13 @@ public: * If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the * image data will be used as the texture. * - * If triangles is null, or triangleCount is 0, the mesh will be removed. + * If @p triangles is @c nullptr, or @p triangleCnt is 0, the mesh will be removed. * * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support. * mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh. * - * @param[in] triangles An array of Polygon objects (triangles) that make up the mesh, or null to remove the mesh. - * @param[in] triangleCount The number of Polygon objects (triangles) provided, or 0 to remove the mesh. + * @param[in] triangles An array of Polygons(triangles) that make up the mesh, or null to remove the mesh. + * @param[in] triangleCnt The number of Polygons(triangles) provided, or 0 to remove the mesh. * * @retval Result::Success When succeed. * @retval Result::Unknown If fails @@ -1216,7 +1216,7 @@ public: * * @BETA_API */ - Result mesh(const Polygon* triangles, const uint32_t triangleCount) noexcept; + Result mesh(const Polygon* triangles, const uint32_t triangleCnt) noexcept; /** * @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh. diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 692d592..03bc695 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -182,7 +182,7 @@ struct SwImageTask : SwTask { SwImage image; Polygon* triangles; - uint32_t triangleCount; + uint32_t triangleCnt; void run(unsigned tid) override { @@ -193,10 +193,10 @@ struct SwImageTask : SwTask imageReset(&image); if (!image.data || image.w == 0 || image.h == 0) goto end; - if (!imagePrepare(&image, triangles, triangleCount, transform, clipRegion, bbox, mpool, tid)) goto end; + if (!imagePrepare(&image, triangles, triangleCnt, transform, clipRegion, bbox, mpool, tid)) goto end; // TODO: How do we clip the triangle mesh? Only clip non-meshed images for now - if (triangleCount == 0 && clips.count > 0) { + if (triangleCnt == 0 && clips.count > 0) { if (!imageGenRle(&image, bbox, false)) goto end; if (image.rle) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { @@ -366,7 +366,7 @@ bool SwRenderer::renderImageMesh(RenderData data) if (task->opacity == 0) return true; - return rasterImageMesh(surface, &task->image, task->triangles, task->triangleCount, task->transform, task->bbox, task->opacity); + return rasterImageMesh(surface, &task->image, task->triangles, task->triangleCnt, task->transform, task->bbox, task->opacity); } @@ -624,7 +624,7 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, } -RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t triangleCount, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) +RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) { //prepare task auto task = static_cast(data); @@ -635,7 +635,7 @@ RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t tria task->image.h = image->h; task->image.stride = image->stride; task->triangles = triangles; - task->triangleCount = triangleCount; + task->triangleCnt = triangleCnt; } return prepareCommon(task, transform, opacity, clips, flags); } diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 4449d2d..56f447d 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -121,9 +121,9 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept } -Result Picture::mesh(const Polygon* triangles, const uint32_t triangleCount) noexcept +Result Picture::mesh(const Polygon* triangles, const uint32_t triangleCnt) noexcept { - if (pImpl->mesh(triangles, triangleCount)) return Result::Success; + if (pImpl->mesh(triangles, triangleCnt)) return Result::Success; return Result::Unknown; } @@ -131,5 +131,5 @@ Result Picture::mesh(const Polygon* triangles, const uint32_t triangleCount) noe uint32_t Picture::mesh(const Polygon** triangles) const noexcept { if (triangles) *triangles = pImpl->triangles; - return pImpl->triangleCount; + return pImpl->triangleCnt; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index ac274df..0ad7e03 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -64,7 +64,7 @@ struct Picture::Impl Paint* paint = nullptr; //vector picture uses Surface* surface = nullptr; //bitmap picture uses Polygon* triangles = nullptr; //mesh data - uint32_t triangleCount = 0; //mesh triangle count + uint32_t triangleCnt = 0; //mesh triangle count void* rdata = nullptr; //engine data float w = 0, h = 0; bool resizing = false; @@ -131,7 +131,7 @@ struct Picture::Impl if (surface) { auto transform = resizeTransform(pTransform); - rdata = renderer.prepare(surface, triangles, triangleCount, rdata, &transform, opacity, clips, static_cast(pFlag | flag)); + rdata = renderer.prepare(surface, triangles, triangleCnt, rdata, &transform, opacity, clips, static_cast(pFlag | flag)); } else if (paint) { if (resizing) { loader->resize(paint, w, h); @@ -172,12 +172,12 @@ struct Picture::Impl bool bounds(float* x, float* y, float* w, float* h) { - if (triangleCount > 0) { + if (triangleCnt > 0) { Point min = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; Point max = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; - for (uint32_t i = 0; i < triangleCount; ++i) { + for (uint32_t i = 0; i < triangleCnt; ++i) { if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x; else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x; if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y; @@ -252,16 +252,16 @@ struct Picture::Impl return Result::Success; } - bool mesh(const Polygon* triangles, const uint32_t triangleCount) + bool mesh(const Polygon* triangles, const uint32_t triangleCnt) { - if (triangles && triangleCount > 0) { - this->triangleCount = triangleCount; - this->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCount); - memcpy(this->triangles, triangles, sizeof(Polygon) * triangleCount); + if (triangles && triangleCnt > 0) { + this->triangleCnt = triangleCnt; + this->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCnt); + memcpy(this->triangles, triangles, sizeof(Polygon) * triangleCnt); } else { free(this->triangles); this->triangles = nullptr; - this->triangleCount = 0; + this->triangleCnt = 0; } return true; } @@ -284,10 +284,10 @@ struct Picture::Impl dup->h = h; dup->resizing = resizing; - if (triangleCount > 0) { - dup->triangleCount = triangleCount; - dup->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCount); - memcpy(dup->triangles, triangles, sizeof(Polygon) * triangleCount); + if (triangleCnt > 0) { + dup->triangleCnt = triangleCnt; + dup->triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCnt); + memcpy(dup->triangles, triangles, sizeof(Polygon) * triangleCnt); } return ret.release(); -- 2.7.4 From 72ac998028633702024dd063cff46ef73d2c841c Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Sat, 20 Aug 2022 10:55:16 +0200 Subject: [PATCH 15/16] fix compilation of svg2png on Windows Change-Id: I9d7dda51a99d0112357bb61cb19f9b55ce802ac1 --- src/bin/svg2png/svg2png.cpp | 88 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/src/bin/svg2png/svg2png.cpp b/src/bin/svg2png/svg2png.cpp index 0699545..71bc1c0 100644 --- a/src/bin/svg2png/svg2png.cpp +++ b/src/bin/svg2png/svg2png.cpp @@ -25,9 +25,17 @@ #include #include #include "lodepng.h" -#include -#include -#include +#ifdef _WIN32 + #include + #ifndef PATH_MAX + #define PATH_MAX MAX_PATH + #endif +#else + #include + #include + #include + #include +#endif using namespace std; @@ -229,11 +237,10 @@ public: for (auto path : paths) { auto real_path = realFile(path); if (real_path) { - DIR* dir = opendir(real_path); - if (dir) { + if (isDirectory(real_path)) { //load from directory cout << "Trying load from directory \"" << real_path << "\"." << endl; - if ((ret = handleDirectory(real_path, dir))) break; + if ((ret = handleDirectory(real_path))) break; } else if (svgFile(path)) { //load single file @@ -286,6 +293,25 @@ private: return path; } + bool isDirectory(const char* path) + { +#ifdef _WIN32 + DWORD attr = GetFileAttributes(path); + if (attr == INVALID_FILE_ATTRIBUTES) + return false; + + return attr & FILE_ATTRIBUTE_DIRECTORY; +#else + struct stat buf; + + if (stat(path, &buf) != 0) { + return false; + } + + return S_ISDIR(buf.st_mode); +#endif + } + int renderFile(const char* path) { if (!path) return 1; @@ -299,15 +325,42 @@ private: return renderer.render(path, width, height, dst, bgColor); } - int handleDirectory(const string& path, DIR* dir) + int handleDirectory(const string& path) { //open directory - if (!dir) { - dir = opendir(path.c_str()); - if (!dir) { - cout << "Couldn't open directory \"" << path.c_str() << "\"." << endl; - return 1; +#ifdef _WIN32 + WIN32_FIND_DATA fd; + HANDLE h = FindFirstFileEx((path + "\\*").c_str(), FindExInfoBasic, &fd, FindExSearchNameMatch, NULL, 0); + if (h == INVALID_HANDLE_VALUE) { + cout << "Couldn't open directory \"" << path.c_str() << "\"." << endl; + return 1; + } + int ret = 0; + do { + if (*fd.cFileName == '.' || *fd.cFileName == '$') continue; + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + string subpath = string(path); + subpath += '\\'; + subpath += fd.cFileName; + ret = handleDirectory(subpath); + if (ret) break; + + } else { + if (!svgFile(fd.cFileName)) continue; + string fullpath = string(path); + fullpath += '\\'; + fullpath += fd.cFileName; + ret = renderFile(fullpath.c_str()); + if (ret) break; } + } while (FindNextFile(h, &fd)); + + FindClose(h); +#else + DIR* dir = opendir(path.c_str()); + if (!dir) { + cout << "Couldn't open directory \"" << path.c_str() << "\"." << endl; + return 1; } //list directory @@ -317,29 +370,22 @@ private: if (*entry->d_name == '.' || *entry->d_name == '$') continue; if (entry->d_type == DT_DIR) { string subpath = string(path); -#ifdef _WIN32 - subpath += '\\'; -#else subpath += '/'; -#endif subpath += entry->d_name; - ret = handleDirectory(subpath, nullptr); + ret = handleDirectory(subpath); if (ret) break; } else { if (!svgFile(entry->d_name)) continue; string fullpath = string(path); -#ifdef _WIN32 - fullpath += '\\'; -#else fullpath += '/'; -#endif fullpath += entry->d_name; ret = renderFile(fullpath.c_str()); if (ret) break; } } closedir(dir); +#endif return ret; } }; -- 2.7.4 From 73b96e7f911f83b3c488eaf79e389baf19b93a67 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 23 Aug 2022 22:44:24 +0900 Subject: [PATCH 16/16] examples: fix a compilation error on windows. ../src/examples/Performance.cpp:32:8: error: 'uint' does not name a type; did you mean 'u_int'? 32 | static uint cnt = 0; | ^~~~ | u_int @Issues: https://github.com/Samsung/thorvg/issues/1247 Change-Id: I3f9ae082a89d32519517bedce68cdd5e0c21564b --- src/examples/Performance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/Performance.cpp b/src/examples/Performance.cpp index 6625aad..ddc5d78 100644 --- a/src/examples/Performance.cpp +++ b/src/examples/Performance.cpp @@ -29,7 +29,7 @@ static tvg::Picture* pPicture = nullptr; static double updateTime = 0; static double accumulateTime = 0; -static uint cnt = 0; +static uint32_t cnt = 0; void tvgDrawCmds(tvg::Canvas* canvas) { -- 2.7.4