mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
common gradient: implement linear/radial gradient interfaces.
Change-Id: Ica9c54e662e73592d3fddcabed09b1605b3a5a4f
This commit is contained in:
parent
c75cca5a13
commit
c36f23e80d
17 changed files with 517 additions and 40 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -14,3 +14,4 @@ testTransform
|
||||||
testSceneTransform
|
testSceneTransform
|
||||||
testStroke
|
testStroke
|
||||||
testStrokeLine
|
testStrokeLine
|
||||||
|
testLinearGradient
|
||||||
|
|
101
inc/tizenvg.h
101
inc/tizenvg.h
|
@ -35,6 +35,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define _TVG_DECLARE_PRIVATE(A) \
|
#define _TVG_DECLARE_PRIVATE(A) \
|
||||||
protected: \
|
protected: \
|
||||||
struct Impl; \
|
struct Impl; \
|
||||||
|
@ -43,16 +44,21 @@ protected: \
|
||||||
const A& operator=(const A&) = delete; \
|
const A& operator=(const A&) = delete; \
|
||||||
A()
|
A()
|
||||||
|
|
||||||
#define _TVG_DECLARE_ACCESSOR(A) \
|
|
||||||
friend A
|
|
||||||
|
|
||||||
#define _TVG_DISABLE_CTOR(A) \
|
#define _TVG_DISABLE_CTOR(A) \
|
||||||
A() = delete; \
|
A() = delete; \
|
||||||
~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: \
|
protected: \
|
||||||
unsigned A##_Id
|
unsigned id
|
||||||
|
|
||||||
|
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
@ -93,9 +99,79 @@ public:
|
||||||
|
|
||||||
virtual Result bounds(float* x, float* y, float* w, float* h) const = 0;
|
virtual Result bounds(float* x, float* y, float* w, float* h) const = 0;
|
||||||
|
|
||||||
_TVG_DECALRE_IDENTIFIER(Paint);
|
_TVG_DECALRE_IDENTIFIER();
|
||||||
_TVG_DECLARE_ACCESSOR(Scene);
|
_TVG_DECLARE_ACCESSORS(Canvas, Scene);
|
||||||
_TVG_DECLARE_ACCESSOR(Canvas);
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<LinearGradient> 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<RadialGradient> gen() noexcept;
|
||||||
|
|
||||||
|
_TVG_DECLARE_PRIVATE(RadialGradient);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,6 +237,7 @@ public:
|
||||||
|
|
||||||
//Fill
|
//Fill
|
||||||
Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
|
Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
|
||||||
|
Result fill(std::unique_ptr<Fill> f) noexcept;
|
||||||
|
|
||||||
//Transform
|
//Transform
|
||||||
Result rotate(float degree) noexcept override;
|
Result rotate(float degree) noexcept override;
|
||||||
|
@ -171,6 +248,7 @@ public:
|
||||||
uint32_t pathCommands(const PathCommand** cmds) const noexcept;
|
uint32_t pathCommands(const PathCommand** cmds) const noexcept;
|
||||||
uint32_t pathCoords(const Point** pts) 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;
|
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;
|
Result bounds(float* x, float* y, float* w, float* h) const noexcept override;
|
||||||
|
|
||||||
float strokeWidth() const noexcept;
|
float strokeWidth() const noexcept;
|
||||||
|
@ -181,9 +259,8 @@ public:
|
||||||
|
|
||||||
static std::unique_ptr<Shape> gen() noexcept;
|
static std::unique_ptr<Shape> gen() noexcept;
|
||||||
|
|
||||||
_TVG_DECLARE_ACCESSOR(Scene);
|
|
||||||
_TVG_DECLARE_ACCESSOR(Canvas);
|
|
||||||
_TVG_DECLARE_PRIVATE(Shape);
|
_TVG_DECLARE_PRIVATE(Shape);
|
||||||
|
_TVG_DECLARE_ACCESSORS(Canvas, Scene);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,8 +288,8 @@ public:
|
||||||
|
|
||||||
static std::unique_ptr<Scene> gen() noexcept;
|
static std::unique_ptr<Scene> gen() noexcept;
|
||||||
|
|
||||||
_TVG_DECLARE_PRIVATE(Scene);
|
|
||||||
_TVG_DECLARE_ACCESSOR(Canvas);
|
_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 target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
||||||
Result sync() noexcept override;
|
Result sync() noexcept override;
|
||||||
|
|
||||||
static std::unique_ptr<SwCanvas> gen() noexcept;
|
static std::unique_ptr<SwCanvas> gen() noexcept;
|
||||||
|
|
||||||
_TVG_DECLARE_PRIVATE(SwCanvas);
|
_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 target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
||||||
Result sync() noexcept override;
|
Result sync() noexcept override;
|
||||||
|
|
||||||
static std::unique_ptr<GlCanvas> gen() noexcept;
|
static std::unique_ptr<GlCanvas> gen() noexcept;
|
||||||
|
|
||||||
_TVG_DECLARE_PRIVATE(GlCanvas);
|
_TVG_DECLARE_PRIVATE(GlCanvas);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
source_file = [
|
source_file = [
|
||||||
'tvgGlCommon.h',
|
'tvgGlCommon.h',
|
||||||
|
'tvgGlGeometry.h',
|
||||||
'tvgGlGpuBuffer.h',
|
'tvgGlGpuBuffer.h',
|
||||||
'tvgGlProgram.h',
|
'tvgGlProgram.h',
|
||||||
'tvgGlRenderer.cpp',
|
|
||||||
'tvgGlRenderer.h',
|
'tvgGlRenderer.h',
|
||||||
'tvgGlShader.h',
|
'tvgGlShader.h',
|
||||||
'tvgGlGeometry.h',
|
'tvgGlRenderer.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
glraster_dep = declare_dependency(
|
glraster_dep = declare_dependency(
|
||||||
include_directories : include_directories('.'),
|
include_directories : include_directories('.'),
|
||||||
|
|
|
@ -2,18 +2,21 @@ subdir('sw_engine')
|
||||||
subdir('gl_engine')
|
subdir('gl_engine')
|
||||||
|
|
||||||
source_file = [
|
source_file = [
|
||||||
|
'tvgCanvasImpl.h',
|
||||||
'tvgCommon.h',
|
'tvgCommon.h',
|
||||||
'tvgRenderCommon.h',
|
'tvgRenderCommon.h',
|
||||||
|
'tvgSceneImpl.h',
|
||||||
'tvgShapePath.h',
|
'tvgShapePath.h',
|
||||||
'tvgShapeImpl.h',
|
'tvgShapeImpl.h',
|
||||||
'tvgCanvasImpl.h',
|
|
||||||
'tvgSceneImpl.h',
|
|
||||||
'tvgEngine.cpp',
|
|
||||||
'tvgCanvas.cpp',
|
'tvgCanvas.cpp',
|
||||||
'tvgSwCanvas.cpp',
|
'tvgEngine.cpp',
|
||||||
|
'tvgFill.cpp',
|
||||||
'tvgGlCanvas.cpp',
|
'tvgGlCanvas.cpp',
|
||||||
|
'tvgLinearGradient.cpp',
|
||||||
|
'tvgRadialGradient.cpp',
|
||||||
'tvgScene.cpp',
|
'tvgScene.cpp',
|
||||||
'tvgShape.cpp'
|
'tvgShape.cpp',
|
||||||
|
'tvgSwCanvas.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
src_dep = declare_dependency(
|
src_dep = declare_dependency(
|
||||||
|
|
|
@ -53,7 +53,7 @@ struct Canvas::Impl
|
||||||
assert(renderer);
|
assert(renderer);
|
||||||
|
|
||||||
for (auto paint : paints) {
|
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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if (!SCENE_IMPL->clear(*renderer)) return Result::InsufficientCondition;
|
if (!SCENE_IMPL->clear(*renderer)) return Result::InsufficientCondition;
|
||||||
|
@ -73,7 +73,7 @@ struct Canvas::Impl
|
||||||
assert(renderer);
|
assert(renderer);
|
||||||
|
|
||||||
for(auto paint: paints) {
|
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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if (!SCENE_IMPL->update(*renderer, nullptr)) return Result::InsufficientCondition;
|
if (!SCENE_IMPL->update(*renderer, nullptr)) return Result::InsufficientCondition;
|
||||||
|
@ -89,7 +89,7 @@ struct Canvas::Impl
|
||||||
{
|
{
|
||||||
assert(renderer);
|
assert(renderer);
|
||||||
|
|
||||||
if (paint->Paint_Id == PAINT_ID_SCENE) {
|
if (paint->id == PAINT_ID_SCENE) {
|
||||||
//We know renderer type, avoid dynamic_cast for performance.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if (!SCENE_IMPL->update(*renderer)) return Result::InsufficientCondition;
|
if (!SCENE_IMPL->update(*renderer)) return Result::InsufficientCondition;
|
||||||
|
@ -108,7 +108,7 @@ struct Canvas::Impl
|
||||||
if (!renderer->clear()) return Result::InsufficientCondition;
|
if (!renderer->clear()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
for(auto paint: paints) {
|
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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if(!SCENE_IMPL->render(*renderer)) return Result::InsufficientCondition;
|
if(!SCENE_IMPL->render(*renderer)) return Result::InsufficientCondition;
|
||||||
|
|
|
@ -34,6 +34,9 @@ using namespace tvg;
|
||||||
#define PAINT_ID_SHAPE 0
|
#define PAINT_ID_SHAPE 0
|
||||||
#define PAINT_ID_SCENE 1
|
#define PAINT_ID_SCENE 1
|
||||||
|
|
||||||
|
#define FILL_ID_LINEAR 0
|
||||||
|
#define FILL_ID_RADIAL 1
|
||||||
|
|
||||||
#include "tvgRenderCommon.h"
|
#include "tvgRenderCommon.h"
|
||||||
#include "tvgShapePath.h"
|
#include "tvgShapePath.h"
|
||||||
#include "tvgShapeImpl.h"
|
#include "tvgShapeImpl.h"
|
||||||
|
|
88
src/lib/tvgFill.cpp
Normal file
88
src/lib/tvgFill.cpp
Normal file
|
@ -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<Impl>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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<ColorStop*>(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_ */
|
86
src/lib/tvgLinearGradient.cpp
Normal file
86
src/lib/tvgLinearGradient.cpp
Normal file
|
@ -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<Impl>())
|
||||||
|
{
|
||||||
|
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> LinearGradient::gen() noexcept
|
||||||
|
{
|
||||||
|
auto fill = unique_ptr<LinearGradient>(new LinearGradient);
|
||||||
|
assert(fill);
|
||||||
|
|
||||||
|
return fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _TVG_LINEAR_GRADIENT_CPP_ */
|
84
src/lib/tvgRadialGradient.cpp
Normal file
84
src/lib/tvgRadialGradient.cpp
Normal file
|
@ -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<Impl>())
|
||||||
|
{
|
||||||
|
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> RadialGradient::gen() noexcept
|
||||||
|
{
|
||||||
|
auto fill = unique_ptr<RadialGradient>(new RadialGradient);
|
||||||
|
assert(fill);
|
||||||
|
|
||||||
|
return fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _TVG_RADIAL_GRADIENT_CPP_ */
|
|
@ -28,7 +28,7 @@ struct Surface
|
||||||
uint32_t w, h;
|
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
|
struct RenderTransform
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
Scene::Scene() : pImpl(make_unique<Impl>())
|
Scene::Scene() : pImpl(make_unique<Impl>())
|
||||||
{
|
{
|
||||||
Paint_Id = PAINT_ID_SCENE;
|
id = PAINT_ID_SCENE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct Scene::Impl
|
||||||
bool clear(RenderMethod& renderer)
|
bool clear(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
for (auto paint : paints) {
|
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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if (!SCENE_IMPL->clear(renderer)) return false;
|
if (!SCENE_IMPL->clear(renderer)) return false;
|
||||||
|
@ -57,7 +57,7 @@ struct Scene::Impl
|
||||||
bool updateInternal(RenderMethod &renderer, const RenderTransform* transform, uint32_t flag)
|
bool updateInternal(RenderMethod &renderer, const RenderTransform* transform, uint32_t flag)
|
||||||
{
|
{
|
||||||
for(auto paint: paints) {
|
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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if (!SCENE_IMPL->update(renderer, transform, flag)) return false;
|
if (!SCENE_IMPL->update(renderer, transform, flag)) return false;
|
||||||
|
@ -97,7 +97,7 @@ struct Scene::Impl
|
||||||
bool render(RenderMethod &renderer)
|
bool render(RenderMethod &renderer)
|
||||||
{
|
{
|
||||||
for(auto paint: paints) {
|
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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if(!SCENE_IMPL->render(renderer)) return false;
|
if(!SCENE_IMPL->render(renderer)) return false;
|
||||||
|
@ -122,7 +122,7 @@ struct Scene::Impl
|
||||||
auto w2 = 0.0f;
|
auto w2 = 0.0f;
|
||||||
auto h2 = 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.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
if (!SCENE_IMPL->bounds(&x2, &y2, &w2, &h2)) return false;
|
if (!SCENE_IMPL->bounds(&x2, &y2, &w2, &h2)) return false;
|
||||||
|
|
|
@ -32,7 +32,7 @@ constexpr auto PATH_KAPPA = 0.552284f;
|
||||||
|
|
||||||
Shape :: Shape() : pImpl(make_unique<Impl>())
|
Shape :: Shape() : pImpl(make_unique<Impl>())
|
||||||
{
|
{
|
||||||
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[1] = g;
|
||||||
impl->color[2] = b;
|
impl->color[2] = b;
|
||||||
impl->color[3] = a;
|
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<Fill> 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;
|
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;
|
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
|
Result Shape::scale(float factor) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,11 +23,6 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
struct ShapeFill
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ShapeStroke
|
struct ShapeStroke
|
||||||
{
|
{
|
||||||
float width = 0;
|
float width = 0;
|
||||||
|
@ -46,9 +41,9 @@ struct ShapeStroke
|
||||||
|
|
||||||
struct Shape::Impl
|
struct Shape::Impl
|
||||||
{
|
{
|
||||||
ShapeFill *fill = nullptr;
|
|
||||||
ShapeStroke *stroke = nullptr;
|
|
||||||
ShapePath *path = nullptr;
|
ShapePath *path = nullptr;
|
||||||
|
Fill *fill = nullptr;
|
||||||
|
ShapeStroke *stroke = nullptr;
|
||||||
RenderTransform *transform = nullptr;
|
RenderTransform *transform = nullptr;
|
||||||
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
|
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
|
||||||
uint32_t flag = RenderUpdateFlag::None;
|
uint32_t flag = RenderUpdateFlag::None;
|
||||||
|
@ -62,8 +57,8 @@ struct Shape::Impl
|
||||||
~Impl()
|
~Impl()
|
||||||
{
|
{
|
||||||
if (path) delete(path);
|
if (path) delete(path);
|
||||||
if (stroke) delete(stroke);
|
|
||||||
if (fill) delete(fill);
|
if (fill) delete(fill);
|
||||||
|
if (stroke) delete(stroke);
|
||||||
if (transform) delete(transform);
|
if (transform) delete(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
compiler_flags = ['-DTIZENVG_BUILD']
|
compiler_flags = ['-DTVG_BUILD']
|
||||||
|
|
||||||
subdir('lib')
|
subdir('lib')
|
||||||
subdir('examples')
|
subdir('examples')
|
||||||
|
|
|
@ -12,3 +12,4 @@ all:
|
||||||
gcc -o testSceneTransform testSceneTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
|
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 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 testStrokeLine testStrokeLine.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
|
||||||
|
gcc -o testLinearGradient testLinearGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
|
||||||
|
|
107
test/testLinearGradient.cpp
Normal file
107
test/testLinearGradient.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#include <tizenvg.h>
|
||||||
|
#include <Elementary.h>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue