mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-16 04:54:39 +00:00
common sw_engine: gather scattered stroking composition.
There are two branches for completing stroke composition between the canvas and sw_engine. It is necessary to centralize the task on the canvas engine side so that we can maintain the logic without confusion.
This commit is contained in:
parent
3626ded041
commit
89db13037d
3 changed files with 30 additions and 38 deletions
|
@ -125,10 +125,6 @@ struct SwShapeTask : SwTask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Decide Stroking Composition
|
|
||||||
if (visibleStroke && visibleFill && opacity < 255) cmpStroking = true;
|
|
||||||
else cmpStroking = false;
|
|
||||||
|
|
||||||
//Fill
|
//Fill
|
||||||
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
|
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
|
||||||
if (visibleFill || clipper) {
|
if (visibleFill || clipper) {
|
||||||
|
@ -143,7 +139,7 @@ struct SwShapeTask : SwTask
|
||||||
if (auto fill = rshape->fill) {
|
if (auto fill = rshape->fill) {
|
||||||
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
||||||
if (ctable) shapeResetFill(&shape);
|
if (ctable) shapeResetFill(&shape);
|
||||||
if (!shapeGenFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
|
if (!shapeGenFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err;
|
||||||
} else {
|
} else {
|
||||||
shapeDelFill(&shape);
|
shapeDelFill(&shape);
|
||||||
}
|
}
|
||||||
|
@ -158,7 +154,7 @@ struct SwShapeTask : SwTask
|
||||||
if (auto fill = rshape->strokeFill()) {
|
if (auto fill = rshape->strokeFill()) {
|
||||||
auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false;
|
auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false;
|
||||||
if (ctable) shapeResetStrokeFill(&shape);
|
if (ctable) shapeResetStrokeFill(&shape);
|
||||||
if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
|
if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err;
|
||||||
} else {
|
} else {
|
||||||
shapeDelStrokeFill(&shape);
|
shapeDelStrokeFill(&shape);
|
||||||
}
|
}
|
||||||
|
@ -490,30 +486,15 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
|
|
||||||
if (task->opacity == 0) return true;
|
if (task->opacity == 0) return true;
|
||||||
|
|
||||||
uint32_t opacity;
|
|
||||||
Compositor* cmp = nullptr;
|
|
||||||
|
|
||||||
//Do Stroking Composition
|
|
||||||
if (task->cmpStroking) {
|
|
||||||
opacity = 255;
|
|
||||||
cmp = target(task->bounds(), colorSpace());
|
|
||||||
beginComposite(cmp, CompositeMethod::None, task->opacity);
|
|
||||||
//No Stroking Composition
|
|
||||||
} else {
|
|
||||||
opacity = task->opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Main raster stage
|
//Main raster stage
|
||||||
if (task->rshape->stroke && task->rshape->stroke->strokeFirst) {
|
if (task->rshape->stroke && task->rshape->stroke->strokeFirst) {
|
||||||
_renderStroke(task, surface, opacity);
|
_renderStroke(task, surface, task->opacity);
|
||||||
_renderFill(task, surface, opacity);
|
_renderFill(task, surface, task->opacity);
|
||||||
} else {
|
} else {
|
||||||
_renderFill(task, surface, opacity);
|
_renderFill(task, surface, task->opacity);
|
||||||
_renderStroke(task, surface, opacity);
|
_renderStroke(task, surface, task->opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->cmpStroking) endComposite(cmp);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct Scene::Impl
|
||||||
RenderData rd = nullptr;
|
RenderData rd = nullptr;
|
||||||
Scene* scene = nullptr;
|
Scene* scene = nullptr;
|
||||||
uint8_t opacity; //for composition
|
uint8_t opacity; //for composition
|
||||||
|
bool needComp; //composite or not
|
||||||
|
|
||||||
Impl(Scene* s) : scene(s)
|
Impl(Scene* s) : scene(s)
|
||||||
{
|
{
|
||||||
|
@ -109,10 +110,12 @@ struct Scene::Impl
|
||||||
|
|
||||||
RenderData update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag, bool clipper)
|
RenderData update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag, bool clipper)
|
||||||
{
|
{
|
||||||
|
if ((needComp = needComposition(opacity))) {
|
||||||
/* Overriding opacity value. If this scene is half-translucent,
|
/* Overriding opacity value. If this scene is half-translucent,
|
||||||
It must do intermeidate composition with that opacity value. */
|
It must do intermeidate composition with that opacity value. */
|
||||||
this->opacity = static_cast<uint8_t>(opacity);
|
this->opacity = static_cast<uint8_t>(opacity);
|
||||||
if (needComposition(opacity)) opacity = 255;
|
opacity = 255;
|
||||||
|
}
|
||||||
|
|
||||||
this->renderer = &renderer;
|
this->renderer = &renderer;
|
||||||
|
|
||||||
|
@ -136,7 +139,7 @@ struct Scene::Impl
|
||||||
{
|
{
|
||||||
Compositor* cmp = nullptr;
|
Compositor* cmp = nullptr;
|
||||||
|
|
||||||
if (needComposition(opacity)) {
|
if (needComp) {
|
||||||
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
||||||
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ struct Shape::Impl
|
||||||
RenderData rd = nullptr; //engine data
|
RenderData rd = nullptr; //engine data
|
||||||
uint32_t flag = RenderUpdateFlag::None;
|
uint32_t flag = RenderUpdateFlag::None;
|
||||||
Shape* shape;
|
Shape* shape;
|
||||||
bool needComp; //for composition
|
uint8_t opacity; //for composition
|
||||||
|
bool needComp; //composite or not
|
||||||
|
|
||||||
Impl(Shape* s) : shape(s)
|
Impl(Shape* s) : shape(s)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +57,7 @@ struct Shape::Impl
|
||||||
|
|
||||||
if (needComp) {
|
if (needComp) {
|
||||||
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
||||||
renderer.beginComposite(cmp, CompositeMethod::None, 255);
|
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
||||||
}
|
}
|
||||||
ret = renderer.renderShape(rd);
|
ret = renderer.renderShape(rd);
|
||||||
if (cmp) renderer.endComposite(cmp);
|
if (cmp) renderer.endComposite(cmp);
|
||||||
|
@ -65,12 +66,14 @@ struct Shape::Impl
|
||||||
|
|
||||||
bool needComposition(uint32_t opacity)
|
bool needComposition(uint32_t opacity)
|
||||||
{
|
{
|
||||||
//In this case, paint(shape) would try composition by backends. (See: SwShapeTask::run())
|
if (opacity == 0) return false;
|
||||||
//TODO: that composition should be moved here?
|
|
||||||
if (opacity < 255) return false;
|
|
||||||
|
|
||||||
//Shape composition is only necessary when stroking is valid.
|
//Shape composition is only necessary when stroking & fill are valid.
|
||||||
if (!rs.stroke || rs.stroke->width < FLT_EPSILON || rs.stroke->color[3] == 0) return false;
|
if (!rs.stroke || rs.stroke->width < FLT_EPSILON || rs.stroke->color[3] == 0) return false;
|
||||||
|
if (!rs.fill && rs.color[3] == 0) return false;
|
||||||
|
|
||||||
|
//translucent fill & stroke
|
||||||
|
if (opacity < 255) return true;
|
||||||
|
|
||||||
//Composition test
|
//Composition test
|
||||||
const Paint* target;
|
const Paint* target;
|
||||||
|
@ -83,7 +86,12 @@ struct Shape::Impl
|
||||||
|
|
||||||
RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
needComp = needComposition(opacity);
|
if ((needComp = needComposition(opacity))) {
|
||||||
|
/* Overriding opacity value. If this scene is half-translucent,
|
||||||
|
It must do intermeidate composition with that opacity value. */
|
||||||
|
this->opacity = static_cast<uint8_t>(opacity);
|
||||||
|
opacity = 255;
|
||||||
|
}
|
||||||
|
|
||||||
rd = renderer.prepare(rs, rd, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
rd = renderer.prepare(rs, rd, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
||||||
flag = RenderUpdateFlag::None;
|
flag = RenderUpdateFlag::None;
|
||||||
|
|
Loading…
Add table
Reference in a new issue