mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
common sw_engine: code refactoring
Renamed internal interfaces. We need both blender & compositor interfaces. Renamed SwCompositor -> SwBlender which is for pixel joining methods. Added (SwCompositor, Compositor) which is designed for compositing images.
This commit is contained in:
parent
c1e36bcb01
commit
7d9023ac5c
10 changed files with 137 additions and 131 deletions
|
@ -102,27 +102,27 @@ bool GlRenderer::postRender()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
Compositor* GlRenderer::addCompositor(TVG_UNUSED uint32_t x, TVG_UNUSED uint32_t y, TVG_UNUSED uint32_t w, TVG_UNUSED uint32_t h)
|
||||||
{
|
{
|
||||||
//TODO: Prepare frameBuffer & Setup render target for composition
|
//TODO: Prepare frameBuffer & Setup render target for composition
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::delCompositor(TVG_UNUSED void* cmp)
|
bool GlRenderer::delCompositor(TVG_UNUSED Compositor* cmp)
|
||||||
{
|
{
|
||||||
//TODO: delete the given compositor and restore the context
|
//TODO: delete the given compositor and restore the context
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::renderImage(TVG_UNUSED void* data, TVG_UNUSED void* cmp)
|
bool GlRenderer::renderImage(TVG_UNUSED void* data, TVG_UNUSED Compositor* cmp)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
bool GlRenderer::renderShape(RenderData data, TVG_UNUSED Compositor* cmp)
|
||||||
{
|
{
|
||||||
auto sdata = static_cast<GlShape*>(data);
|
auto sdata = static_cast<GlShape*>(data);
|
||||||
if (!sdata) return false;
|
if (!sdata) return false;
|
||||||
|
|
|
@ -33,11 +33,11 @@ public:
|
||||||
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) 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;
|
RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
bool dispose(RenderData data) 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;
|
Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
|
||||||
bool delCompositor(void* cmp) override;
|
bool delCompositor(Compositor* cmp) override;
|
||||||
bool preRender() override;
|
bool preRender() override;
|
||||||
bool renderShape(RenderData data, void* cmp) override;
|
bool renderShape(RenderData data, Compositor* cmp) override;
|
||||||
bool renderImage(RenderData data, void* cmp) override;
|
bool renderImage(RenderData data, Compositor* cmp) override;
|
||||||
bool postRender() override;
|
bool postRender() override;
|
||||||
bool renderRegion(RenderData 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 target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||||
|
|
|
@ -220,7 +220,7 @@ struct SwImage
|
||||||
uint32_t w, h;
|
uint32_t w, h;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwCompositor
|
struct SwBlender
|
||||||
{
|
{
|
||||||
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
uint32_t (*alpha)(uint32_t rgba);
|
uint32_t (*alpha)(uint32_t rgba);
|
||||||
|
@ -228,7 +228,7 @@ struct SwCompositor
|
||||||
|
|
||||||
struct SwSurface : Surface
|
struct SwSurface : Surface
|
||||||
{
|
{
|
||||||
SwCompositor comp;
|
SwBlender blender;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline SwCoord TO_SWCOORD(float val)
|
static inline SwCoord TO_SWCOORD(float val)
|
||||||
|
|
|
@ -52,7 +52,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac
|
||||||
auto g = ALPHA_MULTIPLY(pColors->g, pColors->a);
|
auto g = ALPHA_MULTIPLY(pColors->g, pColors->a);
|
||||||
auto b = ALPHA_MULTIPLY(pColors->b, pColors->a);
|
auto b = ALPHA_MULTIPLY(pColors->b, pColors->a);
|
||||||
|
|
||||||
auto rgba = surface->comp.join(r, g, b, pColors->a);
|
auto rgba = surface->blender.join(r, g, b, pColors->a);
|
||||||
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
|
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
|
||||||
auto pos = 1.5f * inc;
|
auto pos = 1.5f * inc;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
@ -75,7 +75,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac
|
||||||
auto g = ALPHA_MULTIPLY(next->g, next->a);
|
auto g = ALPHA_MULTIPLY(next->g, next->a);
|
||||||
auto b = ALPHA_MULTIPLY(next->b, next->a);
|
auto b = ALPHA_MULTIPLY(next->b, next->a);
|
||||||
|
|
||||||
auto rgba2 = surface->comp.join(r, g, b, next->a);
|
auto rgba2 = surface->blender.join(r, g, b, next->a);
|
||||||
|
|
||||||
while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
|
while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
|
||||||
auto t = (pos - curr->offset) * delta;
|
auto t = (pos - curr->offset) * delta;
|
||||||
|
|
|
@ -97,7 +97,7 @@ static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uin
|
||||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
auto ialpha = 255 - surface->comp.alpha(color);
|
auto ialpha = 255 - surface->blender.alpha(color);
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
|
@ -133,7 +133,7 @@ static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t c
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
auto ialpha = 255 - surface->comp.alpha(src);
|
auto ialpha = 255 - surface->blender.alpha(src);
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
dst[i] = src + ALPHA_BLEND(dst[i], ialpha);
|
dst[i] = src + ALPHA_BLEND(dst[i], ialpha);
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint3
|
||||||
if (rX >= w || rY >= h) continue;
|
if (rX >= w || rY >= h) continue;
|
||||||
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
|
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
|
||||||
auto src = ALPHA_BLEND(img[rY * w + rX], alpha); //TODO: need to use image's stride
|
auto src = ALPHA_BLEND(img[rY * w + rX], alpha); //TODO: need to use image's stride
|
||||||
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
++span;
|
++span;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, u
|
||||||
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + ey2));
|
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + ey2));
|
||||||
if (rX >= w || rY >= h) continue;
|
if (rX >= w || rY >= h) continue;
|
||||||
auto src = ALPHA_BLEND(img[rY * w + rX], span->coverage); //TODO: need to use image's stride
|
auto src = ALPHA_BLEND(img[rY * w + rX], span->coverage); //TODO: need to use image's stride
|
||||||
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
++span;
|
++span;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t
|
||||||
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2));
|
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2));
|
||||||
if (rX >= w || rY >= h) continue;
|
if (rX >= w || rY >= h) continue;
|
||||||
auto src = ALPHA_BLEND(img[rX + (rY * w)], opacity); //TODO: need to use image's stride
|
auto src = ALPHA_BLEND(img[rX + (rY * w)], opacity); //TODO: need to use image's stride
|
||||||
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -210,7 +210,7 @@ static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t
|
||||||
auto dst = &surface->buffer[y * surface->stride + region.min.x];
|
auto dst = &surface->buffer[y * surface->stride + region.min.x];
|
||||||
auto src = img + region.min.x + (y * w); //TODO: need to use image's stride
|
auto src = img + region.min.x + (y * w); //TODO: need to use image's stride
|
||||||
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
|
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
|
||||||
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(*src));
|
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -228,7 +228,7 @@ static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t
|
||||||
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2));
|
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2));
|
||||||
if (rX >= w || rY >= h) continue;
|
if (rX >= w || rY >= h) continue;
|
||||||
auto src = img[rX + (rY * w)]; //TODO: need to use image's stride
|
auto src = img[rX + (rY * w)]; //TODO: need to use image's stride
|
||||||
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -276,7 +276,7 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
|
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
for (uint32_t x = 0; x < w; ++x) {
|
||||||
dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x]));
|
dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->blender.alpha(tmpBuf[x]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Opaque Gradient
|
//Opaque Gradient
|
||||||
|
@ -307,7 +307,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
|
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
for (uint32_t x = 0; x < w; ++x) {
|
||||||
dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x]));
|
dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->blender.alpha(tmpBuf[x]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Opaque Gradient
|
//Opaque Gradient
|
||||||
|
@ -337,12 +337,12 @@ static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const S
|
||||||
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i]));
|
dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(buf[i]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
auto tmp = ALPHA_BLEND(buf[i], span->coverage);
|
auto tmp = ALPHA_BLEND(buf[i], span->coverage);
|
||||||
dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp));
|
dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(tmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++span;
|
++span;
|
||||||
|
@ -383,12 +383,12 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S
|
||||||
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i]));
|
dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(buf[i]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
auto tmp = ALPHA_BLEND(buf[i], span->coverage);
|
auto tmp = ALPHA_BLEND(buf[i], span->coverage);
|
||||||
dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp));
|
dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(tmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++span;
|
++span;
|
||||||
|
@ -420,11 +420,11 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S
|
||||||
bool rasterCompositor(SwSurface* surface)
|
bool rasterCompositor(SwSurface* surface)
|
||||||
{
|
{
|
||||||
if (surface->cs == SwCanvas::ABGR8888) {
|
if (surface->cs == SwCanvas::ABGR8888) {
|
||||||
surface->comp.alpha = _colorAlpha;
|
surface->blender.alpha = _colorAlpha;
|
||||||
surface->comp.join = _abgrJoin;
|
surface->blender.join = _abgrJoin;
|
||||||
} else if (surface->cs == SwCanvas::ARGB8888) {
|
} else if (surface->cs == SwCanvas::ARGB8888) {
|
||||||
surface->comp.alpha = _colorAlpha;
|
surface->blender.alpha = _colorAlpha;
|
||||||
surface->comp.join = _argbJoin;
|
surface->blender.join = _argbJoin;
|
||||||
} else {
|
} else {
|
||||||
//What Color Space ???
|
//What Color Space ???
|
||||||
return false;
|
return false;
|
||||||
|
@ -455,7 +455,7 @@ bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g,
|
||||||
g = ALPHA_MULTIPLY(g, a);
|
g = ALPHA_MULTIPLY(g, a);
|
||||||
b = ALPHA_MULTIPLY(b, a);
|
b = ALPHA_MULTIPLY(b, a);
|
||||||
|
|
||||||
auto color = surface->comp.join(r, g, b, a);
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
|
|
||||||
//Fast Track
|
//Fast Track
|
||||||
if (shape->rect) {
|
if (shape->rect) {
|
||||||
|
@ -476,7 +476,7 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint
|
||||||
g = ALPHA_MULTIPLY(g, a);
|
g = ALPHA_MULTIPLY(g, a);
|
||||||
b = ALPHA_MULTIPLY(b, a);
|
b = ALPHA_MULTIPLY(b, a);
|
||||||
|
|
||||||
auto color = surface->comp.join(r, g, b, a);
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
|
|
||||||
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color);
|
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color);
|
||||||
return _rasterTranslucentRle(surface, shape->strokeRle, color);
|
return _rasterTranslucentRle(surface, shape->strokeRle, color);
|
||||||
|
|
|
@ -30,14 +30,12 @@
|
||||||
static bool initEngine = false;
|
static bool initEngine = false;
|
||||||
static uint32_t rendererCnt = 0;
|
static uint32_t rendererCnt = 0;
|
||||||
|
|
||||||
struct SwComposite
|
struct SwCompositor : Compositor
|
||||||
{
|
{
|
||||||
SwSurface surface;
|
SwSurface surface;
|
||||||
SwComposite* recover;
|
SwCompositor* recover;
|
||||||
SwImage image;
|
SwImage image;
|
||||||
SwBBox bbox;
|
SwBBox bbox;
|
||||||
CompositeMethod method;
|
|
||||||
uint32_t opacity;
|
|
||||||
bool valid;
|
bool valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ struct SwShapeTask : SwTask
|
||||||
{
|
{
|
||||||
SwShape shape;
|
SwShape shape;
|
||||||
const Shape* sdata = nullptr;
|
const Shape* sdata = nullptr;
|
||||||
bool compStroking;
|
bool cmpStroking;
|
||||||
|
|
||||||
void run(unsigned tid) override
|
void run(unsigned tid) override
|
||||||
{
|
{
|
||||||
|
@ -134,23 +132,23 @@ struct SwShapeTask : SwTask
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clip Path
|
//Clip Path
|
||||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||||
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape;
|
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
||||||
//Clip shape rle
|
//Clip shape rle
|
||||||
if (shape.rle) {
|
if (shape.rle) {
|
||||||
if (compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
|
if (clipper->rect) rleClipRect(shape.rle, &clipper->bbox);
|
||||||
else if (compShape->rle) rleClipPath(shape.rle, compShape->rle);
|
else if (clipper->rle) rleClipPath(shape.rle, clipper->rle);
|
||||||
}
|
}
|
||||||
//Clip stroke rle
|
//Clip stroke rle
|
||||||
if (shape.strokeRle) {
|
if (shape.strokeRle) {
|
||||||
if (compShape->rect) rleClipRect(shape.strokeRle, &compShape->bbox);
|
if (clipper->rect) rleClipRect(shape.strokeRle, &clipper->bbox);
|
||||||
else if (compShape->rle) rleClipPath(shape.strokeRle, compShape->rle);
|
else if (clipper->rle) rleClipPath(shape.strokeRle, clipper->rle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
shapeDelOutline(&shape, tid);
|
shapeDelOutline(&shape, tid);
|
||||||
if (addStroking == 2 && opacity < 255) compStroking = true;
|
if (addStroking == 2 && opacity < 255) cmpStroking = true;
|
||||||
else compStroking = false;
|
else cmpStroking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dispose() override
|
bool dispose() override
|
||||||
|
@ -182,10 +180,10 @@ struct SwImageTask : SwTask
|
||||||
if (clips.count > 0) {
|
if (clips.count > 0) {
|
||||||
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
|
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
|
||||||
if (image.rle) {
|
if (image.rle) {
|
||||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||||
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape;
|
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
||||||
if (compShape->rect) rleClipRect(image.rle, &compShape->bbox);
|
if (clipper->rect) rleClipRect(image.rle, &clipper->bbox);
|
||||||
else if (compShape->rle) rleClipPath(image.rle, compShape->rle);
|
else if (clipper->rle) rleClipPath(image.rle, clipper->rle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +280,7 @@ bool SwRenderer::postRender()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::renderImage(RenderData data, TVG_UNUSED void* cmp)
|
bool SwRenderer::renderImage(RenderData data, TVG_UNUSED Compositor* cmp)
|
||||||
{
|
{
|
||||||
auto task = static_cast<SwImageTask*>(data);
|
auto task = static_cast<SwImageTask*>(data);
|
||||||
task->done();
|
task->done();
|
||||||
|
@ -293,7 +291,7 @@ bool SwRenderer::renderImage(RenderData data, TVG_UNUSED void* cmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
bool SwRenderer::renderShape(RenderData data, TVG_UNUSED Compositor* cmp)
|
||||||
{
|
{
|
||||||
auto task = static_cast<SwShapeTask*>(data);
|
auto task = static_cast<SwShapeTask*>(data);
|
||||||
task->done();
|
task->done();
|
||||||
|
@ -301,15 +299,17 @@ bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
||||||
if (task->opacity == 0) return true;
|
if (task->opacity == 0) return true;
|
||||||
|
|
||||||
uint32_t opacity;
|
uint32_t opacity;
|
||||||
void *cmp2 = nullptr;
|
Compositor* cmp2 = nullptr;
|
||||||
|
|
||||||
//Do Composition
|
//Do Composition
|
||||||
if (task->compStroking) {
|
if (task->cmpStroking) {
|
||||||
uint32_t x, y, w, h;
|
uint32_t x, y, w, h;
|
||||||
task->bounds(&x, &y, &w, &h);
|
task->bounds(&x, &y, &w, &h);
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
//CompositeMethod::None is used for a default alpha blending
|
//CompositeMethod::None is used for a default alpha blending
|
||||||
cmp2 = addCompositor(CompositeMethod::None, x, y, w, h, opacity);
|
cmp2 = addCompositor(x, y, w, h);
|
||||||
|
cmp2->method = CompositeMethod::None;
|
||||||
|
cmp2->opacity = opacity;
|
||||||
//No Composition
|
//No Composition
|
||||||
} else {
|
} else {
|
||||||
opacity = task->opacity;
|
opacity = task->opacity;
|
||||||
|
@ -332,7 +332,7 @@ bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
||||||
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
||||||
|
|
||||||
//Composition (Shape + Stroke) stage
|
//Composition (Shape + Stroke) stage
|
||||||
if (task->compStroking) delCompositor(cmp2);
|
if (task->cmpStroking) delCompositor(cmp2);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -345,92 +345,90 @@ bool SwRenderer::renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void* SwRenderer::addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity)
|
Compositor* SwRenderer::addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
||||||
{
|
{
|
||||||
SwComposite* comp = nullptr;
|
SwCompositor* cmp = nullptr;
|
||||||
|
|
||||||
//Use cached data
|
//Use cached data
|
||||||
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
|
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
|
||||||
if ((*p)->valid) {
|
if ((*p)->valid) {
|
||||||
comp = *p;
|
cmp = *p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//New Composition
|
//New Composition
|
||||||
if (!comp) {
|
if (!cmp) {
|
||||||
comp = new SwComposite;
|
cmp = new SwCompositor;
|
||||||
if (!comp) return nullptr;
|
if (!cmp) return nullptr;
|
||||||
//SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H
|
//SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H
|
||||||
comp->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h);
|
cmp->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h);
|
||||||
if (!comp->image.data) {
|
if (!cmp->image.data) {
|
||||||
delete(comp);
|
delete(cmp);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
compositors.push(comp);
|
compositors.push(cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
comp->valid = false;
|
cmp->valid = false;
|
||||||
comp->method = method;
|
|
||||||
comp->opacity = opacity;
|
|
||||||
|
|
||||||
//Boundary Check
|
//Boundary Check
|
||||||
if (x + w > surface->w) w = (surface->w - x);
|
if (x + w > surface->w) w = (surface->w - x);
|
||||||
if (y + h > surface->h) h = (surface->h - y);
|
if (y + h > surface->h) h = (surface->h - y);
|
||||||
|
|
||||||
#ifdef THORVG_LOG_ENABLED
|
#ifdef THORVG_LOG_ENABLED
|
||||||
printf("SW_ENGINE: Using intermediate composition [Method: %d][Region: %d %d %d %d]\n", (int)method, x, y, w, h);
|
printf("SW_ENGINE: Using intermediate composition [Region: %d %d %d %d]\n", x, y, w, h);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
comp->bbox.min.x = x;
|
cmp->bbox.min.x = x;
|
||||||
comp->bbox.min.y = y;
|
cmp->bbox.min.y = y;
|
||||||
comp->bbox.max.x = x + w;
|
cmp->bbox.max.x = x + w;
|
||||||
comp->bbox.max.y = y + h;
|
cmp->bbox.max.y = y + h;
|
||||||
comp->image.w = surface->w;
|
cmp->image.w = surface->w;
|
||||||
comp->image.h = surface->h;
|
cmp->image.h = surface->h;
|
||||||
|
|
||||||
//Inherits attributes from main surface
|
//Inherits attributes from main surface
|
||||||
comp->surface.comp = surface->comp;
|
cmp->surface.blender = surface->blender;
|
||||||
comp->surface.stride = surface->w;
|
cmp->surface.stride = surface->w;
|
||||||
comp->surface.cs = surface->cs;
|
cmp->surface.cs = surface->cs;
|
||||||
|
|
||||||
//We know partial clear region
|
//We know partial clear region
|
||||||
comp->surface.buffer = comp->image.data + (comp->surface.stride * y + x);
|
cmp->surface.buffer = cmp->image.data + (cmp->surface.stride * y + x);
|
||||||
comp->surface.w = w;
|
cmp->surface.w = w;
|
||||||
comp->surface.h = h;
|
cmp->surface.h = h;
|
||||||
|
|
||||||
rasterClear(&comp->surface);
|
rasterClear(&cmp->surface);
|
||||||
|
|
||||||
//Recover context
|
//Recover context
|
||||||
comp->surface.buffer = comp->image.data;
|
cmp->surface.buffer = cmp->image.data;
|
||||||
comp->surface.w = comp->image.w;
|
cmp->surface.w = cmp->image.w;
|
||||||
comp->surface.h = comp->image.h;
|
cmp->surface.h = cmp->image.h;
|
||||||
|
|
||||||
//Switch active compositor
|
//Switch active compositor
|
||||||
comp->recover = compositor; //Backup current compositor
|
cmp->recover = compositor; //Backup current compositor
|
||||||
compositor = comp;
|
compositor = cmp;
|
||||||
|
|
||||||
//Switch render target
|
//Switch render target
|
||||||
surface = &comp->surface;
|
surface = &cmp->surface;
|
||||||
|
|
||||||
return comp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::delCompositor(void* ctx)
|
bool SwRenderer::delCompositor(Compositor* cmp)
|
||||||
{
|
{
|
||||||
if (!ctx) return false;
|
if (!cmp) return false;
|
||||||
|
|
||||||
auto comp = static_cast<SwComposite*>(ctx);
|
auto p = static_cast<SwCompositor*>(cmp);
|
||||||
comp->valid = true;
|
p->valid = true;
|
||||||
|
|
||||||
//Recover Context
|
//Recover Context
|
||||||
compositor = comp->recover;
|
compositor = p->recover;
|
||||||
surface = compositor ? &compositor->surface : mainSurface;
|
surface = compositor ? &compositor->surface : mainSurface;
|
||||||
|
|
||||||
//Default is alpha blending
|
//Default is alpha blending
|
||||||
if (comp->method == CompositeMethod::None) {
|
if (p->method == CompositeMethod::None) {
|
||||||
return rasterImage(surface, &comp->image, nullptr, comp->bbox, comp->opacity);
|
return rasterImage(surface, &p->image, nullptr, p->bbox, p->opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -460,8 +458,8 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
|
||||||
|
|
||||||
if (clips.count > 0) {
|
if (clips.count > 0) {
|
||||||
//Guarantee composition targets get ready.
|
//Guarantee composition targets get ready.
|
||||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||||
static_cast<SwShapeTask*>(*comp)->done();
|
static_cast<SwShapeTask*>(*clip)->done();
|
||||||
}
|
}
|
||||||
task->clips = clips;
|
task->clips = clips;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
struct SwSurface;
|
struct SwSurface;
|
||||||
struct SwTask;
|
struct SwTask;
|
||||||
struct SwComposite;
|
struct SwCompositor;
|
||||||
|
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
@ -36,15 +36,15 @@ class SwRenderer : public RenderMethod
|
||||||
public:
|
public:
|
||||||
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) 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;
|
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;
|
Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
|
||||||
bool delCompositor(void* cmp) override;
|
bool delCompositor(Compositor* cmp) override;
|
||||||
bool dispose(RenderData data) override;
|
bool dispose(RenderData data) override;
|
||||||
bool preRender() override;
|
bool preRender() override;
|
||||||
bool postRender() override;
|
bool postRender() override;
|
||||||
bool renderRegion(RenderData 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 clear() override;
|
||||||
bool renderShape(RenderData data, void* cmp) override;
|
bool renderShape(RenderData data, Compositor* cmp) override;
|
||||||
bool renderImage(RenderData data, void* cmp) override;
|
bool renderImage(RenderData data, Compositor* cmp) override;
|
||||||
bool sync() override;
|
bool sync() override;
|
||||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||||
|
|
||||||
|
@ -53,11 +53,11 @@ public:
|
||||||
static bool term();
|
static bool term();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SwSurface* surface = nullptr; //active surface
|
SwSurface* surface = nullptr; //active surface
|
||||||
SwComposite* compositor = nullptr; //active compositor
|
SwCompositor* compositor = nullptr; //active compositor
|
||||||
SwSurface* mainSurface = nullptr; //main (default) surface
|
SwSurface* mainSurface = nullptr; //main (default) surface
|
||||||
Array<SwTask*> tasks; //async task list
|
Array<SwTask*> tasks; //async task list
|
||||||
Array<SwComposite*> compositors; //compositor cache list
|
Array<SwCompositor*> compositors; //compositor cache list
|
||||||
|
|
||||||
SwRenderer(){};
|
SwRenderer(){};
|
||||||
~SwRenderer();
|
~SwRenderer();
|
||||||
|
|
|
@ -47,13 +47,13 @@ namespace tvg
|
||||||
RenderTransform *rTransform = nullptr;
|
RenderTransform *rTransform = nullptr;
|
||||||
uint32_t flag = RenderUpdateFlag::None;
|
uint32_t flag = RenderUpdateFlag::None;
|
||||||
|
|
||||||
Paint* compTarget = nullptr;
|
Paint* cmpTarget = nullptr;
|
||||||
CompositeMethod compMethod = CompositeMethod::None;
|
CompositeMethod cmpMethod = CompositeMethod::None;
|
||||||
|
|
||||||
uint8_t opacity = 255;
|
uint8_t opacity = 255;
|
||||||
|
|
||||||
~Impl() {
|
~Impl() {
|
||||||
if (compTarget) delete(compTarget);
|
if (cmpTarget) delete(cmpTarget);
|
||||||
if (smethod) delete(smethod);
|
if (smethod) delete(smethod);
|
||||||
if (rTransform) delete(rTransform);
|
if (rTransform) delete(rTransform);
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ namespace tvg
|
||||||
|
|
||||||
bool dispose(RenderMethod& renderer)
|
bool dispose(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
if (compTarget) compTarget->pImpl->dispose(renderer);
|
if (cmpTarget) cmpTarget->pImpl->dispose(renderer);
|
||||||
return smethod->dispose(renderer);
|
return smethod->dispose(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,11 +147,11 @@ namespace tvg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *compdata = nullptr;
|
void *cmpData = nullptr;
|
||||||
|
|
||||||
if (compTarget) {
|
if (cmpTarget) {
|
||||||
compdata = compTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
|
cmpData = cmpTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
|
||||||
if (compMethod == CompositeMethod::ClipPath) clips.push(compdata);
|
if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *edata = nullptr;
|
void *edata = nullptr;
|
||||||
|
@ -167,21 +167,23 @@ namespace tvg
|
||||||
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
|
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compdata) clips.pop();
|
if (cmpData) clips.pop();
|
||||||
|
|
||||||
return edata;
|
return edata;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render(RenderMethod& renderer)
|
bool render(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
void* cmp = nullptr;
|
Compositor* cmp = nullptr;
|
||||||
|
|
||||||
/* Note: only ClipPath is processed in update() step */
|
/* Note: only ClipPath is processed in update() step */
|
||||||
if (compTarget && compMethod != CompositeMethod::ClipPath) {
|
if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) {
|
||||||
uint32_t x, y, w, h;
|
uint32_t x, y, w, h;
|
||||||
if (!compTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
|
if (!cmpTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
|
||||||
cmp = renderer.addCompositor(compMethod, x, y, w, h, 255);
|
cmp = renderer.addCompositor(x, y, w, h);
|
||||||
compTarget->pImpl->render(renderer);
|
cmp->method = CompositeMethod::None;
|
||||||
|
cmp->opacity = 255;
|
||||||
|
cmpTarget->pImpl->render(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = smethod->render(renderer);
|
auto ret = smethod->render(renderer);
|
||||||
|
@ -213,8 +215,8 @@ namespace tvg
|
||||||
{
|
{
|
||||||
if (!target && method != CompositeMethod::None) return false;
|
if (!target && method != CompositeMethod::None) return false;
|
||||||
if (target && method == CompositeMethod::None) return false;
|
if (target && method == CompositeMethod::None) return false;
|
||||||
compTarget = target;
|
cmpTarget = target;
|
||||||
compMethod = method;
|
cmpMethod = method;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,11 @@ struct Surface
|
||||||
|
|
||||||
using RenderData = void*;
|
using RenderData = void*;
|
||||||
|
|
||||||
|
struct Compositor {
|
||||||
|
CompositeMethod method;
|
||||||
|
uint32_t opacity;
|
||||||
|
};
|
||||||
|
|
||||||
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64};
|
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64};
|
||||||
|
|
||||||
struct RenderTransform
|
struct RenderTransform
|
||||||
|
@ -57,18 +62,17 @@ struct RenderTransform
|
||||||
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderMethod
|
struct RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
virtual ~RenderMethod() {}
|
virtual ~RenderMethod() {}
|
||||||
virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 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 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 Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) = 0;
|
||||||
virtual bool delCompositor(void* cmp) = 0;
|
virtual bool delCompositor(Compositor* cmp) = 0;
|
||||||
virtual bool dispose(RenderData data) = 0;
|
virtual bool dispose(RenderData data) = 0;
|
||||||
virtual bool preRender() = 0;
|
virtual bool preRender() = 0;
|
||||||
virtual bool renderShape(RenderData data, void* cmp) = 0;
|
virtual bool renderShape(RenderData data, Compositor* cmp) = 0;
|
||||||
virtual bool renderImage(RenderData data, void* cmp) = 0;
|
virtual bool renderImage(RenderData data, Compositor* cmp) = 0;
|
||||||
virtual bool postRender() = 0;
|
virtual bool postRender() = 0;
|
||||||
virtual bool renderRegion(RenderData 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 clear() = 0;
|
||||||
|
|
|
@ -63,14 +63,16 @@ struct Scene::Impl
|
||||||
|
|
||||||
bool render(RenderMethod& renderer)
|
bool render(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
void* cmp = nullptr;
|
Compositor* cmp = nullptr;
|
||||||
|
|
||||||
//Half translucent. This condition requires intermediate composition.
|
//Half translucent. This condition requires intermediate composition.
|
||||||
if (opacity < 255 && opacity > 0 && (paints.count > 1)) {
|
if (opacity < 255 && opacity > 0 && (paints.count > 1)) {
|
||||||
uint32_t x, y, w, h;
|
uint32_t x, y, w, h;
|
||||||
if (!bounds(renderer, &x, &y, &w, &h)) return false;
|
if (!bounds(renderer, &x, &y, &w, &h)) return false;
|
||||||
//CompositeMethod::None is used for a default alpha blending
|
//CompositeMethod::None is used for a default alpha blending
|
||||||
cmp = renderer.addCompositor(CompositeMethod::None, x, y, w, h, opacity);
|
cmp = renderer.addCompositor(x, y, w, h);
|
||||||
|
cmp->method = CompositeMethod::None;
|
||||||
|
cmp->opacity = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue