mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
common composite: code refactoring
Splited out ClipPath routine from other pixel compositions' since yet it's unlikely compatible... Also revise internal engine interfaces to be simpler. This is a step forward to enhance masking feature.
This commit is contained in:
parent
9cb256f473
commit
4767f83b99
14 changed files with 251 additions and 237 deletions
|
@ -279,6 +279,7 @@ public:
|
|||
|
||||
Result size(float w, float h) noexcept;
|
||||
Result size(float* w, float* h) const noexcept;
|
||||
const uint32_t* data() const noexcept;
|
||||
|
||||
static std::unique_ptr<Picture> gen() noexcept;
|
||||
|
||||
|
|
|
@ -12,11 +12,12 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
if (!canvas) return;
|
||||
|
||||
//Mask Target 2
|
||||
#if 0
|
||||
auto scene = tvg::Scene::gen();
|
||||
scene->opacity(127);
|
||||
scene->scale(1.2);
|
||||
scene->reserve(2);
|
||||
|
||||
#endif
|
||||
//Star
|
||||
auto shape = tvg::Shape::gen();
|
||||
|
||||
|
@ -33,17 +34,20 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
shape->lineTo(146, 143);
|
||||
shape->close();
|
||||
shape->fill(0, 0, 255, 255);
|
||||
shape->stroke(10);
|
||||
shape->stroke(255, 255, 255, 255);
|
||||
shape->opacity(127);
|
||||
// shape->stroke(10);
|
||||
// shape->stroke(255, 255, 255, 255);
|
||||
//shape->opacity(127);
|
||||
|
||||
scene->push(move(shape));
|
||||
// scene->push(move(shape));
|
||||
|
||||
//Alpha Mask
|
||||
auto mask2 = tvg::Shape::gen();
|
||||
mask2->appendCircle(200, 200, 125, 125);
|
||||
mask2->fill(255, 255, 255, 100);
|
||||
auto mask = tvg::Shape::gen();
|
||||
mask->appendCircle(200, 200, 125, 125);
|
||||
mask->fill(255, 255, 255, 255);
|
||||
shape->composite(move(mask), tvg::CompositeMethod::AlphaMask);
|
||||
canvas->push(move(shape));
|
||||
|
||||
#if 0
|
||||
scene->composite(move(mask2), tvg::CompositeMethod::AlphaMask);
|
||||
if (canvas->push(move(scene)) != tvg::Result::Success) return;
|
||||
|
||||
|
@ -66,9 +70,7 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
|
||||
picture->composite(move(mask), tvg::CompositeMethod::AlphaMask);
|
||||
if (canvas->push(move(picture)) != tvg::Result::Success) return;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class GlGeometry;
|
|||
|
||||
struct GlShape
|
||||
{
|
||||
const Shape* shape = nullptr;
|
||||
float viewWd;
|
||||
float viewHt;
|
||||
RenderUpdateFlag updateFlag;
|
||||
|
|
|
@ -73,7 +73,7 @@ bool GlRenderer::sync()
|
|||
}
|
||||
|
||||
|
||||
bool GlRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
bool GlRenderer::renderRegion(TVG_UNUSED RenderData data, TVG_UNUSED uint32_t* x, TVG_UNUSED uint32_t* y, TVG_UNUSED uint32_t* w, TVG_UNUSED uint32_t* h)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -102,31 +102,29 @@ bool GlRenderer::postRender()
|
|||
}
|
||||
|
||||
|
||||
void* GlRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
||||
void* GlRenderer::addCompositor(TVG_UNUSED CompositeMethod method, TVG_UNUSED uint32_t x, TVG_UNUSED uint32_t y, TVG_UNUSED uint32_t w, TVG_UNUSED uint32_t h, TVG_UNUSED uint32_t opacity)
|
||||
{
|
||||
//TODO: Prepare frameBuffer & Setup render target for composition
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::endComposite(void* ctx, uint32_t opacity)
|
||||
bool GlRenderer::delCompositor(TVG_UNUSED void* cmp)
|
||||
{
|
||||
//TODO: Composite Framebuffer to main surface
|
||||
//TODO: delete the given compositor and restore the context
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::render(const Picture& picture, void *data)
|
||||
bool GlRenderer::renderImage(TVG_UNUSED void* data, TVG_UNUSED void* cmp)
|
||||
{
|
||||
//TODO Draw Bitmap Image
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::render(const Shape& shape, void* data)
|
||||
bool GlRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
||||
{
|
||||
GlShape* sdata = static_cast<GlShape*>(data);
|
||||
auto sdata = static_cast<GlShape*>(data);
|
||||
if (!sdata) return false;
|
||||
|
||||
uint8_t r, g, b, a;
|
||||
|
@ -139,17 +137,17 @@ bool GlRenderer::render(const Shape& shape, void* data)
|
|||
{
|
||||
if (flags & RenderUpdateFlag::Gradient)
|
||||
{
|
||||
const Fill* gradient = shape.fill();
|
||||
const Fill* gradient = sdata->shape->fill();
|
||||
drawPrimitive(*sdata, gradient, i, RenderUpdateFlag::Gradient);
|
||||
}
|
||||
else if (flags & RenderUpdateFlag::Color)
|
||||
{
|
||||
shape.fillColor(&r, &g, &b, &a);
|
||||
sdata->shape->fillColor(&r, &g, &b, &a);
|
||||
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Color);
|
||||
}
|
||||
if (flags & RenderUpdateFlag::Stroke)
|
||||
{
|
||||
shape.strokeColor(&r, &g, &b, &a);
|
||||
sdata->shape->strokeColor(&r, &g, &b, &a);
|
||||
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Stroke);
|
||||
}
|
||||
}
|
||||
|
@ -158,9 +156,9 @@ bool GlRenderer::render(const Shape& shape, void* data)
|
|||
}
|
||||
|
||||
|
||||
bool GlRenderer::dispose(void *data)
|
||||
bool GlRenderer::dispose(RenderData data)
|
||||
{
|
||||
GlShape* sdata = static_cast<GlShape*>(data);
|
||||
auto sdata = static_cast<GlShape*>(data);
|
||||
if (!sdata) return false;
|
||||
|
||||
delete sdata;
|
||||
|
@ -168,20 +166,21 @@ bool GlRenderer::dispose(void *data)
|
|||
}
|
||||
|
||||
|
||||
void* GlRenderer::prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED void* data, TVG_UNUSED uint32_t *buffer, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED Array<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags)
|
||||
RenderData GlRenderer::prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED Array<RenderData>& clips, TVG_UNUSED RenderUpdateFlag flags)
|
||||
{
|
||||
//TODO:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
|
||||
RenderData GlRenderer::prepare(const Shape& shape, RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||
{
|
||||
//prepare shape data
|
||||
GlShape* sdata = static_cast<GlShape*>(data);
|
||||
if (!sdata) {
|
||||
sdata = new GlShape;
|
||||
if (!sdata) return nullptr;
|
||||
sdata->shape = &shape;
|
||||
}
|
||||
|
||||
sdata->viewWd = static_cast<float>(surface.w);
|
||||
|
|
|
@ -30,16 +30,16 @@ class GlRenderer : public RenderMethod
|
|||
public:
|
||||
Surface surface = {nullptr, 0, 0, 0};
|
||||
|
||||
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
|
||||
void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
|
||||
bool dispose(void *data) override;
|
||||
void* beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
|
||||
bool endComposite(void* ctx, uint32_t opacity) override;
|
||||
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||
RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||
bool dispose(RenderData data) override;
|
||||
void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) override;
|
||||
bool delCompositor(void* cmp) override;
|
||||
bool preRender() override;
|
||||
bool render(const Shape& shape, void *data) override;
|
||||
bool render(const Picture& picture, void *data) override;
|
||||
bool renderShape(RenderData data, void* cmp) override;
|
||||
bool renderImage(RenderData data, void* cmp) override;
|
||||
bool postRender() override;
|
||||
bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||
bool sync() override;
|
||||
bool clear() override;
|
||||
|
|
|
@ -33,9 +33,11 @@ static uint32_t rendererCnt = 0;
|
|||
struct SwComposite
|
||||
{
|
||||
SwSurface surface;
|
||||
SwSurface* recover;
|
||||
SwComposite* recover;
|
||||
SwImage image;
|
||||
SwBBox bbox;
|
||||
CompositeMethod method;
|
||||
uint32_t opacity;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
|
@ -45,7 +47,7 @@ struct SwTask : Task
|
|||
Matrix* transform = nullptr;
|
||||
SwSurface* surface = nullptr;
|
||||
RenderUpdateFlag flags = RenderUpdateFlag::None;
|
||||
Array<Composite> compList;
|
||||
Array<RenderData> clips;
|
||||
uint32_t opacity;
|
||||
SwBBox bbox = {{0, 0}, {0, 0}}; //Whole Rendering Region
|
||||
|
||||
|
@ -102,7 +104,7 @@ struct SwShapeTask : SwTask
|
|||
shape outline below stroke could be full covered by stroke drawing.
|
||||
Thus it turns off antialising in that condition. */
|
||||
auto antiAlias = (strokeAlpha == 255 && strokeWidth > 2) ? false : true;
|
||||
if (!shapeGenRle(&shape, sdata, clip, antiAlias, compList.count > 0 ? true : false)) goto end;
|
||||
if (!shapeGenRle(&shape, sdata, clip, antiAlias, clips.count > 0 ? true : false)) goto end;
|
||||
++addStroking;
|
||||
}
|
||||
}
|
||||
|
@ -131,10 +133,9 @@ struct SwShapeTask : SwTask
|
|||
}
|
||||
}
|
||||
|
||||
//Composition
|
||||
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
|
||||
auto compShape = &static_cast<SwShapeTask*>((*comp).edata)->shape;
|
||||
if ((*comp).method == CompositeMethod::ClipPath) {
|
||||
//Clip Path
|
||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
||||
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape;
|
||||
//Clip shape rle
|
||||
if (shape.rle) {
|
||||
if (compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
|
||||
|
@ -145,9 +146,6 @@ struct SwShapeTask : SwTask
|
|||
if (compShape->rect) rleClipRect(shape.strokeRle, &compShape->bbox);
|
||||
else if (compShape->rle) rleClipPath(shape.strokeRle, compShape->rle);
|
||||
}
|
||||
} else if ((*comp).method == CompositeMethod::AlphaMask) {
|
||||
rleAlphaMask(shape.rle, compShape->rle);
|
||||
}
|
||||
}
|
||||
end:
|
||||
shapeDelOutline(&shape, tid);
|
||||
|
@ -167,7 +165,6 @@ struct SwImageTask : SwTask
|
|||
{
|
||||
SwImage image;
|
||||
const Picture* pdata = nullptr;
|
||||
uint32_t* pixels = nullptr;
|
||||
|
||||
void run(unsigned tid) override
|
||||
{
|
||||
|
@ -181,23 +178,19 @@ struct SwImageTask : SwTask
|
|||
imageReset(&image);
|
||||
if (!imagePrepare(&image, pdata, tid, clip, transform, bbox)) goto end;
|
||||
|
||||
//Composition?
|
||||
if (compList.count > 0) {
|
||||
//Clip Path?
|
||||
if (clips.count > 0) {
|
||||
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
|
||||
if (image.rle) {
|
||||
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
|
||||
auto compShape = &static_cast<SwShapeTask*>((*comp).edata)->shape;
|
||||
if ((*comp).method == CompositeMethod::ClipPath) {
|
||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
||||
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape;
|
||||
if (compShape->rect) rleClipRect(image.rle, &compShape->bbox);
|
||||
else if (compShape->rle) rleClipPath(image.rle, compShape->rle);
|
||||
} else if ((*comp).method == CompositeMethod::AlphaMask) {
|
||||
rleAlphaMask(image.rle, compShape->rle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pixels) image.data = pixels;
|
||||
image.data = const_cast<uint32_t*>(pdata->data());
|
||||
end:
|
||||
imageDelOutline(&image, tid);
|
||||
}
|
||||
|
@ -255,6 +248,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
if (!surface) {
|
||||
surface = new SwSurface;
|
||||
if (!surface) return false;
|
||||
mainSurface = surface;
|
||||
}
|
||||
|
||||
surface->buffer = buffer;
|
||||
|
@ -278,17 +272,72 @@ bool SwRenderer::postRender()
|
|||
tasks.clear();
|
||||
|
||||
//Free Composite Caches
|
||||
for (auto comp = composites.data; comp < (composites.data + composites.count); ++comp) {
|
||||
for (auto comp = compositors.data; comp < (compositors.data + compositors.count); ++comp) {
|
||||
free((*comp)->image.data);
|
||||
delete(*comp);
|
||||
}
|
||||
composites.reset();
|
||||
compositors.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
bool SwRenderer::renderImage(RenderData data, TVG_UNUSED void* cmp)
|
||||
{
|
||||
auto task = static_cast<SwImageTask*>(data);
|
||||
task->done();
|
||||
|
||||
if (task->opacity == 0) return true;
|
||||
|
||||
return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
||||
{
|
||||
auto task = static_cast<SwShapeTask*>(data);
|
||||
task->done();
|
||||
|
||||
if (task->opacity == 0) return true;
|
||||
|
||||
uint32_t opacity;
|
||||
void *cmp2 = nullptr;
|
||||
|
||||
//Do Composition
|
||||
if (task->compStroking) {
|
||||
uint32_t x, y, w, h;
|
||||
task->bounds(&x, &y, &w, &h);
|
||||
opacity = 255;
|
||||
//CompositeMethod::None is used for a default alpha blending
|
||||
cmp2 = addCompositor(CompositeMethod::None, x, y, w, h, opacity);
|
||||
//No Composition
|
||||
} else {
|
||||
opacity = task->opacity;
|
||||
}
|
||||
|
||||
//Main raster stage
|
||||
uint8_t r, g, b, a;
|
||||
|
||||
if (auto fill = task->sdata->fill()) {
|
||||
//FIXME: pass opacity to apply gradient fill?
|
||||
rasterGradientShape(surface, &task->shape, fill->id());
|
||||
} else{
|
||||
task->sdata->fillColor(&r, &g, &b, &a);
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterSolidShape(surface, &task->shape, r, g, b, a);
|
||||
}
|
||||
|
||||
task->sdata->strokeColor(&r, &g, &b, &a);
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
||||
|
||||
//Composition (Shape + Stroke) stage
|
||||
if (task->compStroking) delCompositor(cmp2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SwRenderer::renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
static_cast<SwTask*>(data)->bounds(x, y, w, h);
|
||||
|
||||
|
@ -296,22 +345,12 @@ bool SwRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w,
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
|
||||
{
|
||||
auto task = static_cast<SwImageTask*>(data);
|
||||
task->done();
|
||||
|
||||
return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
|
||||
}
|
||||
|
||||
|
||||
void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
||||
void* SwRenderer::addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity)
|
||||
{
|
||||
SwComposite* comp = nullptr;
|
||||
|
||||
//Use cached data
|
||||
for (auto p = composites.data; p < (composites.data + composites.count); ++p) {
|
||||
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
|
||||
if ((*p)->valid) {
|
||||
comp = *p;
|
||||
break;
|
||||
|
@ -328,17 +367,19 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
|||
delete(comp);
|
||||
return nullptr;
|
||||
}
|
||||
composites.push(comp);
|
||||
compositors.push(comp);
|
||||
}
|
||||
|
||||
comp->valid = false;
|
||||
comp->method = method;
|
||||
comp->opacity = opacity;
|
||||
|
||||
//Boundary Check
|
||||
if (x + w > surface->w) w = (surface->w - x);
|
||||
if (y + h > surface->h) h = (surface->h - y);
|
||||
|
||||
#ifdef THORVG_LOG_ENABLED
|
||||
printf("SW_ENGINE: Using intermediate opacity composition [Region: %d %d %d %d]\n", x, y, w, h);
|
||||
printf("SW_ENGINE: Using intermediate composition [Method: %d][Region: %d %d %d %d]\n", (int)method, x, y, w, h);
|
||||
#endif
|
||||
|
||||
comp->bbox.min.x = x;
|
||||
|
@ -365,75 +406,38 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
|||
comp->surface.w = comp->image.w;
|
||||
comp->surface.h = comp->image.h;
|
||||
|
||||
//Switch active compositor
|
||||
comp->recover = compositor; //Backup current compositor
|
||||
compositor = comp;
|
||||
|
||||
//Switch render target
|
||||
comp->recover = surface;
|
||||
surface = &comp->surface;
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::endComposite(void* p, uint32_t opacity)
|
||||
bool SwRenderer::delCompositor(void* ctx)
|
||||
{
|
||||
if (!p) return false;
|
||||
auto comp = static_cast<SwComposite*>(p);
|
||||
|
||||
//Recover render target
|
||||
surface = comp->recover;
|
||||
|
||||
auto ret = rasterImage(surface, &comp->image, nullptr, comp->bbox, opacity);
|
||||
if (!ctx) return false;
|
||||
|
||||
auto comp = static_cast<SwComposite*>(ctx);
|
||||
comp->valid = true;
|
||||
|
||||
return ret;
|
||||
//Recover Context
|
||||
compositor = comp->recover;
|
||||
surface = compositor ? &compositor->surface : mainSurface;
|
||||
|
||||
//Default is alpha blending
|
||||
if (comp->method == CompositeMethod::None) {
|
||||
return rasterImage(surface, &comp->image, nullptr, comp->bbox, comp->opacity);
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
|
||||
{
|
||||
auto task = static_cast<SwShapeTask*>(data);
|
||||
task->done();
|
||||
|
||||
if (task->opacity == 0) return true;
|
||||
|
||||
uint32_t opacity;
|
||||
void *ctx = nullptr;
|
||||
|
||||
//Do Composition
|
||||
if (task->compStroking) {
|
||||
uint32_t x, y, w, h;
|
||||
task->bounds(&x, &y, &w, &h);
|
||||
ctx = beginComposite(x, y, w, h);
|
||||
opacity = 255;
|
||||
//No Composition
|
||||
} else {
|
||||
opacity = task->opacity;
|
||||
}
|
||||
|
||||
//Main raster stage
|
||||
uint8_t r, g, b, a;
|
||||
|
||||
if (auto fill = task->sdata->fill()) {
|
||||
//FIXME: pass opacity to apply gradient fill?
|
||||
rasterGradientShape(surface, &task->shape, fill->id());
|
||||
} else{
|
||||
task->sdata->fillColor(&r, &g, &b, &a);
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterSolidShape(surface, &task->shape, r, g, b, a);
|
||||
}
|
||||
|
||||
task->sdata->strokeColor(&r, &g, &b, &a);
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
||||
|
||||
//Composition (Shape + Stroke) stage
|
||||
if (task->compStroking) endComposite(ctx, task->opacity);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::dispose(void *data)
|
||||
bool SwRenderer::dispose(RenderData data)
|
||||
{
|
||||
auto task = static_cast<SwTask*>(data);
|
||||
if (!task) return true;
|
||||
|
@ -447,14 +451,19 @@ bool SwRenderer::dispose(void *data)
|
|||
}
|
||||
|
||||
|
||||
void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
|
||||
void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||
{
|
||||
if (compList.count > 0) {
|
||||
if (flags == RenderUpdateFlag::None) return task;
|
||||
|
||||
//Finish previous task if it has duplicated request.
|
||||
task->done();
|
||||
|
||||
if (clips.count > 0) {
|
||||
//Guarantee composition targets get ready.
|
||||
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
|
||||
static_cast<SwShapeTask*>((*comp).edata)->done();
|
||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
||||
static_cast<SwShapeTask*>(*comp)->done();
|
||||
}
|
||||
task->compList = compList;
|
||||
task->clips = clips;
|
||||
}
|
||||
|
||||
if (transform) {
|
||||
|
@ -471,50 +480,34 @@ void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, u
|
|||
|
||||
tasks.push(task);
|
||||
TaskScheduler::request(task);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
void* SwRenderer::prepare(const Picture& pdata, void* data, uint32_t *pixels, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
|
||||
RenderData SwRenderer::prepare(const Picture& pdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||
{
|
||||
//prepare task
|
||||
auto task = static_cast<SwImageTask*>(data);
|
||||
if (!task) {
|
||||
task = new SwImageTask;
|
||||
if (!task) return nullptr;
|
||||
}
|
||||
|
||||
if (flags == RenderUpdateFlag::None) return task;
|
||||
|
||||
//Finish previous task if it has duplicated request.
|
||||
task->done();
|
||||
|
||||
task->pdata = &pdata;
|
||||
task->pixels = pixels;
|
||||
|
||||
prepareCommon(task, transform, opacity, compList, flags);
|
||||
|
||||
return task;
|
||||
}
|
||||
return prepareCommon(task, transform, opacity, clips, flags);
|
||||
}
|
||||
|
||||
|
||||
void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
|
||||
RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||
{
|
||||
//prepare task
|
||||
auto task = static_cast<SwShapeTask*>(data);
|
||||
if (!task) {
|
||||
task = new SwShapeTask;
|
||||
if (!task) return nullptr;
|
||||
}
|
||||
|
||||
if (flags == RenderUpdateFlag::None) return task;
|
||||
|
||||
//Finish previous task if it has duplicated request.
|
||||
task->done();
|
||||
task->sdata = &sdata;
|
||||
|
||||
prepareCommon(task, transform, opacity, compList, flags);
|
||||
|
||||
return task;
|
||||
}
|
||||
return prepareCommon(task, transform, opacity, clips, flags);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
struct SwSurface;
|
||||
struct SwTask;
|
||||
struct SwShapeTask;
|
||||
struct SwImage;
|
||||
struct SwComposite;
|
||||
|
||||
namespace tvg
|
||||
|
@ -36,17 +34,17 @@ namespace tvg
|
|||
class SwRenderer : public RenderMethod
|
||||
{
|
||||
public:
|
||||
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
|
||||
void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
|
||||
void* beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
|
||||
bool endComposite(void* ctx, uint32_t opacity) override;
|
||||
bool dispose(void *data) override;
|
||||
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||
RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||
void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) override;
|
||||
bool delCompositor(void* cmp) override;
|
||||
bool dispose(RenderData data) override;
|
||||
bool preRender() override;
|
||||
bool postRender() override;
|
||||
bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool clear() override;
|
||||
bool render(const Shape& shape, void *data) override;
|
||||
bool render(const Picture& picture, void *data) override;
|
||||
bool renderShape(RenderData data, void* cmp) override;
|
||||
bool renderImage(RenderData data, void* cmp) override;
|
||||
bool sync() override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
|
||||
|
@ -55,14 +53,16 @@ public:
|
|||
static bool term();
|
||||
|
||||
private:
|
||||
SwSurface* surface = nullptr;
|
||||
Array<SwTask*> tasks;
|
||||
Array<SwComposite*> composites;
|
||||
SwSurface* surface = nullptr; //active surface
|
||||
SwComposite* compositor = nullptr; //active compositor
|
||||
SwSurface* mainSurface = nullptr; //main (default) surface
|
||||
Array<SwTask*> tasks; //async task list
|
||||
Array<SwComposite*> compositors; //compositor cache list
|
||||
|
||||
SwRenderer(){};
|
||||
~SwRenderer();
|
||||
|
||||
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags);
|
||||
RenderData prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -76,15 +76,15 @@ struct Canvas::Impl
|
|||
{
|
||||
if (!renderer) return Result::InsufficientCondition;
|
||||
|
||||
Array<Composite> compList;
|
||||
Array<RenderData> clips;
|
||||
|
||||
//Update single paint node
|
||||
if (paint) {
|
||||
paint->pImpl->update(*renderer, nullptr, 255, compList, RenderUpdateFlag::None);
|
||||
paint->pImpl->update(*renderer, nullptr, 255, clips, RenderUpdateFlag::None);
|
||||
//Update all retained paint nodes
|
||||
} else {
|
||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||
(*paint)->pImpl->update(*renderer, nullptr, 255, compList, RenderUpdateFlag::None);
|
||||
(*paint)->pImpl->update(*renderer, nullptr, 255, clips, RenderUpdateFlag::None);
|
||||
}
|
||||
}
|
||||
return Result::Success;
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace tvg
|
|||
virtual ~StrategyMethod() {}
|
||||
|
||||
virtual bool dispose(RenderMethod& renderer) = 0;
|
||||
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
|
||||
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
|
||||
virtual bool render(RenderMethod& renderer) = 0;
|
||||
virtual bool bounds(float* x, float* y, float* w, float* h) const = 0;
|
||||
virtual bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const = 0;
|
||||
|
@ -137,7 +137,7 @@ namespace tvg
|
|||
return smethod->dispose(renderer);
|
||||
}
|
||||
|
||||
void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<Composite>& compList, uint32_t pFlag)
|
||||
void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag)
|
||||
{
|
||||
if (flag & RenderUpdateFlag::Transform) {
|
||||
if (!rTransform) return nullptr;
|
||||
|
@ -149,9 +149,9 @@ namespace tvg
|
|||
|
||||
void *compdata = nullptr;
|
||||
|
||||
if (compTarget && (compMethod != CompositeMethod::None)) {
|
||||
compdata = compTarget->pImpl->update(renderer, pTransform, opacity, compList, pFlag);
|
||||
if (compdata) compList.push({compdata, compMethod});
|
||||
if (compTarget) {
|
||||
compdata = compTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
|
||||
if (compMethod == CompositeMethod::ClipPath) clips.push(compdata);
|
||||
}
|
||||
|
||||
void *edata = nullptr;
|
||||
|
@ -161,20 +161,34 @@ namespace tvg
|
|||
|
||||
if (rTransform && pTransform) {
|
||||
RenderTransform outTransform(pTransform, rTransform);
|
||||
edata = smethod->update(renderer, &outTransform, opacity, compList, newFlag);
|
||||
edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag);
|
||||
} else {
|
||||
auto outTransform = pTransform ? pTransform : rTransform;
|
||||
edata = smethod->update(renderer, outTransform, opacity, compList, newFlag);
|
||||
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
|
||||
}
|
||||
|
||||
if (compdata) compList.pop();
|
||||
if (compdata) clips.pop();
|
||||
|
||||
return edata;
|
||||
}
|
||||
|
||||
bool render(RenderMethod& renderer)
|
||||
{
|
||||
return smethod->render(renderer);
|
||||
void* cmp = nullptr;
|
||||
|
||||
/* Note: only ClipPath is processed in update() step */
|
||||
if (compTarget && compMethod != CompositeMethod::ClipPath) {
|
||||
uint32_t x, y, w, h;
|
||||
if (!compTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
|
||||
cmp = renderer.addCompositor(compMethod, x, y, w, h, 255);
|
||||
compTarget->pImpl->render(renderer);
|
||||
}
|
||||
|
||||
auto ret = smethod->render(renderer);
|
||||
|
||||
renderer.delCompositor(cmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Paint* duplicate()
|
||||
|
@ -198,6 +212,7 @@ namespace tvg
|
|||
bool composite(Paint* target, CompositeMethod method)
|
||||
{
|
||||
if (!target && method != CompositeMethod::None) return false;
|
||||
if (target && method == CompositeMethod::None) return false;
|
||||
compTarget = target;
|
||||
compMethod = method;
|
||||
return true;
|
||||
|
@ -228,9 +243,9 @@ namespace tvg
|
|||
return inst->dispose(renderer);
|
||||
}
|
||||
|
||||
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flag) override
|
||||
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag) override
|
||||
{
|
||||
return inst->update(renderer, transform, opacity, compList, flag);
|
||||
return inst->update(renderer, transform, opacity, clips, flag);
|
||||
}
|
||||
|
||||
bool render(RenderMethod& renderer) override
|
||||
|
|
|
@ -89,3 +89,11 @@ Result Picture::size(float* w, float* h) const noexcept
|
|||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
const uint32_t* Picture::data() const noexcept
|
||||
{
|
||||
//Try it, If not loaded yet.
|
||||
if (pImpl->loader) return pImpl->loader->pixels();
|
||||
|
||||
return pImpl->pixels;
|
||||
}
|
|
@ -36,7 +36,7 @@ struct Picture::Impl
|
|||
Paint* paint = nullptr;
|
||||
uint32_t *pixels = nullptr;
|
||||
Picture *picture = nullptr;
|
||||
void *edata = nullptr; //engine data
|
||||
void *rdata = nullptr; //engine data
|
||||
float w = 0, h = 0;
|
||||
bool resizing = false;
|
||||
|
||||
|
@ -53,7 +53,7 @@ struct Picture::Impl
|
|||
return true;
|
||||
}
|
||||
else if (pixels) {
|
||||
return renderer.dispose(edata);
|
||||
return renderer.dispose(rdata);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -103,28 +103,28 @@ struct Picture::Impl
|
|||
}
|
||||
}
|
||||
if (!pixels) {
|
||||
pixels = (uint32_t*)loader->pixels();
|
||||
pixels = const_cast<uint32_t*>(loader->pixels());
|
||||
if (pixels) return RenderUpdateFlag::Image;
|
||||
}
|
||||
}
|
||||
return RenderUpdateFlag::None;
|
||||
}
|
||||
|
||||
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag)
|
||||
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
||||
{
|
||||
uint32_t flag = reload();
|
||||
auto flag = reload();
|
||||
|
||||
if (pixels) edata = renderer.prepare(*picture, edata, pixels, transform, opacity, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||
if (pixels) rdata = renderer.prepare(*picture, rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||
else if (paint) {
|
||||
if (resizing) resize();
|
||||
edata = paint->pImpl->update(renderer, transform, opacity, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||
rdata = paint->pImpl->update(renderer, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||
}
|
||||
return edata;
|
||||
return rdata;
|
||||
}
|
||||
|
||||
bool render(RenderMethod &renderer)
|
||||
{
|
||||
if (pixels) return renderer.render(*picture, edata);
|
||||
if (pixels) return renderer.renderImage(rdata, nullptr);
|
||||
else if (paint) return paint->pImpl->render(renderer);
|
||||
return false;
|
||||
}
|
||||
|
@ -155,8 +155,8 @@ struct Picture::Impl
|
|||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
if (edata) return renderer.renderRegion(edata, x, y, w, h);
|
||||
if (paint) paint->pImpl->bounds(renderer, x, y, w, h);
|
||||
if (rdata) return renderer.renderRegion(rdata, x, y, w, h);
|
||||
if (paint) return paint->pImpl->bounds(renderer, x, y, w, h);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,7 @@ struct Surface
|
|||
uint32_t cs;
|
||||
};
|
||||
|
||||
struct Composite {
|
||||
void* edata;
|
||||
CompositeMethod method;
|
||||
};
|
||||
using RenderData = void*;
|
||||
|
||||
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64};
|
||||
|
||||
|
@ -60,21 +57,20 @@ struct RenderTransform
|
|||
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
||||
};
|
||||
|
||||
|
||||
class RenderMethod
|
||||
{
|
||||
public:
|
||||
virtual ~RenderMethod() {}
|
||||
virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) = 0;
|
||||
virtual void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) = 0;
|
||||
virtual void* beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) = 0;
|
||||
virtual bool endComposite(void* ctx, uint32_t opacity) = 0;
|
||||
virtual bool dispose(void *data) = 0;
|
||||
virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
||||
virtual RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
||||
virtual void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) = 0;
|
||||
virtual bool delCompositor(void* cmp) = 0;
|
||||
virtual bool dispose(RenderData data) = 0;
|
||||
virtual bool preRender() = 0;
|
||||
virtual bool render(const Shape& shape, void *data) = 0;
|
||||
virtual bool render(const Picture& picture, void *data) = 0;
|
||||
virtual bool renderShape(RenderData data, void* cmp) = 0;
|
||||
virtual bool renderImage(RenderData data, void* cmp) = 0;
|
||||
virtual bool postRender() = 0;
|
||||
virtual bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) = 0;
|
||||
virtual bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) = 0;
|
||||
virtual bool clear() = 0;
|
||||
virtual bool sync() = 0;
|
||||
};
|
||||
|
|
|
@ -44,41 +44,40 @@ struct Scene::Impl
|
|||
return true;
|
||||
}
|
||||
|
||||
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flag)
|
||||
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag)
|
||||
{
|
||||
this->opacity = opacity;
|
||||
|
||||
/* Overriding opacity value. If this scene is half-translucent,
|
||||
It must do intermeidate composition with that opacity value. */
|
||||
if (opacity < 255 && opacity > 0) opacity = 255;
|
||||
if (opacity > 0) opacity = 255;
|
||||
|
||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||
(*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast<uint32_t>(flag));
|
||||
}
|
||||
|
||||
/* FXIME: it requires to return list of children engine data
|
||||
This is necessary for scene composition */
|
||||
void* edata = nullptr;
|
||||
|
||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||
edata = (*paint)->pImpl->update(renderer, transform, opacity, compList, static_cast<uint32_t>(flag));
|
||||
}
|
||||
|
||||
return edata;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool render(RenderMethod& renderer)
|
||||
{
|
||||
void* ctx = nullptr;
|
||||
void* cmp = nullptr;
|
||||
|
||||
//Half translucent. This requires intermediate composition.
|
||||
if (opacity < 255 && opacity > 0) {
|
||||
//Half translucent. This condition requires intermediate composition.
|
||||
if (opacity < 255 && opacity > 0 && (paints.count > 1)) {
|
||||
uint32_t x, y, w, h;
|
||||
if (!bounds(renderer, &x, &y, &w, &h)) return false;
|
||||
ctx = renderer.beginComposite(x, y, w, h);
|
||||
//CompositeMethod::None is used for a default alpha blending
|
||||
cmp = renderer.addCompositor(CompositeMethod::None, x, y, w, h, opacity);
|
||||
}
|
||||
|
||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||
if (!(*paint)->pImpl->render(renderer)) return false;
|
||||
}
|
||||
|
||||
if (ctx) return renderer.endComposite(ctx, opacity);
|
||||
if (cmp) renderer.delCompositor(cmp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ struct Shape::Impl
|
|||
ShapeStroke *stroke = nullptr;
|
||||
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
|
||||
FillRule rule = FillRule::Winding;
|
||||
void *edata = nullptr; //engine data
|
||||
RenderData rdata = nullptr; //engine data
|
||||
Shape *shape = nullptr;
|
||||
uint32_t flag = RenderUpdateFlag::None;
|
||||
|
||||
|
@ -215,24 +215,24 @@ struct Shape::Impl
|
|||
|
||||
bool dispose(RenderMethod& renderer)
|
||||
{
|
||||
return renderer.dispose(edata);
|
||||
return renderer.dispose(rdata);
|
||||
}
|
||||
|
||||
bool render(RenderMethod& renderer)
|
||||
{
|
||||
return renderer.render(*shape, edata);
|
||||
return renderer.renderShape(rdata, nullptr);
|
||||
}
|
||||
|
||||
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag)
|
||||
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
||||
{
|
||||
this->edata = renderer.prepare(*shape, this->edata, transform, opacity, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||
this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||
flag = RenderUpdateFlag::None;
|
||||
return this->edata;
|
||||
return this->rdata;
|
||||
}
|
||||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
return renderer.renderRegion(edata, x, y, w, h);
|
||||
return renderer.renderRegion(rdata, x, y, w, h);
|
||||
}
|
||||
|
||||
bool bounds(float* x, float* y, float* w, float* h)
|
||||
|
|
Loading…
Add table
Reference in a new issue