mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-15 04:24:28 +00:00
sw_engine renderer: refactoring code & optimize composition.
Move the prepare stage of shape & stroking composition stage to a separate function this returns SwImage to use in composite stage. Also clear partial region buffer since we know composition area.
This commit is contained in:
parent
3881f20e9c
commit
ceb14e73a8
3 changed files with 56 additions and 37 deletions
|
@ -91,6 +91,7 @@ static SwBBox _clipRegion(Surface* surface, SwBBox& in)
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
||||||
{
|
{
|
||||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
@ -502,7 +503,7 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, ui
|
||||||
Matrix invTransform;
|
Matrix invTransform;
|
||||||
|
|
||||||
if (transform) _inverse(transform, &invTransform);
|
if (transform) _inverse(transform, &invTransform);
|
||||||
else invTransform = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
|
else invTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
|
|
||||||
if (image->rle) {
|
if (image->rle) {
|
||||||
if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, image->w, image->h, opacity, &invTransform);
|
if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, image->w, image->h, opacity, &invTransform);
|
||||||
|
|
|
@ -268,6 +268,54 @@ bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SwRenderer::prepareComposite(const SwShapeTask* task, SwImage* image)
|
||||||
|
{
|
||||||
|
if (!compSurface) {
|
||||||
|
compSurface = new SwSurface;
|
||||||
|
if (!compSurface) return false;
|
||||||
|
*compSurface = *mainSurface;
|
||||||
|
compSurface->buffer = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->w * mainSurface->h);
|
||||||
|
if (!compSurface->buffer) {
|
||||||
|
delete(compSurface);
|
||||||
|
compSurface = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup SwImage to return
|
||||||
|
image->data = compSurface->buffer;
|
||||||
|
image->w = compSurface->w;
|
||||||
|
image->h = compSurface->h;
|
||||||
|
image->rle = nullptr;
|
||||||
|
|
||||||
|
//Add stroke size to bounding box.
|
||||||
|
auto strokeWidth = static_cast<SwCoord>(ceilf(task->sdata->strokeWidth() * 0.5f));
|
||||||
|
image->bbox.min.x = task->shape.bbox.min.x - strokeWidth;
|
||||||
|
image->bbox.min.y = task->shape.bbox.min.y - strokeWidth;
|
||||||
|
image->bbox.max.x = task->shape.bbox.max.x + strokeWidth;
|
||||||
|
image->bbox.max.y = task->shape.bbox.max.y + strokeWidth;
|
||||||
|
|
||||||
|
if (image->bbox.min.x < 0) image->bbox.min.x = 0;
|
||||||
|
if (image->bbox.min.y < 0) image->bbox.min.y = 0;
|
||||||
|
if (image->bbox.max.x > image->w) image->bbox.max.x = image->w;
|
||||||
|
if (image->bbox.max.y > image->h) image->bbox.max.y = image->h;
|
||||||
|
|
||||||
|
//We know partial clear region
|
||||||
|
compSurface->buffer = compSurface->buffer + (compSurface->stride * image->bbox.min.y) + image->bbox.min.x;
|
||||||
|
compSurface->w = image->bbox.max.x - image->bbox.min.x;
|
||||||
|
compSurface->h = image->bbox.max.y - image->bbox.min.y;
|
||||||
|
|
||||||
|
rasterClear(compSurface);
|
||||||
|
|
||||||
|
//Recover context
|
||||||
|
compSurface->buffer = image->data;
|
||||||
|
compSurface->w = image->w;
|
||||||
|
compSurface->h = image->h;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
|
bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
|
||||||
{
|
{
|
||||||
auto task = static_cast<SwShapeTask*>(data);
|
auto task = static_cast<SwShapeTask*>(data);
|
||||||
|
@ -276,32 +324,18 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
|
||||||
if (task->opacity == 0) return true;
|
if (task->opacity == 0) return true;
|
||||||
|
|
||||||
SwSurface* renderTarget;
|
SwSurface* renderTarget;
|
||||||
|
SwImage image;
|
||||||
uint32_t opacity;
|
uint32_t opacity;
|
||||||
bool composite;
|
|
||||||
|
|
||||||
//Do Composition
|
//Do Composition
|
||||||
if (task->compStroking) {
|
if (task->compStroking) {
|
||||||
//Setup Composition Surface
|
if (!prepareComposite(task, &image)) return false;
|
||||||
if (!compSurface) {
|
|
||||||
compSurface = new SwSurface;
|
|
||||||
if (!compSurface) return false;
|
|
||||||
*compSurface = *mainSurface;
|
|
||||||
compSurface->buffer = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->stride * mainSurface->h);
|
|
||||||
if (!compSurface->buffer) {
|
|
||||||
delete(compSurface);
|
|
||||||
compSurface = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rasterClear(compSurface);
|
|
||||||
renderTarget = compSurface;
|
renderTarget = compSurface;
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
composite = true;
|
|
||||||
//No Composition
|
//No Composition
|
||||||
} else {
|
} else {
|
||||||
renderTarget = mainSurface;
|
renderTarget = mainSurface;
|
||||||
opacity = task->opacity;
|
opacity = task->opacity;
|
||||||
composite = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Main raster stage
|
//Main raster stage
|
||||||
|
@ -321,26 +355,7 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
|
||||||
if (a > 0) rasterStroke(renderTarget, &task->shape, r, g, b, a);
|
if (a > 0) rasterStroke(renderTarget, &task->shape, r, g, b, a);
|
||||||
|
|
||||||
//Composition (Shape + Stroke) stage
|
//Composition (Shape + Stroke) stage
|
||||||
if (composite) {
|
if (task->compStroking) rasterImage(mainSurface, &image, nullptr, task->opacity);
|
||||||
SwImage image;
|
|
||||||
image.data = compSurface->buffer;
|
|
||||||
image.w = compSurface->w;
|
|
||||||
image.h = compSurface->h;
|
|
||||||
image.rle = nullptr;
|
|
||||||
|
|
||||||
//Add stroke size to bounding box.
|
|
||||||
auto strokeWidth = static_cast<SwCoord>(ceilf(task->sdata->strokeWidth() * 0.5f));
|
|
||||||
image.bbox.min.x = task->shape.bbox.min.x - strokeWidth;
|
|
||||||
image.bbox.min.y = task->shape.bbox.min.y - strokeWidth;
|
|
||||||
image.bbox.max.x = task->shape.bbox.max.x + strokeWidth;
|
|
||||||
image.bbox.max.y = task->shape.bbox.max.y + strokeWidth;
|
|
||||||
if (image.bbox.min.x < 0) image.bbox.min.x = 0;
|
|
||||||
if (image.bbox.min.y < 0) image.bbox.min.y = 0;
|
|
||||||
if (image.bbox.max.x > compSurface->w) image.bbox.max.x = compSurface->w;
|
|
||||||
if (image.bbox.max.y > compSurface->h) image.bbox.max.y = compSurface->h;
|
|
||||||
|
|
||||||
rasterImage(mainSurface, &image, nullptr, task->opacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
struct SwSurface;
|
struct SwSurface;
|
||||||
struct SwTask;
|
struct SwTask;
|
||||||
|
struct SwShapeTask;
|
||||||
|
struct SwImage;
|
||||||
|
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
@ -56,6 +58,7 @@ private:
|
||||||
SwRenderer(){};
|
SwRenderer(){};
|
||||||
~SwRenderer();
|
~SwRenderer();
|
||||||
|
|
||||||
|
bool prepareComposite(const SwShapeTask* task, SwImage* image);
|
||||||
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
|
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue