enum class TVG_EXPORT StrokeCap { Square = 0, Round, Butt };
enum class TVG_EXPORT StrokeJoin { Bevel = 0, Round, Miter };
enum class TVG_EXPORT FillSpread { Pad = 0, Reflect, Repeat };
+enum class TVG_EXPORT CompMethod { None = 0, ClipPath };
enum class TVG_EXPORT CanvasEngine { Sw = (1 << 1), Gl = (1 << 2)};
Result bounds(float* x, float* y, float* w, float* h) const noexcept;
Paint* duplicate() const noexcept;
+ Result composite(std::unique_ptr<Paint> target, CompMethod method) const noexcept;
+
_TVG_DECLARE_ACCESSOR();
_TVG_DECLARE_PRIVATE(Paint);
};
'testSvg.cpp',
'testTransform.cpp',
'testUpdate.cpp',
+ 'testClipPath.cpp',
]
foreach current_file : source_file
--- /dev/null
+#include "testCommon.h"
+
+/************************************************************************/
+/* Drawing Commands */
+/************************************************************************/
+
+void tvgDrawStar(tvg::Shape* star)
+{
+ star->moveTo(199, 34);
+ star->lineTo(253, 143);
+ star->lineTo(374, 160);
+ star->lineTo(287, 244);
+ star->lineTo(307, 365);
+ star->lineTo(199, 309);
+ star->lineTo(97, 365);
+ star->lineTo(112, 245);
+ star->lineTo(26, 161);
+ star->lineTo(146, 143);
+ star->close();
+}
+
+void tvgDrawCmds(tvg::Canvas* canvas)
+{
+ if (!canvas) return;
+ //Background
+ auto shape = tvg::Shape::gen();
+ shape->appendRect(0, 0, WIDTH, HEIGHT, 0, 0);
+ shape->fill(255, 255, 255, 255);
+ if (canvas->push(move(shape)) != tvg::Result::Success) return;
+
+ //////////////////////////////////////////////
+ auto scene = tvg::Scene::gen();
+ scene->reserve(2);
+
+ auto star1 = tvg::Shape::gen();
+ tvgDrawStar(star1.get());
+ star1->fill(255, 255, 0, 255);
+ star1->stroke(255 ,0, 0, 128);
+ star1->stroke(10);
+
+ //Move Star1
+ star1->translate(-10, -10);
+
+ auto clipStar = tvg::Shape::gen();
+ clipStar->appendCircle(200, 230, 110, 110);
+ clipStar->fill(255, 255, 255, 255); // clip object must have alpha.
+ clipStar->translate(10, 10);
+
+ star1->composite(move(clipStar), tvg::CompMethod::ClipPath);
+
+ auto star2 = tvg::Shape::gen();
+ tvgDrawStar(star2.get());
+ star2->fill(0, 255, 255, 64);
+ star2->stroke(0 ,255, 0, 128);
+ star2->stroke(10);
+
+ //Move Star2
+ star2->translate(10, 40);
+
+ auto clip = tvg::Shape::gen();
+ clip->appendCircle(200, 230, 130, 130);
+ clip->fill(255, 255, 255, 255); // clip object must have alpha.
+ clip->translate(10, 10);
+
+ scene->push(move(star1));
+ scene->push(move(star2));
+
+ //Clipping scene to shape
+ scene->composite(move(clip), tvg::CompMethod::ClipPath);
+
+ canvas->push(move(scene));
+
+ //////////////////////////////////////////////
+ auto star3 = tvg::Shape::gen();
+ tvgDrawStar(star3.get());
+ star3->translate(400, 0);
+ star3->fill(255, 255, 0, 255); //r, g, b, a
+ star3->stroke(255 ,0, 0, 128);
+ star3->stroke(10);
+
+ auto clipRect = tvg::Shape::gen();
+ clipRect->appendRect(480, 110, 200, 200, 0, 0); //x, y, w, h, rx, ry
+ clipRect->fill(255, 255, 255, 255); // clip object must have alpha.
+ clipRect->translate(20, 20);
+
+ //Clipping scene to rect(shape)
+ star3->composite(move(clipRect), tvg::CompMethod::ClipPath);
+
+ canvas->push(move(star3));
+
+ //////////////////////////////////////////////
+ auto picture = tvg::Picture::gen();
+ char buf[PATH_MAX];
+ sprintf(buf,"%s/cartman.svg", EXAMPLE_DIR);
+
+ if (picture->load(buf) != tvg::Result::Success) return;
+
+ picture->scale(3);
+ picture->translate(200, 400);
+
+ auto clipPath = tvg::Shape::gen();
+ clipPath->appendCircle(350, 510, 110, 110); //x, y, w, h, rx, ry
+ clipPath->appendCircle(350, 650, 50, 50); //x, y, w, h, rx, ry
+ clipPath->fill(255, 255, 255, 255); // clip object must have alpha.
+ clipPath->translate(20, 20);
+
+ //Clipping picture to path
+ picture->composite(move(clipPath), tvg::CompMethod::ClipPath);
+
+ canvas->push(move(picture));
+}
+
+
+/************************************************************************/
+/* Sw Engine Test Code */
+/************************************************************************/
+
+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;
+}
}
-void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const RenderTransform* transform, RenderUpdateFlag flags)
+void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const RenderTransform* transform, vector<Composite>& compList, RenderUpdateFlag flags)
{
//prepare shape data
GlShape* sdata = static_cast<GlShape*>(data);
public:
Surface surface = {nullptr, 0, 0, 0};
- void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
+ void* prepare(const Shape& shape, void* data, const RenderTransform* transform, vector<Composite>& compList, RenderUpdateFlag flags) override;
bool dispose(const Shape& shape, void *data) override;
bool preRender() override;
bool render(const Shape& shape, void *data) override;
void shapeReset(SwShape* shape);
bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform);
bool shapePrepare(SwShape* shape, const Shape* sdata, const SwSize& clip, const Matrix* transform);
-bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias);
+bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite);
void shapeDelOutline(SwShape* shape);
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip);
SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias);
void rleFree(SwRleData* rle);
+void rleClipPath(SwRleData *rle, const SwRleData *clip);
+void rleClipRect(SwRleData *rle, const SwBBox* clip);
+
bool rasterCompositor(SwSurface* surface);
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
Matrix* transform = nullptr;
SwSurface* surface = nullptr;
RenderUpdateFlag flags = RenderUpdateFlag::None;
+ vector<Composite> compList;
void run() override
{
if (!shapePrepare(&shape, sdata, clip, transform)) return;
if (renderShape) {
auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true;
- if (!shapeGenRle(&shape, sdata, clip, antiAlias)) return;
+ if (!shapeGenRle(&shape, sdata, clip, antiAlias, compList.size() > 0 ? true : false)) return;
}
}
}
+
//Fill
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
auto fill = sdata->fill();
shapeDelStroke(&shape);
}
}
+
+ //Composite clip-path
+ for (auto comp : compList) {
+ SwShape *compShape = &static_cast<SwTask*>(comp.edata)->shape;
+ if (comp.method == CompMethod::ClipPath) {
+ //Clip to fill(path) rle
+ if (shape.rle && compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
+ else if (shape.rle && compShape->rle) rleClipPath(shape.rle, compShape->rle);
+
+ //Clip to stroke rle
+ if (shape.strokeRle && compShape->rect) rleClipRect(shape.strokeRle, &compShape->bbox);
+ else if (shape.strokeRle && compShape->rle) rleClipPath(shape.strokeRle, compShape->rle);
+ }
+ }
shapeDelOutline(&shape);
}
};
}
-void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
+void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, vector<Composite>& compList, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwTask*>(data);
if (flags == RenderUpdateFlag::None || task->valid()) return task;
task->sdata = &sdata;
+ if (compList.size() > 0) {
+ for (auto comp : compList) static_cast<SwTask*>(comp.edata)->get();
+ task->compList.assign(compList.begin(), compList.end());
+ }
if (transform) {
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
class SwRenderer : public RenderMethod
{
public:
- void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
+ void* prepare(const Shape& shape, void* data, const RenderTransform* transform, vector<Composite>& compList, RenderUpdateFlag flags) override;
bool dispose(const Shape& shape, void *data) override;
bool preRender() override;
bool postRender() override;
}
+SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
+{
+ auto out = outSpans;
+ auto spans = targetRle->spans;
+ auto end = targetRle->spans + targetRle->size;
+ auto clipSpans = clip->spans;
+ auto clipEnd = clip->spans + clip->size;
+
+ while (spanCnt && spans < end ) {
+ if (clipSpans > clipEnd) {
+ spans = end;
+ break;
+ }
+ if (clipSpans->y > spans->y) {
+ ++spans;
+ continue;
+ }
+ if (spans->y != clipSpans->y) {
+ ++clipSpans;
+ continue;
+ }
+ auto sx1 = spans->x;
+ auto sx2 = sx1 + spans->len;
+ auto cx1 = clipSpans->x;
+ auto cx2 = cx1 + clipSpans->len;
+
+ if (cx1 < sx1 && cx2 < sx1) {
+ ++clipSpans;
+ continue;
+ }
+ else if (sx1 < cx1 && sx2 < cx1) {
+ ++spans;
+ continue;
+ }
+ auto x = sx1 > cx1 ? sx1 : cx1;
+ auto len = (sx2 < cx2 ? sx2 : cx2) - x;
+ if (len) {
+ auto spansCorverage = spans->coverage;
+ auto clipSpansCoverage = clipSpans->coverage;
+ out->x = sx1 > cx1 ? sx1 : cx1;
+ out->len = (sx2 < cx2 ? sx2 : cx2) - out->x;
+ out->y = spans->y;
+ out->coverage = (uint8_t)((spansCorverage * clipSpansCoverage) >> 8);
+ ++out;
+ --spanCnt;
+ }
+ if (sx2 < cx2) ++spans;
+ else ++clipSpans;
+ }
+ return out;
+}
+
+SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
+{
+ auto out = outSpans;
+ auto spans = targetRle->spans;
+ auto end = targetRle->spans + targetRle->size;
+ auto minx = static_cast<int16_t>(bbox->min.x);
+ auto miny = static_cast<int16_t>(bbox->min.y);
+ auto maxx = minx + static_cast<int16_t>(bbox->max.x - bbox->min.x) - 1;
+ auto maxy = miny + static_cast<int16_t>(bbox->max.y - bbox->min.y) - 1;
+
+ while (spanCnt && spans < end ) {
+ if (spans->y > maxy) {
+ spans = end;
+ break;
+ }
+ if (spans->y < miny || spans->x > maxx || spans->x + spans->len <= minx) {
+ ++spans;
+ continue;
+ }
+ if (spans->x < minx) {
+ out->len = (spans->len - (minx - spans->x)) < (maxx - minx + 1) ? (spans->len - (minx - spans->x)) : (maxx - minx + 1);
+ out->x = minx;
+ }
+ else {
+ out->x = spans->x;
+ out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1);
+ }
+ if (out->len != 0) {
+ out->y = spans->y;
+ out->coverage = spans->coverage;
+ ++out;
+ }
+ ++spans;
+ --spanCnt;
+ }
+ return out;
+}
/************************************************************************/
/* External Class Implementation */
if (!rle) return;
if (rle->spans) free(rle->spans);
free(rle);
-}
\ No newline at end of file
+}
+
+void updateRleSpans(SwRleData *rle, SwSpan* curSpans, uint32_t size)
+{
+ if (!rle->spans || !curSpans || size == 0) return;
+ rle->size = size;
+ rle->spans = static_cast<SwSpan*>(realloc(rle->spans, rle->size * sizeof(SwSpan)));
+
+ if (!rle->spans) return;
+
+ for (int i = 0; i < (int)rle->size ; i++)
+ {
+ rle->spans[i].x = curSpans[i].x;
+ rle->spans[i].y = curSpans[i].y;
+ rle->spans[i].len = curSpans[i].len;
+ rle->spans[i].coverage = curSpans[i].coverage;
+ }
+}
+
+void rleClipPath(SwRleData *rle, const SwRleData *clip)
+{
+ if (rle->size == 0 || clip->size == 0) return;
+ auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
+ auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
+ if (!spans) return;
+ auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
+
+ //Update Spans
+ updateRleSpans(rle, spans, spansEnd - spans);
+
+ if (spans) free(spans);
+}
+
+void rleClipRect(SwRleData *rle, const SwBBox* clip)
+{
+ if (rle->size == 0) return;
+ auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
+ if (!spans) return;
+ auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
+
+ //Update Spans
+ updateRleSpans(rle, spans, spansEnd - spans);
+
+ if (spans) free(spans);
+}
}
-bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, const SwSize& clip, bool antiAlias)
+bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite)
{
//FIXME: Should we draw it?
//Case: Stroke Line
//if (shape.outline->opened) return true;
//Case A: Fast Track Rectangle Drawing
- if ((shape->rect = _fastTrack(shape->outline))) return true;
+ if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true;
//Case B: Normale Shape RLE Drawing
if ((shape->rle = rleRender(shape->outline, shape->bbox, clip, antiAlias))) return true;
if (!shape->fill) return;
fillFree(shape->fill);
shape->fill = nullptr;
-}
\ No newline at end of file
+}
paint->pImpl->dispose(*renderer);
delete(paint);
}
+
paints.clear();
return Result::Success;
{
if (!renderer) return Result::InsufficientCondition;
+ vector<Composite> compList;
+
//Update single paint node
if (paint) {
- if (!paint->pImpl->update(*renderer, nullptr, RenderUpdateFlag::None)) {
+ if (!paint->pImpl->update(*renderer, nullptr, compList, nullptr, RenderUpdateFlag::None)) {
return Result::InsufficientCondition;
}
//Update retained all paint nodes
} else {
- for(auto paint: paints) {
- if (!paint->pImpl->update(*renderer, nullptr, RenderUpdateFlag::None)) {
+ for (auto paint: paints) {
+ if (!paint->pImpl->update(*renderer, nullptr, compList, nullptr, RenderUpdateFlag::None)) {
return Result::InsufficientCondition;
}
}
}
};
-#endif /* _TVG_CANVAS_IMPL_H_ */
\ No newline at end of file
+#endif /* _TVG_CANVAS_IMPL_H_ */
return Result::FailedAllocation;
}
-
Result Paint::bounds(float* x, float* y, float* w, float* h) const noexcept
{
if (pImpl->bounds(x, y, w, h)) return Result::Success;
Paint* Paint::duplicate() const noexcept
{
return pImpl->duplicate();
-}
\ No newline at end of file
+}
+
+Result Paint::composite(std::unique_ptr<Paint> target, CompMethod method) const noexcept
+{
+ if (pImpl->composite(target.release(), method)) return Result::Success;
+ return Result::InsufficientCondition;
+}
+
virtual ~StrategyMethod(){}
virtual bool dispose(RenderMethod& renderer) = 0;
- virtual bool update(RenderMethod& renderer, const RenderTransform* transform, RenderUpdateFlag pFlag) = 0;
+ virtual bool update(RenderMethod& renderer, const RenderTransform* transform, vector<Composite> compList, void** edata, RenderUpdateFlag pFlag) = 0;
virtual bool render(RenderMethod& renderer) = 0;
virtual bool bounds(float* x, float* y, float* w, float* h) const = 0;
virtual Paint* duplicate() = 0;
RenderTransform *rTransform = nullptr;
uint32_t flag = RenderUpdateFlag::None;
+ Paint* compTarget = nullptr;
+ CompMethod compMethod = CompMethod::None;
+
~Impl() {
if (smethod) delete(smethod);
if (rTransform) delete(rTransform);
bool dispose(RenderMethod& renderer)
{
+ if (this->compTarget) this->compTarget->pImpl->dispose(renderer);
return smethod->dispose(renderer);
}
- bool update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t pFlag)
+ bool update(RenderMethod& renderer, const RenderTransform* pTransform, vector<Composite>& compList, void **edata, uint32_t pFlag)
{
if (flag & RenderUpdateFlag::Transform) {
if (!rTransform) return false;
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | flag);
flag = RenderUpdateFlag::None;
+ bool updated = false;
+ void *compEngineData = nullptr; //composite target paint's engine data.
+
+ if (this->compTarget && compMethod == CompMethod::ClipPath) {
+ if (this->compTarget->pImpl->update(renderer, pTransform, compList, &compEngineData, static_cast<RenderUpdateFlag>(pFlag | flag))) {
+ Composite comp;
+ comp.edata = compEngineData;
+ comp.method = this->compMethod;
+ compList.push_back(comp);
+ }
+ }
if (rTransform && pTransform) {
RenderTransform outTransform(pTransform, rTransform);
- return smethod->update(renderer, &outTransform, newFlag);
+ updated = smethod->update(renderer, &outTransform, compList, edata, newFlag);
} else {
auto outTransform = pTransform ? pTransform : rTransform;
- return smethod->update(renderer, outTransform, newFlag);
+ updated = smethod->update(renderer, outTransform, compList, edata, newFlag);
+ }
+
+ if (compEngineData) {
+ compList.pop_back();
}
+ return updated;
}
bool render(RenderMethod& renderer)
return ret;
}
+
+ bool composite(Paint* target, CompMethod compMethod)
+ {
+ this->compTarget = target;
+ this->compMethod = compMethod;
+ if (this->compTarget) return true;
+ return false;
+ }
};
return inst->dispose(renderer);
}
- bool update(RenderMethod& renderer, const RenderTransform* transform, RenderUpdateFlag flag) override
+ bool update(RenderMethod& renderer, const RenderTransform* transform, vector<Composite> compList, void** edata, RenderUpdateFlag flag) override
{
- return inst->update(renderer, transform, flag);
+ return inst->update(renderer, transform, compList, edata, flag);
}
bool render(RenderMethod& renderer) override
}
- bool update(RenderMethod &renderer, const RenderTransform* transform, RenderUpdateFlag flag)
+ bool update(RenderMethod &renderer, const RenderTransform* transform, vector<Composite>& compList, void** edata, RenderUpdateFlag flag)
{
reload();
if (!paint) return false;
- return paint->pImpl->update(renderer, transform, flag);
+ return paint->pImpl->update(renderer, transform, compList, edata, flag);
}
bool render(RenderMethod &renderer)
}
};
-#endif //_TVG_PICTURE_IMPL_H_
\ No newline at end of file
+#endif //_TVG_PICTURE_IMPL_H_
#ifndef _TVG_RENDER_H_
#define _TVG_RENDER_H_
+#include <vector>
#include "tvgCommon.h"
namespace tvg
uint32_t cs;
};
+struct Composite {
+ void* edata;
+ CompMethod method;
+};
+
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, All = 32};
struct RenderTransform
{
public:
virtual ~RenderMethod() {}
- virtual void* prepare(TVG_UNUSED const Shape& shape, TVG_UNUSED void* data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; }
+ virtual void* prepare(TVG_UNUSED const Shape& shape, TVG_UNUSED void* data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED vector<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; }
virtual bool dispose(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; }
virtual bool preRender() { return true; }
virtual bool render(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; }
}
-#endif //_TVG_RENDER_H_
\ No newline at end of file
+#endif //_TVG_RENDER_H_
return true;
}
- bool update(RenderMethod &renderer, const RenderTransform* transform, RenderUpdateFlag flag)
+ bool update(RenderMethod &renderer, const RenderTransform* transform, vector<Composite>& compList, void** edata, RenderUpdateFlag flag)
{
- for(auto paint: paints) {
- if (!paint->pImpl->update(renderer, transform, static_cast<uint32_t>(flag))) return false;
+ for (auto paint: paints) {
+ if (!paint->pImpl->update(renderer, transform, compList, edata, static_cast<uint32_t>(flag))) return false;
}
return true;
}
}
};
-#endif //_TVG_SCENE_IMPL_H_
\ No newline at end of file
+#endif //_TVG_SCENE_IMPL_H_
return renderer.render(*shape, edata);
}
- bool update(RenderMethod& renderer, const RenderTransform* transform, RenderUpdateFlag pFlag)
+ bool update(RenderMethod& renderer, const RenderTransform* transform, vector<Composite>& compList, void** edata, RenderUpdateFlag pFlag)
{
- edata = renderer.prepare(*shape, edata, transform, static_cast<RenderUpdateFlag>(pFlag | flag));
-
+ this->edata = renderer.prepare(*shape, this->edata, transform, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
flag = RenderUpdateFlag::None;
-
- if (edata) return true;
+ if (edata) *edata = this->edata;
+ if (this->edata) return true;
return false;
}