mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
shape: added duplicate api.
Changes: 1. New shape->duplicate(Shape) api. 2. New example: testDuplicate 3. Added capi binding for duploicate api 4. Added capi duplication test in testCapi.c Description: Added implementation of duplicate api. For now it supports stroke properties and shape properties (fill color, path) duplication. TODO: Implement gradient properties duplication
This commit is contained in:
parent
be93b17563
commit
538db6e881
13 changed files with 242 additions and 8 deletions
|
@ -92,6 +92,8 @@ public:
|
|||
Result transform(const Matrix& m) noexcept;
|
||||
Result bounds(float* x, float* y, float* w, float* h) const noexcept;
|
||||
|
||||
virtual std::unique_ptr<Paint> duplicate() const noexcept = 0;
|
||||
|
||||
_TVG_DECLARE_ACCESSOR();
|
||||
_TVG_DECLARE_PRIVATE(Paint);
|
||||
};
|
||||
|
@ -248,6 +250,7 @@ public:
|
|||
StrokeJoin strokeJoin() const noexcept;
|
||||
|
||||
static std::unique_ptr<Shape> gen() noexcept;
|
||||
std::unique_ptr<Paint> duplicate() const noexcept override;
|
||||
|
||||
_TVG_DECLARE_PRIVATE(Shape);
|
||||
};
|
||||
|
@ -271,6 +274,7 @@ public:
|
|||
Result viewbox(float* x, float* y, float* w, float* h) const noexcept;
|
||||
|
||||
static std::unique_ptr<Picture> gen() noexcept;
|
||||
std::unique_ptr<Paint> duplicate() const noexcept override;
|
||||
|
||||
_TVG_DECLARE_PRIVATE(Picture);
|
||||
};
|
||||
|
@ -293,6 +297,7 @@ public:
|
|||
Result reserve(uint32_t size) noexcept;
|
||||
|
||||
static std::unique_ptr<Scene> gen() noexcept;
|
||||
std::unique_ptr<Paint> duplicate() const noexcept override;
|
||||
|
||||
_TVG_DECLARE_PRIVATE(Scene);
|
||||
};
|
||||
|
|
|
@ -120,7 +120,7 @@ TVG_EXPORT Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor);
|
|||
TVG_EXPORT Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree);
|
||||
TVG_EXPORT Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y);
|
||||
TVG_EXPORT Tvg_Result tvg_paint_transform(Tvg_Paint* paint, const Tvg_Matrix* m);
|
||||
|
||||
TVG_EXPORT Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint);
|
||||
|
||||
/************************************************************************/
|
||||
/* Shape API */
|
||||
|
|
|
@ -177,6 +177,14 @@ TVG_EXPORT Tvg_Result tvg_paint_transform(Tvg_Paint* paint, const Tvg_Matrix* m)
|
|||
}
|
||||
|
||||
|
||||
|
||||
TVG_EXPORT Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint)
|
||||
{
|
||||
if (!paint) return NULL;
|
||||
return (Tvg_Paint*) reinterpret_cast<Paint*>(paint)->duplicate().release();
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Shape API */
|
||||
/************************************************************************/
|
||||
|
|
|
@ -63,3 +63,10 @@ Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept
|
|||
if (IMPL->viewbox(x, y, w, h)) return Result::Success;
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Paint> Picture::duplicate() const noexcept
|
||||
{
|
||||
//TODO: implement
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -58,3 +58,10 @@ Result Scene::reserve(uint32_t size) noexcept
|
|||
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Paint> Scene::duplicate() const noexcept
|
||||
{
|
||||
//TODO: implement
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,14 @@ unique_ptr<Shape> Shape::gen() noexcept
|
|||
}
|
||||
|
||||
|
||||
unique_ptr<Paint> Shape::duplicate() const noexcept
|
||||
{
|
||||
auto shape = Shape::gen();
|
||||
shape->pImpl->duplicate(IMPL);
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
||||
Result Shape::reset() noexcept
|
||||
{
|
||||
IMPL->path->reset();
|
||||
|
|
|
@ -162,6 +162,46 @@ struct Shape::Impl
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void duplicate(Shape::Impl *s)
|
||||
{
|
||||
if (memcmp(color, s->color, sizeof(color))) {
|
||||
memcpy(color, s->color, sizeof(color));
|
||||
flag = RenderUpdateFlag::Color;
|
||||
}
|
||||
|
||||
if (s->path) {
|
||||
path = new ShapePath();
|
||||
|
||||
path->cmdCnt = s->path->cmdCnt;
|
||||
path->ptsCnt = s->path->ptsCnt;
|
||||
path->reservedCmdCnt = s->path->reservedCmdCnt;
|
||||
path->reservedPtsCnt = s->path->reservedPtsCnt;
|
||||
|
||||
path->cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * path->reservedCmdCnt));
|
||||
path->pts = static_cast<Point*>(malloc(sizeof(Point) * path->reservedPtsCnt));
|
||||
|
||||
memcpy(path->cmds, s->path->cmds, sizeof(PathCommand) * s->path->cmdCnt);
|
||||
memcpy(path->pts, s->path->pts, sizeof(Point) * s->path->ptsCnt);
|
||||
|
||||
flag = RenderUpdateFlag::Path;
|
||||
}
|
||||
|
||||
if (s->stroke) {
|
||||
stroke = new ShapeStroke();
|
||||
strokeCap(s->stroke->cap);
|
||||
strokeColor(s->stroke->color[0], s->stroke->color[1],
|
||||
s->stroke->color[2], s->stroke->color[3]);
|
||||
strokeJoin(s->stroke->join);
|
||||
strokeWidth(s->stroke->width);
|
||||
|
||||
if (s->stroke->dashPattern && s->stroke->dashCnt > 0) {
|
||||
strokeDash(s->stroke->dashPattern, s->stroke->dashCnt);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: add fill
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_TVG_SHAPE_IMPL_H_
|
|
@ -38,7 +38,6 @@ struct ShapePath
|
|||
uint32_t ptsCnt = 0;
|
||||
uint32_t reservedPtsCnt = 0;
|
||||
|
||||
|
||||
~ShapePath()
|
||||
{
|
||||
if (cmds) free(cmds);
|
||||
|
|
|
@ -21,4 +21,5 @@ all:
|
|||
gcc -o testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testArc testArc.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testMultiCanvas testMultiCanvas.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testDuplicate testDuplicate.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testCapi testCapi.c -g `pkg-config --cflags --libs elementary thorvg`
|
||||
|
|
|
@ -136,6 +136,17 @@ void testCapi()
|
|||
printf("(%.2lf, %.2lf)\n", pts[i].x, pts[i].y);
|
||||
}
|
||||
|
||||
//Origin paint for duplicated
|
||||
Tvg_Paint* org = tvg_shape_new();
|
||||
tvg_shape_append_rect(org, 550, 10, 100, 100, 0, 0);
|
||||
tvg_shape_set_stroke_width(org, 3);
|
||||
tvg_shape_set_stroke_color(org, 255, 0, 0, 255);
|
||||
tvg_shape_set_fill_color(org, 0, 255, 0, 255);
|
||||
|
||||
//Duplicated paint test - should copy rectangle parameters from origin
|
||||
Tvg_Paint* dup = tvg_paint_duplicate(org);
|
||||
tvg_canvas_push(canvas, dup);
|
||||
|
||||
tvg_canvas_draw(canvas);
|
||||
tvg_canvas_sync(canvas);
|
||||
|
||||
|
|
148
test/testDuplicate.cpp
Normal file
148
test/testDuplicate.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "testCommon.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* Drawing Commands */
|
||||
/************************************************************************/
|
||||
|
||||
void tvgDrawCmds(tvg::Canvas* canvas)
|
||||
{
|
||||
if (!canvas) return;
|
||||
|
||||
//Prepare first shape, which will not be drawn
|
||||
auto shape1 = tvg::Shape::gen();
|
||||
shape1->appendRect(10, 10, 200, 200, 0, 0);
|
||||
shape1->appendRect(220, 10, 100, 100, 0, 0);
|
||||
|
||||
shape1->stroke(3);
|
||||
shape1->stroke(0, 255, 0, 255);
|
||||
|
||||
float dashPattern[2] = {4, 4};
|
||||
shape1->stroke(dashPattern, 2);
|
||||
shape1->fill(255, 0, 0, 255);
|
||||
|
||||
//Create second shape and duplicate parameters
|
||||
auto shape2 = shape1->duplicate();
|
||||
|
||||
//Create third shape, duplicate from first and add some new parameters
|
||||
auto shape3 = shape1->duplicate();
|
||||
|
||||
//Get access to valid derived class type
|
||||
tvg::Shape* shapePtr = reinterpret_cast<tvg::Shape*>(shape3.get());
|
||||
|
||||
//move shape3 to new postion to don't cover second shape
|
||||
shape3->translate(0, 220);
|
||||
|
||||
//append new paths
|
||||
shapePtr->appendRect(340, 10, 100, 100, 0, 0);
|
||||
shapePtr->fill(0, 0, 255, 255);
|
||||
|
||||
//TODO: test gradient
|
||||
canvas->push(move(shape2));
|
||||
canvas->push(move(shape3));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Sw Engine Test Code */
|
||||
/************************************************************************/
|
||||
|
||||
static unique_ptr<tvg::SwCanvas> swCanvas;
|
||||
|
||||
void tvgSwTest(uint32_t* buffer)
|
||||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
internal data asynchronously for coming rendering.
|
||||
Canvas keeps this shape node unless user call canvas->clear() */
|
||||
tvgDrawCmds(swCanvas.get());
|
||||
}
|
||||
|
||||
void drawSwView(void* data, Eo* obj)
|
||||
{
|
||||
if (swCanvas->draw() == tvg::Result::Success) {
|
||||
swCanvas->sync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* GL Engine Test Code */
|
||||
/************************************************************************/
|
||||
|
||||
static unique_ptr<tvg::GlCanvas> glCanvas;
|
||||
|
||||
void initGLview(Evas_Object *obj)
|
||||
{
|
||||
static constexpr auto BPP = 4;
|
||||
|
||||
//Create a Canvas
|
||||
glCanvas = tvg::GlCanvas::gen();
|
||||
glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
internal data asynchronously for coming rendering.
|
||||
Canvas keeps this shape node unless user call canvas->clear() */
|
||||
tvgDrawCmds(glCanvas.get());
|
||||
}
|
||||
|
||||
void drawGLview(Evas_Object *obj)
|
||||
{
|
||||
auto gl = elm_glview_gl_api_get(obj);
|
||||
gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
gl->glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (glCanvas->draw() == tvg::Result::Success) {
|
||||
glCanvas->sync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Main Code */
|
||||
/************************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl;
|
||||
}
|
||||
|
||||
//Initialize ThorVG Engine
|
||||
if (tvgEngine == tvg::CanvasEngine::Sw) {
|
||||
cout << "tvg engine: software" << endl;
|
||||
} else {
|
||||
cout << "tvg engine: opengl" << endl;
|
||||
}
|
||||
|
||||
//Threads Count
|
||||
auto threads = std::thread::hardware_concurrency();
|
||||
|
||||
//Initialize ThorVG Engine
|
||||
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||
|
||||
elm_init(argc, argv);
|
||||
|
||||
if (tvgEngine == tvg::CanvasEngine::Sw) {
|
||||
createSwView();
|
||||
} else {
|
||||
createGlView();
|
||||
}
|
||||
|
||||
elm_run();
|
||||
elm_shutdown();
|
||||
|
||||
//Terminate ThorVG Engine
|
||||
tvg::Initializer::term(tvgEngine);
|
||||
|
||||
} else {
|
||||
cout << "engine is not supported" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue