From c36f23e80d243946bed1010f3ef7b36b67fda080 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 9 Jun 2020 15:40:13 +0900 Subject: [PATCH] common gradient: implement linear/radial gradient interfaces. Change-Id: Ica9c54e662e73592d3fddcabed09b1605b3a5a4f --- .gitignore | 1 + inc/tizenvg.h | 101 ++++++++++++++++++++++++++++++++++----- src/lib/gl_engine/meson.build | 6 +-- src/lib/meson.build | 13 +++-- src/lib/tvgCanvasImpl.h | 8 ++-- src/lib/tvgCommon.h | 3 ++ src/lib/tvgFill.cpp | 88 ++++++++++++++++++++++++++++++++++ src/lib/tvgLinearGradient.cpp | 86 +++++++++++++++++++++++++++++++++ src/lib/tvgRadialGradient.cpp | 84 +++++++++++++++++++++++++++++++++ src/lib/tvgRenderCommon.h | 2 +- src/lib/tvgScene.cpp | 2 +- src/lib/tvgSceneImpl.h | 8 ++-- src/lib/tvgShape.cpp | 34 +++++++++++++- src/lib/tvgShapeImpl.h | 11 ++--- src/meson.build | 2 +- test/makefile | 1 + test/testLinearGradient.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++ 17 files changed, 517 insertions(+), 40 deletions(-) create mode 100644 src/lib/tvgFill.cpp create mode 100644 src/lib/tvgLinearGradient.cpp create mode 100644 src/lib/tvgRadialGradient.cpp create mode 100644 test/testLinearGradient.cpp diff --git a/.gitignore b/.gitignore index ba439cb..b9cdf24 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ testTransform testSceneTransform testStroke testStrokeLine +testLinearGradient diff --git a/inc/tizenvg.h b/inc/tizenvg.h index a2d245d..b089387 100644 --- a/inc/tizenvg.h +++ b/inc/tizenvg.h @@ -35,6 +35,7 @@ extern "C" { #endif + #define _TVG_DECLARE_PRIVATE(A) \ protected: \ struct Impl; \ @@ -43,16 +44,21 @@ protected: \ const A& operator=(const A&) = delete; \ A() -#define _TVG_DECLARE_ACCESSOR(A) \ - friend A - #define _TVG_DISABLE_CTOR(A) \ A() = delete; \ ~A() = delete -#define _TVG_DECALRE_IDENTIFIER(A) \ +#define _TVG_DECLARE_ACCESSOR(A) \ + friend A + +#define _TVG_DECLARE_ACCESSORS(A, B) \ + friend A; \ + friend B + +#define _TVG_DECALRE_IDENTIFIER() \ protected: \ - unsigned A##_Id + unsigned id + namespace tvg { @@ -93,9 +99,79 @@ public: virtual Result bounds(float* x, float* y, float* w, float* h) const = 0; - _TVG_DECALRE_IDENTIFIER(Paint); - _TVG_DECLARE_ACCESSOR(Scene); - _TVG_DECLARE_ACCESSOR(Canvas); + _TVG_DECALRE_IDENTIFIER(); + _TVG_DECLARE_ACCESSORS(Canvas, Scene); +}; + + +/** + * @class Fill + * + * @ingroup TizenVG + * + * @brief description... + * + */ +class TVG_EXPORT Fill +{ +public: + struct ColorStop + { + float pos; + uint8_t r, g, b, a; + }; + + virtual ~Fill(); + + Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept; + uint32_t colorStops(const ColorStop** colorStops) const noexcept; + + _TVG_DECALRE_IDENTIFIER(); + _TVG_DECLARE_PRIVATE(Fill); +}; + + +/** + * @class LinearGradient + * + * @ingroup TizenVG + * + * @brief description... + * + */ +class TVG_EXPORT LinearGradient final : public Fill +{ +public: + ~LinearGradient(); + + Result linear(float x1, float y1, float x2, float y2) noexcept; + Result linear(float* x1, float* y1, float* x2, float* y2) const noexcept; + + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(LinearGradient); +}; + + +/** + * @class RadialGradient + * + * @ingroup TizenVG + * + * @brief description... + * + */ +class TVG_EXPORT RadialGradient final : public Fill +{ +public: + ~RadialGradient(); + + Result radial(float cx, float cy, float radius) noexcept; + Result radial(float* cx, float* cy, float* radius) const noexcept; + + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(RadialGradient); }; @@ -161,6 +237,7 @@ public: //Fill Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept; + Result fill(std::unique_ptr f) noexcept; //Transform Result rotate(float degree) noexcept override; @@ -171,6 +248,7 @@ public: uint32_t pathCommands(const PathCommand** cmds) const noexcept; uint32_t pathCoords(const Point** pts) const noexcept; Result fill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept; + const Fill* fill() const noexcept; Result bounds(float* x, float* y, float* w, float* h) const noexcept override; float strokeWidth() const noexcept; @@ -181,9 +259,8 @@ public: static std::unique_ptr gen() noexcept; - _TVG_DECLARE_ACCESSOR(Scene); - _TVG_DECLARE_ACCESSOR(Canvas); _TVG_DECLARE_PRIVATE(Shape); + _TVG_DECLARE_ACCESSORS(Canvas, Scene); }; @@ -211,8 +288,8 @@ public: static std::unique_ptr gen() noexcept; - _TVG_DECLARE_PRIVATE(Scene); _TVG_DECLARE_ACCESSOR(Canvas); + _TVG_DECLARE_PRIVATE(Scene); }; @@ -231,6 +308,7 @@ public: Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept; Result sync() noexcept override; + static std::unique_ptr gen() noexcept; _TVG_DECLARE_PRIVATE(SwCanvas); @@ -254,6 +332,7 @@ public: Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept; Result sync() noexcept override; + static std::unique_ptr gen() noexcept; _TVG_DECLARE_PRIVATE(GlCanvas); diff --git a/src/lib/gl_engine/meson.build b/src/lib/gl_engine/meson.build index 41a25e0..5494f69 100644 --- a/src/lib/gl_engine/meson.build +++ b/src/lib/gl_engine/meson.build @@ -1,12 +1,12 @@ source_file = [ 'tvgGlCommon.h', + 'tvgGlGeometry.h', 'tvgGlGpuBuffer.h', 'tvgGlProgram.h', - 'tvgGlRenderer.cpp', 'tvgGlRenderer.h', 'tvgGlShader.h', - 'tvgGlGeometry.h', - ] + 'tvgGlRenderer.cpp', +] glraster_dep = declare_dependency( include_directories : include_directories('.'), diff --git a/src/lib/meson.build b/src/lib/meson.build index 0a56f0d..5aba9bb 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -2,18 +2,21 @@ subdir('sw_engine') subdir('gl_engine') source_file = [ + 'tvgCanvasImpl.h', 'tvgCommon.h', 'tvgRenderCommon.h', + 'tvgSceneImpl.h', 'tvgShapePath.h', 'tvgShapeImpl.h', - 'tvgCanvasImpl.h', - 'tvgSceneImpl.h', - 'tvgEngine.cpp', 'tvgCanvas.cpp', - 'tvgSwCanvas.cpp', + 'tvgEngine.cpp', + 'tvgFill.cpp', 'tvgGlCanvas.cpp', + 'tvgLinearGradient.cpp', + 'tvgRadialGradient.cpp', 'tvgScene.cpp', - 'tvgShape.cpp' + 'tvgShape.cpp', + 'tvgSwCanvas.cpp', ] src_dep = declare_dependency( diff --git a/src/lib/tvgCanvasImpl.h b/src/lib/tvgCanvasImpl.h index 078385a..c6dc073 100644 --- a/src/lib/tvgCanvasImpl.h +++ b/src/lib/tvgCanvasImpl.h @@ -53,7 +53,7 @@ struct Canvas::Impl assert(renderer); for (auto paint : paints) { - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if (!SCENE_IMPL->clear(*renderer)) return Result::InsufficientCondition; @@ -73,7 +73,7 @@ struct Canvas::Impl assert(renderer); for(auto paint: paints) { - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if (!SCENE_IMPL->update(*renderer, nullptr)) return Result::InsufficientCondition; @@ -89,7 +89,7 @@ struct Canvas::Impl { assert(renderer); - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if (!SCENE_IMPL->update(*renderer)) return Result::InsufficientCondition; @@ -108,7 +108,7 @@ struct Canvas::Impl if (!renderer->clear()) return Result::InsufficientCondition; for(auto paint: paints) { - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if(!SCENE_IMPL->render(*renderer)) return Result::InsufficientCondition; diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index ca18cca..49c3f96 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -34,6 +34,9 @@ using namespace tvg; #define PAINT_ID_SHAPE 0 #define PAINT_ID_SCENE 1 +#define FILL_ID_LINEAR 0 +#define FILL_ID_RADIAL 1 + #include "tvgRenderCommon.h" #include "tvgShapePath.h" #include "tvgShapeImpl.h" diff --git a/src/lib/tvgFill.cpp b/src/lib/tvgFill.cpp new file mode 100644 index 0000000..13001c8 --- /dev/null +++ b/src/lib/tvgFill.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _TVG_FILL_CPP_ +#define _TVG_FILL_CPP_ + +#include "tvgCommon.h" + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Fill::Impl +{ + ColorStop* colorStops = nullptr; + uint32_t cnt = 0; + + ~Impl() + { + if (colorStops) free(colorStops); + } +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Fill::Fill():pImpl(make_unique()) +{ +} + + +Fill::~Fill() +{ +} + + +Result Fill::colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept +{ + auto impl = pImpl.get(); + if (!impl) return Result::MemoryCorruption; + + if (cnt == 0) { + if (impl->colorStops) { + free(impl->colorStops); + impl->colorStops = nullptr; + impl->cnt = cnt; + } + return Result::Success; + } + + if (impl->cnt != cnt) { + impl->colorStops = static_cast(realloc(impl->colorStops, cnt * sizeof(ColorStop))); + } + + impl->cnt = cnt; + memcpy(impl->colorStops, colorStops, cnt * sizeof(ColorStop)); + + return Result::Success; +} + + +uint32_t Fill::colorStops(const ColorStop** colorStops) const noexcept +{ + auto impl = pImpl.get(); + if (!impl) return 0; + + if (colorStops) *colorStops = impl->colorStops; + + return impl->cnt; +} + +#endif /* _TVG_FILL_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgLinearGradient.cpp b/src/lib/tvgLinearGradient.cpp new file mode 100644 index 0000000..9ea803d --- /dev/null +++ b/src/lib/tvgLinearGradient.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _TVG_LINEAR_GRADIENT_CPP_ +#define _TVG_LINEAR_GRADIENT_CPP_ + +#include "tvgCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct LinearGradient::Impl +{ + float x1, y1, x2, y2; +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +LinearGradient::LinearGradient():pImpl(make_unique()) +{ + id = FILL_ID_LINEAR; +} + + +LinearGradient::~LinearGradient() +{ +} + + +Result LinearGradient::linear(float x1, float y1, float x2, float y2) noexcept +{ + if (fabsf(x2 - x1) < FLT_EPSILON && fabsf(y2 - y1) < FLT_EPSILON) + return Result::InvalidArguments; + + auto impl = pImpl.get(); + if (!impl) return Result::MemoryCorruption; + + impl->x1 = x1; + impl->y1 = y1; + impl->x2 = x2; + impl->y2 = y2; + + return Result::Success; +} + + +Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const noexcept +{ + auto impl = pImpl.get(); + if (!impl) return Result::MemoryCorruption; + + if (x1) *x1 = impl->x1; + if (x2) *x2 = impl->x2; + if (y1) *y1 = impl->y1; + if (y2) *y2 = impl->y2; + + return Result::Success; +} + + +unique_ptr LinearGradient::gen() noexcept +{ + auto fill = unique_ptr(new LinearGradient); + assert(fill); + + return fill; +} + +#endif /* _TVG_LINEAR_GRADIENT_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgRadialGradient.cpp b/src/lib/tvgRadialGradient.cpp new file mode 100644 index 0000000..2447e6f --- /dev/null +++ b/src/lib/tvgRadialGradient.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _TVG_RADIAL_GRADIENT_CPP_ +#define _TVG_RADIAL_GRADIENT_CPP_ + +#include "tvgCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct RadialGradient::Impl +{ + float cx, cy, radius; +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +RadialGradient::RadialGradient():pImpl(make_unique()) +{ + id = FILL_ID_RADIAL; +} + + +RadialGradient::~RadialGradient() +{ +} + + +Result RadialGradient::radial(float cx, float cy, float radius) noexcept +{ + if (radius < FLT_EPSILON) + return Result::InvalidArguments; + + auto impl = pImpl.get(); + if (!impl) return Result::MemoryCorruption; + + impl->cx = cx; + impl->cy = cy; + impl->radius = radius; + + return Result::Success; +} + + +Result RadialGradient::radial(float* cx, float* cy, float* radius) const noexcept +{ + auto impl = pImpl.get(); + if (!impl) return Result::MemoryCorruption; + + if (cx) *cx = impl->cx; + if (cy) *cy = impl->cy; + if (radius) *radius = impl->radius; + + return Result::Success; +} + + +unique_ptr RadialGradient::gen() noexcept +{ + auto fill = unique_ptr(new RadialGradient); + assert(fill); + + return fill; +} + +#endif /* _TVG_RADIAL_GRADIENT_CPP_ */ \ No newline at end of file diff --git a/src/lib/tvgRenderCommon.h b/src/lib/tvgRenderCommon.h index 0e98e17..f89d949 100644 --- a/src/lib/tvgRenderCommon.h +++ b/src/lib/tvgRenderCommon.h @@ -28,7 +28,7 @@ struct Surface uint32_t w, h; }; -enum RenderUpdateFlag {None = 0, Path = 1, Fill = 2, Stroke = 4, Transform = 8, All = 16}; +enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, All = 32}; struct RenderTransform { diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index a1c7a7f..ac2ae82 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -25,7 +25,7 @@ Scene::Scene() : pImpl(make_unique()) { - Paint_Id = PAINT_ID_SCENE; + id = PAINT_ID_SCENE; } diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 1f1fa14..8596292 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -39,7 +39,7 @@ struct Scene::Impl bool clear(RenderMethod& renderer) { for (auto paint : paints) { - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if (!SCENE_IMPL->clear(renderer)) return false; @@ -57,7 +57,7 @@ struct Scene::Impl bool updateInternal(RenderMethod &renderer, const RenderTransform* transform, uint32_t flag) { for(auto paint: paints) { - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if (!SCENE_IMPL->update(renderer, transform, flag)) return false; @@ -97,7 +97,7 @@ struct Scene::Impl bool render(RenderMethod &renderer) { for(auto paint: paints) { - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if(!SCENE_IMPL->render(renderer)) return false; @@ -122,7 +122,7 @@ struct Scene::Impl auto w2 = 0.0f; auto h2 = 0.0f; - if (paint->Paint_Id == PAINT_ID_SCENE) { + if (paint->id == PAINT_ID_SCENE) { //We know renderer type, avoid dynamic_cast for performance. auto scene = static_cast(paint); if (!SCENE_IMPL->bounds(&x2, &y2, &w2, &h2)) return false; diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 5119ac8..012fcb1 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -32,7 +32,7 @@ constexpr auto PATH_KAPPA = 0.552284f; Shape :: Shape() : pImpl(make_unique()) { - Paint_Id = PAINT_ID_SHAPE; + id = PAINT_ID_SHAPE; } @@ -226,7 +226,29 @@ Result Shape::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept impl->color[1] = g; impl->color[2] = b; impl->color[3] = a; - impl->flag |= RenderUpdateFlag::Fill; + impl->flag |= RenderUpdateFlag::Color; + + if (impl->fill) { + delete(impl->fill); + impl->fill = nullptr; + impl->flag |= RenderUpdateFlag::Gradient; + } + + return Result::Success; +} + + +Result Shape::fill(unique_ptr f) noexcept +{ + auto impl = pImpl.get(); + if (!impl) return Result::MemoryCorruption; + + auto p = f.release(); + if (!p) return Result::MemoryCorruption; + + if (impl->fill) delete(impl->fill); + impl->fill = p; + impl->flag |= RenderUpdateFlag::Gradient; return Result::Success; } @@ -245,6 +267,14 @@ Result Shape::fill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcep return Result::Success; } +const Fill* Shape::fill() const noexcept +{ + auto impl = pImpl.get(); + if (!impl) return nullptr; + + return impl->fill; +} + Result Shape::scale(float factor) noexcept { diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 08acb36..4cce022 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -23,11 +23,6 @@ /* Internal Class Implementation */ /************************************************************************/ -struct ShapeFill -{ -}; - - struct ShapeStroke { float width = 0; @@ -46,9 +41,9 @@ struct ShapeStroke struct Shape::Impl { - ShapeFill *fill = nullptr; - ShapeStroke *stroke = nullptr; ShapePath *path = nullptr; + Fill *fill = nullptr; + ShapeStroke *stroke = nullptr; RenderTransform *transform = nullptr; uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a uint32_t flag = RenderUpdateFlag::None; @@ -62,8 +57,8 @@ struct Shape::Impl ~Impl() { if (path) delete(path); - if (stroke) delete(stroke); if (fill) delete(fill); + if (stroke) delete(stroke); if (transform) delete(transform); } diff --git a/src/meson.build b/src/meson.build index aded001..a0ef37d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,4 @@ -compiler_flags = ['-DTIZENVG_BUILD'] +compiler_flags = ['-DTVG_BUILD'] subdir('lib') subdir('examples') diff --git a/test/makefile b/test/makefile index 2aba05d..353d7b8 100644 --- a/test/makefile +++ b/test/makefile @@ -12,3 +12,4 @@ all: gcc -o testSceneTransform testSceneTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg` gcc -o testStroke testStroke.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg` gcc -o testStrokeLine testStrokeLine.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg` + gcc -o testLinearGradient testLinearGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg` diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp new file mode 100644 index 0000000..4f87cad --- /dev/null +++ b/test/testLinearGradient.cpp @@ -0,0 +1,107 @@ +#include +#include + +using namespace std; + +#define WIDTH 800 +#define HEIGHT 800 + +static uint32_t buffer[WIDTH * HEIGHT]; + +void tvgtest() +{ + //Initialize TizenVG Engine + tvg::Engine::init(); + + //Create a Canvas + auto canvas = tvg::SwCanvas::gen(); + canvas->target(buffer, WIDTH, WIDTH, HEIGHT); + canvas->reserve(3); //reserve 3 shape nodes (optional) + + //Linear Gradient Color Stops + tvg::Fill::ColorStop colorStops[3]; + colorStops[0] = {0, 255, 0, 0, 255}; + colorStops[1] = {0.5, 255, 255, 255, 255}; + colorStops[2] = {1, 0, 0, 255, 255}; + + //Prepare Round Rectangle + auto shape1 = tvg::Shape::gen(); + shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius + shape1->stroke(255, 255, 255, 255); + shape1->stroke(2); + + //LinearGradient + auto fill = tvg::LinearGradient::gen(); + fill->linear(0, 0, 400, 400); + fill->colorStops(colorStops, 3); + + shape1->fill(move(fill)); + canvas->push(move(shape1)); + + + //Prepare Circle + auto shape2 = tvg::Shape::gen(); + shape2->appendCircle(400, 400, 200, 200); //cx, cy, radiusW, radiusH + shape2->stroke(255, 255, 255, 255); + shape2->stroke(2); + + //LinearGradient + auto fill2 = tvg::LinearGradient::gen(); + fill2->linear(400, 200, 400, 600); + fill2->colorStops(colorStops, 3); + + shape2->fill(move(fill2)); + canvas->push(move(shape2)); + + + //Prepare Ellipse + auto shape3 = tvg::Shape::gen(); + shape3->appendCircle(600, 600, 150, 100); //cx, cy, radiusW, radiusH + shape3->stroke(255, 255, 255, 255); + shape3->stroke(2); + + //LinearGradient + auto fill3 = tvg::LinearGradient::gen(); + fill3->linear(450, 600, 750, 600); + fill3->colorStops(colorStops, 3); + + shape3->fill(move(fill3)); + canvas->push(move(shape3)); + + //Draw the Shapes onto the Canvas + canvas->draw(); + canvas->sync(); + + //Terminate TizenVG Engine + tvg::Engine::term(); +} + +void +win_del(void *data, Evas_Object *o, void *ev) +{ + elm_exit(); +} + +int main(int argc, char **argv) +{ + tvgtest(); + + //Show the result using EFL... + elm_init(argc, argv); + + Eo* win = elm_win_util_standard_add(NULL, "TizenVG Test"); + evas_object_smart_callback_add(win, "delete,request", win_del, 0); + + Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); + evas_object_image_size_set(img, WIDTH, HEIGHT); + evas_object_image_data_set(img, buffer); + evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(img); + + elm_win_resize_object_add(win, img); + evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT); + evas_object_show(win); + + elm_run(); + elm_shutdown(); +} -- 2.7.4