From fb52ddf7f88c2e6608139762033af8781f4995cb Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Tue, 13 Jul 2021 14:28:52 +0200 Subject: [PATCH 01/16] svg_loader: race condition on arc processing Unneeded static keyword in _pathAppendArcTo function led to race conditioning @issue: #604 Change-Id: I1741b56f6cf210b7709f513aceb657840851b3bf --- src/loaders/svg/tvgSvgPath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loaders/svg/tvgSvgPath.cpp b/src/loaders/svg/tvgSvgPath.cpp index 1c8538f..b73d132 100644 --- a/src/loaders/svg/tvgSvgPath.cpp +++ b/src/loaders/svg/tvgSvgPath.cpp @@ -207,7 +207,7 @@ void _pathAppendArcTo(Array* cmds, Array* pts, Point* cur, P float theta2 = theta1 + delta; float cosTheta2 = cos(theta2); float sinTheta2 = sin(theta2); - static Point p[3]; + Point p[3]; //First control point (based on start point sx,sy) c1x = sx - bcp * (cosPhiRx * sinTheta1 + sinPhiRy * cosTheta1); -- 2.7.4 From c058223d9852b581bb2cb7d29bbd0f4e1274c0f5 Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Tue, 13 Jul 2021 11:26:15 +0200 Subject: [PATCH 02/16] svg_loader: image tag: fixed utf8 decode Fixed svgUtilURLDecode function. Deleted snippet was not needed and it broken decoding when space. Change-Id: I1f14ff60c10f8c73006c7ab4fc6bf0b0f945d02e --- src/loaders/svg/tvgSvgUtil.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/loaders/svg/tvgSvgUtil.cpp b/src/loaders/svg/tvgSvgUtil.cpp index 3db6098..b0f1d84 100644 --- a/src/loaders/svg/tvgSvgUtil.cpp +++ b/src/loaders/svg/tvgSvgUtil.cpp @@ -271,11 +271,6 @@ string svgUtilURLDecode(const char *src) char a, b; while (*src) { - if (*src <= 0x20) { - ++src; - continue; - } - if (*src == '%' && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) { -- 2.7.4 From 30ab8c3c91d39ceaf8fd290f4f59332c221424a2 Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:19:42 +0200 Subject: [PATCH 03/16] capi binding: added missing null paint check (#616) --- src/bindings/capi/tvgCapi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 0809f5d..40183ad 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -265,6 +265,7 @@ TVG_EXPORT Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry) { + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; return (Tvg_Result) reinterpret_cast(paint)->appendCircle(cx, cy, rx, ry); } -- 2.7.4 From bc7cfa6253fd3a14793fbf660df0a65b48dd76fd Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Wed, 14 Jul 2021 13:57:32 +0200 Subject: [PATCH 04/16] example: logo_test.svg (#617) Manually created svg with edited logo.svg that test most of the svg tags and attributes --- src/examples/images/logo_test.svg | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/examples/images/logo_test.svg diff --git a/src/examples/images/logo_test.svg b/src/examples/images/logo_test.svg new file mode 100644 index 0000000..4533376 --- /dev/null +++ b/src/examples/images/logo_test.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- 2.7.4 From 4b2bca95221dadffb5c29138bb8351bc3bf43d85 Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Wed, 14 Jul 2021 11:59:50 +0200 Subject: [PATCH 05/16] test capi: scene added negative tests --- test/capi/capiScene.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/test/capi/capiScene.cpp b/test/capi/capiScene.cpp index ba6044b..892630c 100644 --- a/test/capi/capiScene.cpp +++ b/test/capi/capiScene.cpp @@ -37,12 +37,13 @@ TEST_CASE("Paints Into a Scene", "[capiScene]") 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); + 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); - //Pusing Null Pointer + //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); } @@ -61,6 +62,9 @@ TEST_CASE("Scene Reservation", "[capiScene]") //Too big size REQUIRE(tvg_scene_reserve(scene, -1) == TVG_RESULT_FAILED_ALLOCATION); + //Invalid scene + REQUIRE(tvg_scene_reserve(NULL, 1) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS); } @@ -69,9 +73,12 @@ 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_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); } @@ -93,7 +100,7 @@ TEST_CASE("Scene reusing paints", "[capiScene]") Tvg_Paint* shape = tvg_shape_new(); REQUIRE(shape); - REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); + 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); @@ -101,7 +108,7 @@ TEST_CASE("Scene reusing paints", "[capiScene]") REQUIRE(tvg_scene_clear(scene, false) == TVG_RESULT_SUCCESS); //Reuse shape. - REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_scene_push(scene, shape) == TVG_RESULT_SUCCESS); REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); -- 2.7.4 From 274f60d25acbf49f1571d251b6109c825fac6a52 Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Wed, 14 Jul 2021 11:27:19 +0200 Subject: [PATCH 06/16] test: svg rendering Added SVG file loading and rendering for increasing TC Line coverage Line coverage for src/loaders/svg: 85.5% --- test/testPicture.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/testPicture.cpp b/test/testPicture.cpp index 2b5eff8..ce87258 100644 --- a/test/testPicture.cpp +++ b/test/testPicture.cpp @@ -130,4 +130,24 @@ TEST_CASE("Picture Size", "[tvgPicture]") REQUIRE(picture->load(EXAMPLE_DIR"/tiger.svg") == Result::Success); REQUIRE(picture->size(&w, &h) == Result::Success); REQUIRE(picture->size(w, h) == Result::Success); -} \ No newline at end of file +} + +TEST_CASE("Load SVG file and render", "[tvgPicture]") +{ + REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success); + + auto canvas = SwCanvas::gen(); + REQUIRE(canvas); + + uint32_t buffer[100*100]; + REQUIRE(canvas->target(buffer, 100, 100, 100, SwCanvas::Colorspace::ABGR8888) == Result::Success); + + auto picture = Picture::gen(); + REQUIRE(picture); + + REQUIRE(picture->load(EXAMPLE_DIR"/logo_test.svg") == Result::Success); + + REQUIRE(canvas->push(move(picture)) == Result::Success); + + REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); +} -- 2.7.4 From 03b3f85b3adbf4a11379a758d5d8d7b90af05bdd Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Thu, 15 Jul 2021 02:24:13 +0200 Subject: [PATCH 07/16] github actions: added tvg and jpg loaders (#613) * github actions: added tvg and jpg loaders * github actions: added tvg and jpg loaders fix #1 Added install libturbojpeg --- .github/workflows/actions.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 956d379..0093408 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -17,10 +17,13 @@ jobs: run: | sudo apt-get update sudo apt-get install ninja-build gcc-multilib g++-multilib meson + + - name: Install TurboJPEG library + run: sudo apt-get install libturbojpeg0-dev libjpeg8-dev - name: Build run: | - meson . build -Dlog=true -Dloaders="svg, png" + meson . build -Dlog=true -Dloaders="svg, tvg, png, jpg" cd build sudo ninja -C . install @@ -36,10 +39,13 @@ jobs: sudo add-apt-repository ppa:niko2040/e19 sudo apt-get install ninja-build gcc-multilib g++-multilib meson sudo apt-get install libefl-dev + + - name: Install TurboJPEG library + run: sudo apt-get install libturbojpeg0-dev libjpeg8-dev - name: Build run: | - meson . build -Dexamples=true -Dloaders="svg, png" + meson . build -Dexamples=true -Dloaders="svg, tvg, png, jpg" cd build sudo ninja -C . install @@ -54,9 +60,13 @@ jobs: run: | sudo apt-get update sudo apt-get install ninja-build gcc-multilib g++-multilib libgtest-dev meson cmake cmake-data + + - name: Install TurboJPEG library + run: sudo apt-get install libturbojpeg0-dev libjpeg8-dev + - name: Install-ThorVG run: | - meson . build -Dloaders="svg, png" -Dbindings="capi" + meson . build -Dloaders="svg, tvg, png, jpg" -Dbindings="capi" cd build sudo ninja -C . install cd .. @@ -64,7 +74,7 @@ jobs: - name: Build run: | - meson . build -Dtests=true -Dloaders="svg, png" -Dbindings="capi" --errorlogs + meson . build -Dtests=true -Dloaders="svg, tvg, png, jpg" -Dbindings="capi" --errorlogs cd build sudo ninja -C . install test -- 2.7.4 From b37deebeb4d8a67e42cb873dde7186f9b1b9f7a2 Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Wed, 14 Jul 2021 09:38:34 +0200 Subject: [PATCH 08/16] test capi: Stroke Linear Gradient --- test/capi/capiLinearGradient.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/capi/capiLinearGradient.cpp b/test/capi/capiLinearGradient.cpp index 317da58..86c6f34 100644 --- a/test/capi/capiLinearGradient.cpp +++ b/test/capi/capiLinearGradient.cpp @@ -58,7 +58,7 @@ TEST_CASE("Linear Gradient in shape", "[capiLinearGradient]") Tvg_Paint *shape = tvg_shape_new(); REQUIRE(shape); - REQUIRE(tvg_gradient_del(gradient) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_set_linear_gradient(shape, gradient) == TVG_RESULT_SUCCESS); REQUIRE(tvg_shape_set_linear_gradient(shape, NULL) == TVG_RESULT_MEMORY_CORRUPTION); REQUIRE(tvg_paint_del(shape) == TVG_RESULT_SUCCESS); @@ -135,3 +135,37 @@ TEST_CASE("Linear Gradient spread", "[capiLinearGradient]") REQUIRE(tvg_gradient_del(gradient) == TVG_RESULT_SUCCESS); REQUIRE(tvg_gradient_del(NULL) == TVG_RESULT_INVALID_ARGUMENT); } + +TEST_CASE("Stroke Linear Gradient", "[capiLinearGradient]") +{ + Tvg_Paint *shape = tvg_shape_new(); + REQUIRE(shape != NULL); + + Tvg_Gradient *gradient = tvg_linear_gradient_new(); + REQUIRE(gradient != NULL); + + Tvg_Color_Stop color_stops[2] = + { + {.offset=0.0, .r=0, .g=0, .b=0, .a=255}, + {.offset=1, .r=0, .g=255, .b=0, .a=255}, + }; + + Tvg_Gradient *gradient_ret = NULL; + const Tvg_Color_Stop *color_stops_ret = NULL; + uint32_t color_stops_count_ret = 0; + + REQUIRE(tvg_gradient_set_color_stops(gradient, color_stops, 2) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_shape_set_stroke_linear_gradient(NULL, NULL) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_set_stroke_linear_gradient(NULL, gradient) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_set_stroke_linear_gradient(shape, gradient) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_shape_get_stroke_gradient(shape, &gradient_ret) == TVG_RESULT_SUCCESS); + REQUIRE(gradient_ret); + + REQUIRE(tvg_gradient_get_color_stops(gradient_ret, &color_stops_ret, &color_stops_count_ret) == TVG_RESULT_SUCCESS); + REQUIRE(color_stops_ret); + REQUIRE(color_stops_count_ret == 2); + + REQUIRE(tvg_paint_del(shape) == TVG_RESULT_SUCCESS); +} -- 2.7.4 From e869369eb3c62759da43df9c16fe2ddcf02c0125 Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Wed, 14 Jul 2021 10:40:40 +0200 Subject: [PATCH 09/16] test capi: Stroke Linear Gradient fix #1 Added tvg_shape_get_gradient --- test/capi/capiLinearGradient.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/capi/capiLinearGradient.cpp b/test/capi/capiLinearGradient.cpp index 86c6f34..b2bf1f4 100644 --- a/test/capi/capiLinearGradient.cpp +++ b/test/capi/capiLinearGradient.cpp @@ -60,6 +60,10 @@ TEST_CASE("Linear Gradient in shape", "[capiLinearGradient]") REQUIRE(tvg_shape_set_linear_gradient(shape, gradient) == TVG_RESULT_SUCCESS); + Tvg_Gradient *gradient_ret = NULL; + REQUIRE(tvg_shape_get_gradient(shape, &gradient_ret) == TVG_RESULT_SUCCESS); + REQUIRE(gradient_ret); + REQUIRE(tvg_shape_set_linear_gradient(shape, NULL) == TVG_RESULT_MEMORY_CORRUPTION); REQUIRE(tvg_paint_del(shape) == TVG_RESULT_SUCCESS); } -- 2.7.4 From f96a9859212c7b09ee929ccbb247e8d27d7efe5d Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Wed, 14 Jul 2021 16:32:43 +0200 Subject: [PATCH 10/16] test capi: Stroke Linear Gradient fix #2 --- test/capi/capiLinearGradient.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/capi/capiLinearGradient.cpp b/test/capi/capiLinearGradient.cpp index b2bf1f4..f5d2a25 100644 --- a/test/capi/capiLinearGradient.cpp +++ b/test/capi/capiLinearGradient.cpp @@ -98,10 +98,10 @@ TEST_CASE("Linear Gradient color stops", "[capiLinearGradient]") TEST_CASE("Linear Gradient clear data", "[capiLinearGradient]") { Tvg_Paint *shape = tvg_shape_new(); - REQUIRE(shape != NULL); + REQUIRE(shape); Tvg_Gradient *gradient = tvg_linear_gradient_new(); - REQUIRE(gradient != NULL); + REQUIRE(gradient); Tvg_Color_Stop color_stops[2] = { @@ -143,10 +143,10 @@ TEST_CASE("Linear Gradient spread", "[capiLinearGradient]") TEST_CASE("Stroke Linear Gradient", "[capiLinearGradient]") { Tvg_Paint *shape = tvg_shape_new(); - REQUIRE(shape != NULL); + REQUIRE(shape); Tvg_Gradient *gradient = tvg_linear_gradient_new(); - REQUIRE(gradient != NULL); + REQUIRE(gradient); Tvg_Color_Stop color_stops[2] = { -- 2.7.4 From 60d29c7b356800f8a504f53e00576fc2b429ee9c Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Thu, 15 Jul 2021 11:13:20 +0200 Subject: [PATCH 11/16] test: render jpg and png files --- test/testPicture.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/testPicture.cpp b/test/testPicture.cpp index ce87258..919e72f 100644 --- a/test/testPicture.cpp +++ b/test/testPicture.cpp @@ -151,3 +151,43 @@ TEST_CASE("Load SVG file and render", "[tvgPicture]") REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); } + +TEST_CASE("Load PNG file and render", "[tvgPicture]") +{ + REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success); + + auto canvas = SwCanvas::gen(); + REQUIRE(canvas); + + uint32_t buffer[100*100]; + REQUIRE(canvas->target(buffer, 100, 100, 100, SwCanvas::Colorspace::ABGR8888) == Result::Success); + + auto picture = Picture::gen(); + REQUIRE(picture); + + REQUIRE(picture->load(EXAMPLE_DIR"/logo.png") == Result::Success); + + REQUIRE(canvas->push(move(picture)) == Result::Success); + + REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); +} + +TEST_CASE("Load JPG file and render", "[tvgPicture]") +{ + REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success); + + auto canvas = SwCanvas::gen(); + REQUIRE(canvas); + + uint32_t buffer[100*100]; + REQUIRE(canvas->target(buffer, 100, 100, 100, SwCanvas::Colorspace::ABGR8888) == Result::Success); + + auto picture = Picture::gen(); + REQUIRE(picture); + + REQUIRE(picture->load(EXAMPLE_DIR"/logo.jpg") == Result::Success); + + REQUIRE(canvas->push(move(picture)) == Result::Success); + + REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); +} -- 2.7.4 From 1fbf162982e6941814d5f720a17b5f19b34cea1e Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Thu, 15 Jul 2021 17:32:41 +0200 Subject: [PATCH 12/16] test capi: Stroke Radial Gradient Added tvg_shape_get_gradient --- test/capi/capiRadialGradient.cpp | 61 ++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/test/capi/capiRadialGradient.cpp b/test/capi/capiRadialGradient.cpp index 608f41a..ca31721 100644 --- a/test/capi/capiRadialGradient.cpp +++ b/test/capi/capiRadialGradient.cpp @@ -38,9 +38,9 @@ TEST_CASE("Set gradient center point and radius", "[capiRadialGradient]") float cx, cy, radius; REQUIRE(tvg_radial_gradient_get(gradient, &cx, &cy, &radius) == TVG_RESULT_SUCCESS); - REQUIRE(cx == 10.0); - REQUIRE(cy == 15.0); - REQUIRE(radius == 30.0); + REQUIRE(cx == Approx(10.0).margin(0.000001)); + REQUIRE(cy == Approx(15.0).margin(0.000001)); + REQUIRE(radius == Approx(30.0).margin(0.000001)); REQUIRE(tvg_gradient_del(gradient) == TVG_RESULT_SUCCESS); } @@ -49,15 +49,18 @@ TEST_CASE("Set gradient in shape", "[capiRadialGradient]") { REQUIRE(tvg_shape_set_radial_gradient(NULL, NULL) == TVG_RESULT_INVALID_ARGUMENT); - Tvg_Paint *shape = tvg_shape_new(); - REQUIRE(shape); - Tvg_Gradient *gradient = tvg_radial_gradient_new(); REQUIRE(gradient); + Tvg_Paint *shape = tvg_shape_new(); + REQUIRE(shape); + REQUIRE(tvg_shape_set_radial_gradient(NULL, gradient) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_set_radial_gradient(shape, gradient) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_gradient_del(gradient) == TVG_RESULT_SUCCESS); + Tvg_Gradient *gradient_ret = NULL; + REQUIRE(tvg_shape_get_gradient(shape, &gradient_ret) == TVG_RESULT_SUCCESS); + REQUIRE(gradient_ret); REQUIRE(tvg_shape_set_radial_gradient(shape, NULL) == TVG_RESULT_MEMORY_CORRUPTION); REQUIRE(tvg_paint_del(shape) == TVG_RESULT_SUCCESS); @@ -133,4 +136,46 @@ TEST_CASE("Set/Get gradient spread", "[capiRadialGradient]") REQUIRE(tvg_gradient_del(gradient) == TVG_RESULT_SUCCESS); REQUIRE(tvg_gradient_del(NULL) == TVG_RESULT_INVALID_ARGUMENT); -} \ No newline at end of file +} + +TEST_CASE("Stroke Radial Gradient", "[capiRadialGradient]") +{ + Tvg_Paint *shape = tvg_shape_new(); + REQUIRE(shape); + + Tvg_Gradient *gradient = tvg_radial_gradient_new(); + REQUIRE(gradient); + + REQUIRE(tvg_radial_gradient_set(gradient, 10.0, 15.0, 30.0) == TVG_RESULT_SUCCESS); + + Tvg_Color_Stop color_stops[2] = + { + {.offset=0.0, .r=0, .g=0, .b=0, .a=255}, + {.offset=1, .r=0, .g=255, .b=0, .a=255}, + }; + + Tvg_Gradient *gradient_ret = NULL; + const Tvg_Color_Stop *color_stops_ret = NULL; + uint32_t color_stops_count_ret = 0; + + REQUIRE(tvg_gradient_set_color_stops(gradient, color_stops, 2) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_shape_set_stroke_radial_gradient(NULL, NULL) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_set_stroke_radial_gradient(NULL, gradient) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_set_stroke_radial_gradient(shape, gradient) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_shape_get_stroke_gradient(shape, &gradient_ret) == TVG_RESULT_SUCCESS); + REQUIRE(gradient_ret); + + REQUIRE(tvg_gradient_get_color_stops(gradient_ret, &color_stops_ret, &color_stops_count_ret) == TVG_RESULT_SUCCESS); + REQUIRE(color_stops_ret); + REQUIRE(color_stops_count_ret == 2); + + float cx, cy, radius; + REQUIRE(tvg_radial_gradient_get(gradient_ret, &cx, &cy, &radius) == TVG_RESULT_SUCCESS); + REQUIRE(cx == Approx(10.0).margin(0.000001)); + REQUIRE(cy == Approx(15.0).margin(0.000001)); + REQUIRE(radius == Approx(30.0).margin(0.000001)); + + REQUIRE(tvg_paint_del(shape) == TVG_RESULT_SUCCESS); +} -- 2.7.4 From 19243ec2cd96792f7203071391da2d53eb519a1e Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Thu, 15 Jul 2021 17:34:54 +0200 Subject: [PATCH 13/16] test capi: added missing canvas, paint and shape tests Added tests for tvg_canvas_reserve, tvg_canvas_update_paint, tvg_paint_duplicate, tvg_paint_set_composite_method, tvg_shape_cubic_to, tvg_shape_close --- test/capi/capiPaint.cpp | 65 +++++++++++++++++++++++++++++++++++++++++----- test/capi/capiShape.cpp | 50 ++++++++++++++++++++++++++++++++++- test/capi/capiSwCanvas.cpp | 42 ++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 8 deletions(-) diff --git a/test/capi/capiPaint.cpp b/test/capi/capiPaint.cpp index dced66c..0ec9c60 100644 --- a/test/capi/capiPaint.cpp +++ b/test/capi/capiPaint.cpp @@ -24,7 +24,7 @@ #include "../catch.hpp" -TEST_CASE("Paint Transform", "[capiPaintTransform]") +TEST_CASE("Paint Transform", "[capiPaint]") { Tvg_Paint* paint = tvg_shape_new(); REQUIRE(paint); @@ -46,7 +46,7 @@ TEST_CASE("Paint Transform", "[capiPaintTransform]") REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } -TEST_CASE("Paint Translate", "[capiPaintTranslate]") +TEST_CASE("Paint Translate", "[capiPaint]") { Tvg_Paint* paint = tvg_shape_new(); REQUIRE(paint); @@ -68,7 +68,7 @@ TEST_CASE("Paint Translate", "[capiPaintTranslate]") REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } -TEST_CASE("Paint Scale", "[capiPaintScale]") +TEST_CASE("Paint Scale", "[capiPaint]") { Tvg_Paint* paint = tvg_shape_new(); REQUIRE(paint); @@ -90,7 +90,7 @@ TEST_CASE("Paint Scale", "[capiPaintScale]") REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } -TEST_CASE("Paint Rotate", "[capiPaintRotate]") +TEST_CASE("Paint Rotate", "[capiPaint]") { Tvg_Paint* paint = tvg_shape_new(); REQUIRE(paint); @@ -112,7 +112,7 @@ TEST_CASE("Paint Rotate", "[capiPaintRotate]") REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } -TEST_CASE("Paint Opacity", "[capiPaintOpacity]") +TEST_CASE("Paint Opacity", "[capiPaint]") { Tvg_Paint* paint = tvg_shape_new(); REQUIRE(paint); @@ -134,7 +134,7 @@ TEST_CASE("Paint Opacity", "[capiPaintOpacity]") REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } -TEST_CASE("Paint Bounds", "[capiPaintBounds]") +TEST_CASE("Paint Bounds", "[capiPaint]") { Tvg_Paint* paint = tvg_shape_new(); REQUIRE(paint); @@ -161,4 +161,55 @@ TEST_CASE("Paint Bounds", "[capiPaintBounds]") REQUIRE(h == 100); REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); -} \ No newline at end of file +} + +TEST_CASE("Paint Dupliction", "[capiPaint]") +{ + Tvg_Paint* paint = tvg_shape_new(); + REQUIRE(paint); + + REQUIRE(tvg_paint_set_opacity(paint, 0) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_paint_translate(paint, 200, 100) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_scale(paint, 2.2f) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_rotate(paint, 90.0f) == TVG_RESULT_SUCCESS); + + Tvg_Paint* paint_copy = tvg_paint_duplicate(paint); + REQUIRE(paint_copy); + + uint8_t opacity; + REQUIRE(tvg_paint_get_opacity(paint_copy, &opacity) == TVG_RESULT_SUCCESS); + REQUIRE(0 == opacity); + + Tvg_Matrix matrix; + REQUIRE(tvg_paint_get_transform(paint, &matrix) == TVG_RESULT_SUCCESS); + REQUIRE(matrix.e11 == Approx(0.0f).margin(0.000001)); + REQUIRE(matrix.e12 == Approx(-2.2f).margin(0.000001)); + REQUIRE(matrix.e13 == Approx(200.0f).margin(0.000001)); + REQUIRE(matrix.e21 == Approx(2.2f).margin(0.000001)); + REQUIRE(matrix.e22 == Approx(0.0f).margin(0.000001)); + REQUIRE(matrix.e23 == Approx(100.0f).margin(0.000001)); + REQUIRE(matrix.e31 == Approx(0.0f).margin(0.000001)); + REQUIRE(matrix.e32 == Approx(0.0f).margin(0.000001)); + REQUIRE(matrix.e33 == Approx(1.0f).margin(0.000001)); + + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_del(paint_copy) == TVG_RESULT_SUCCESS); +} + +TEST_CASE("Paint Clip Path Composite Method", "[capiPaint]") +{ + Tvg_Paint* paint = tvg_shape_new(); + REQUIRE(paint); + + Tvg_Paint* target = tvg_shape_new(); + REQUIRE(target); + + REQUIRE(tvg_paint_set_composite_method(paint, NULL, TVG_COMPOSITE_METHOD_NONE) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_set_composite_method(paint, target, TVG_COMPOSITE_METHOD_NONE) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_paint_set_composite_method(paint, target, TVG_COMPOSITE_METHOD_CLIP_PATH) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_set_composite_method(paint, NULL, TVG_COMPOSITE_METHOD_CLIP_PATH) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); +} diff --git a/test/capi/capiShape.cpp b/test/capi/capiShape.cpp index 65f7838..84172de 100644 --- a/test/capi/capiShape.cpp +++ b/test/capi/capiShape.cpp @@ -35,6 +35,22 @@ TEST_CASE("Multiple shapes", "[capiShapes]") REQUIRE(tvg_shape_append_circle(paint, 100, 100, 0, 0) == TVG_RESULT_SUCCESS); REQUIRE(tvg_shape_append_arc(paint, 100, 100, 50, 90, 90, 0) == TVG_RESULT_SUCCESS); + //Invalid paint + REQUIRE(tvg_shape_append_rect(NULL, 0, 0, 0, 0, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_append_circle(NULL, 0, 0, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_append_arc(NULL, 0, 0, 0, 0, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); +} + +TEST_CASE("Shape reset", "[capiShapes]") +{ + Tvg_Paint* paint = tvg_shape_new(); + REQUIRE(paint); + + REQUIRE(tvg_shape_reset(NULL) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_reset(paint) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } @@ -88,6 +104,27 @@ TEST_CASE("Shape path", "[capiShapePath]") REQUIRE(pts_get[i].y == pts[i].y); } + //Invalid paint + REQUIRE(tvg_shape_append_path(NULL, NULL, 0, NULL, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_get_path_coords(NULL, NULL, NULL) == TVG_RESULT_INVALID_ARGUMENT); + + REQUIRE(tvg_shape_reset(paint) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_shape_move_to(paint, 0, 10) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_line_to(paint, 100, 110) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_line_to(paint, 100, 10) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_close(paint) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_shape_move_to(paint, 100, 0) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_cubic_to(paint, 150, 0, 200, 50, 200, 100) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_close(paint) == TVG_RESULT_SUCCESS); + + //Invalid paint + REQUIRE(tvg_shape_move_to(NULL, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_line_to(NULL, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_cubic_to(NULL, 0, 0, 0, 0, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_close(NULL) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } @@ -106,6 +143,11 @@ TEST_CASE("Stroke width", "[capiStrokeWidth]") REQUIRE(tvg_shape_get_stroke_width(paint, &stroke) == TVG_RESULT_SUCCESS); REQUIRE(stroke == 5.0f); + //Invalid paint or width pointer + REQUIRE(tvg_shape_set_stroke_width(NULL, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_get_stroke_width(NULL, &stroke) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_get_stroke_width(paint, NULL) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } @@ -123,6 +165,12 @@ TEST_CASE("Stroke color", "[capiStrokeColor]") REQUIRE(b == 50); REQUIRE(a == 1); + //Invalid paint or no color pointers + REQUIRE(tvg_shape_set_stroke_color(NULL, 0, 0, 0, 0) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_get_stroke_color(NULL, &r, &g, &b, &a) == TVG_RESULT_INVALID_ARGUMENT); + REQUIRE(tvg_shape_get_stroke_color(paint, &r, &g, &b, NULL) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_shape_get_stroke_color(paint, NULL, NULL, NULL, &a) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); } @@ -216,4 +264,4 @@ TEST_CASE("Fill rule", "[capiFillRule]") REQUIRE(rule == rule_get); REQUIRE(tvg_paint_del(paint) == TVG_RESULT_SUCCESS); -} \ No newline at end of file +} diff --git a/test/capi/capiSwCanvas.cpp b/test/capi/capiSwCanvas.cpp index a0b9992..e35a872 100644 --- a/test/capi/capiSwCanvas.cpp +++ b/test/capi/capiSwCanvas.cpp @@ -45,6 +45,25 @@ TEST_CASE("Basic canvas", "[capiSwCanvas]") REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); } +TEST_CASE("Memory Reservation", "[capiSwCanvas]") +{ + REQUIRE(tvg_engine_init(TVG_ENGINE_SW, 0) == TVG_RESULT_SUCCESS); + + Tvg_Canvas* canvas = tvg_swcanvas_create(); + REQUIRE(canvas); + + REQUIRE(tvg_canvas_reserve(canvas, 1) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_reserve(canvas, 10) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_reserve(canvas, 100) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_reserve(canvas, 0) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_canvas_reserve(canvas, -1) == TVG_RESULT_FAILED_ALLOCATION); + + REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); +} + TEST_CASE("Canvas initialization", "[capiSwCanvas]") { uint32_t* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 200 * 200); @@ -104,3 +123,26 @@ TEST_CASE("Canvas draw", "[capiSwCanvas]") REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); } + +TEST_CASE("Canvas update, clear and reuse", "[capiSwCanvas]") +{ + REQUIRE(tvg_engine_init(TVG_ENGINE_SW, 0) == TVG_RESULT_SUCCESS); + + Tvg_Canvas* canvas = tvg_swcanvas_create(); + REQUIRE(canvas); + + Tvg_Paint* paint = tvg_shape_new(); + REQUIRE(paint); + + REQUIRE(tvg_canvas_push(canvas, paint) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_canvas_update_paint(canvas, paint) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_canvas_clear(canvas, false) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_canvas_push(canvas, paint) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); + + REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); +} -- 2.7.4 From c462cb2a81d7624881dd3c019db8226b74b9bd8f Mon Sep 17 00:00:00 2001 From: Michal Maciola Date: Wed, 14 Jul 2021 09:50:15 +0200 Subject: [PATCH 14/16] test: testPicture added .jpg and .png loading tests --- test/testPicture.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/test/testPicture.cpp b/test/testPicture.cpp index 919e72f..c6d6533 100644 --- a/test/testPicture.cpp +++ b/test/testPicture.cpp @@ -95,8 +95,7 @@ TEST_CASE("Load RAW Data", "[tvgPicture]") free(data); } - -TEST_CASE("Load PNG file", "[tvgPicture]") +TEST_CASE("Load PNG file from path", "[tvgPicture]") { auto picture = Picture::gen(); REQUIRE(picture); @@ -108,8 +107,75 @@ TEST_CASE("Load PNG file", "[tvgPicture]") float w, h; REQUIRE(picture->size(&w, &h) == Result::Success); + + REQUIRE(w == 1000); + REQUIRE(h == 1000); +} + +TEST_CASE("Load PNG file from data", "[tvgPicture]") +{ + auto picture = Picture::gen(); + REQUIRE(picture); + + //Open file + ifstream file(EXAMPLE_DIR"/logo.png"); + REQUIRE(file.is_open()); + auto size = sizeof(uint32_t) * (1000*1000); + auto data = (char*)malloc(size); + file.read(data, size); + file.close(); + + REQUIRE(picture->load(data, size, false) == Result::Success); + REQUIRE(picture->load(data, size, true) == Result::Success); + + float w, h; + REQUIRE(picture->size(&w, &h) == Result::Success); + REQUIRE(w == 1000); + REQUIRE(h == 1000); + + free(data); +} + +TEST_CASE("Load JPG file from path", "[tvgPicture]") +{ + auto picture = Picture::gen(); + REQUIRE(picture); + + //Invalid file + REQUIRE(picture->load("invalid.jpg") == Result::InvalidArguments); + + REQUIRE(picture->load(EXAMPLE_DIR"/logo.jpg") == Result::Success); + + float w, h; + REQUIRE(picture->size(&w, &h) == Result::Success); + + REQUIRE(w == 1000); + REQUIRE(h == 1000); } +TEST_CASE("Load JPG file from data", "[tvgPicture]") +{ + auto picture = Picture::gen(); + REQUIRE(picture); + + //Open file + ifstream file(EXAMPLE_DIR"/logo.jpg"); + REQUIRE(file.is_open()); + auto size = sizeof(uint32_t) * (1000*1000); + auto data = (char*)malloc(size); + file.read(data, size); + file.close(); + + REQUIRE(picture->load(data, size, false) == Result::Success); + REQUIRE(picture->load(data, size, true) == Result::Success); + + float w, h; + REQUIRE(picture->size(&w, &h) == Result::Success); + REQUIRE(w == 1000); + REQUIRE(h == 1000); + + free(data); +} TEST_CASE("Picture Size", "[tvgPicture]") { -- 2.7.4 From 28ead258cf4a77393ee76d47f224aff24ff7ed9f Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Fri, 16 Jul 2021 02:48:35 +0200 Subject: [PATCH 15/16] svg_loader: image tag: force size equal to the viewbox (#603) * svg_loader: image tag: force size equal to the viewbox For some svg files it is needed to force size equal the viewbox for proper scaling * svg_loader: image tag: force size equal to the viewbox fix #1 Change-Id: I480e832b1f5a184ef0ef6ee597a320d5bbf7b508 --- src/loaders/svg/tvgSvgSceneBuilder.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index 814d001..c2d608d 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -448,7 +448,6 @@ static unique_ptr _imageBuildHelper(SvgNode* node, float vx, float vy, } if (picture->load(href) != Result::Success) return nullptr; - picture->size(node->node.image.w, node->node.image.h); } float x, y, w, h; -- 2.7.4 From 175597203bf3ecf70f9bb5561f44edb4cda68eab Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 19 Jul 2021 12:06:47 +0900 Subject: [PATCH 16/16] bump up version 0.3.1 Change-Id: Id0aee760027f288fbfe547d974e4241aa500e40b --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index 9170ffd..f30540e 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.3.0 +Version: 0.3.1 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4