mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-25 07:39:02 +00:00
common shape: fixing stroking composition issue.
When combining Shape, Stroke, and AlphaMasking, there is a missing composition step which results in an incorrect output as expected by the user. This problem is resolved by introducing shape fill and stroking composition. @Issue: https://github.com/thorvg/thorvg/issues/209
This commit is contained in:
parent
4938c3253c
commit
6994925b9d
4 changed files with 42 additions and 4 deletions
|
@ -70,6 +70,7 @@ protected: \
|
||||||
#define _TVG_DECLARE_ACCESSOR() \
|
#define _TVG_DECLARE_ACCESSOR() \
|
||||||
friend Canvas; \
|
friend Canvas; \
|
||||||
friend Scene; \
|
friend Scene; \
|
||||||
|
friend Shape; \
|
||||||
friend Picture; \
|
friend Picture; \
|
||||||
friend Accessor; \
|
friend Accessor; \
|
||||||
friend IteratorAccessor
|
friend IteratorAccessor
|
||||||
|
@ -81,6 +82,7 @@ namespace tvg
|
||||||
class RenderMethod;
|
class RenderMethod;
|
||||||
class IteratorAccessor;
|
class IteratorAccessor;
|
||||||
class Scene;
|
class Scene;
|
||||||
|
class Shape;
|
||||||
class Picture;
|
class Picture;
|
||||||
class Canvas;
|
class Canvas;
|
||||||
class Accessor;
|
class Accessor;
|
||||||
|
|
|
@ -142,8 +142,9 @@ struct Picture::Impl
|
||||||
const Paint* target;
|
const Paint* target;
|
||||||
auto method = picture->composite(&target);
|
auto method = picture->composite(&target);
|
||||||
if (!target || method == tvg::CompositeMethod::ClipPath) return false;
|
if (!target || method == tvg::CompositeMethod::ClipPath) return false;
|
||||||
if (target->pImpl->opacity < 255 && target->pImpl->opacity > 0) return true;
|
if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false;
|
||||||
return false;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
||||||
|
|
|
@ -32,7 +32,7 @@ constexpr auto PATH_KAPPA = 0.552284f;
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
Shape :: Shape() : pImpl(new Impl())
|
Shape :: Shape() : pImpl(new Impl(this))
|
||||||
{
|
{
|
||||||
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
|
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
|
||||||
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
|
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
|
||||||
|
|
|
@ -35,6 +35,12 @@ struct Shape::Impl
|
||||||
RenderShape rs; //shape data
|
RenderShape rs; //shape data
|
||||||
RenderData rd = nullptr; //engine data
|
RenderData rd = nullptr; //engine data
|
||||||
uint32_t flag = RenderUpdateFlag::None;
|
uint32_t flag = RenderUpdateFlag::None;
|
||||||
|
Shape* shape;
|
||||||
|
bool needComp; //for composition
|
||||||
|
|
||||||
|
Impl(Shape* s) : shape(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool dispose(RenderMethod& renderer)
|
bool dispose(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
|
@ -45,11 +51,40 @@ struct Shape::Impl
|
||||||
|
|
||||||
bool render(RenderMethod& renderer)
|
bool render(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
return renderer.renderShape(rd);
|
Compositor* cmp = nullptr;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
if (needComp) {
|
||||||
|
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
||||||
|
renderer.beginComposite(cmp, CompositeMethod::None, 255);
|
||||||
|
}
|
||||||
|
ret = renderer.renderShape(rd);
|
||||||
|
if (cmp) renderer.endComposite(cmp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needComposition(uint32_t opacity)
|
||||||
|
{
|
||||||
|
//In this case, paint(shape) would try composition by backends. (See: SwShapeTask::run())
|
||||||
|
//TODO: that composition should be moved here?
|
||||||
|
if (opacity < 255) return false;
|
||||||
|
|
||||||
|
//Shape composition is only necessary when stroking is valid.
|
||||||
|
if (!rs.stroke || rs.stroke->width < FLT_EPSILON || rs.stroke->color[3] == 0) return false;
|
||||||
|
|
||||||
|
//Composition test
|
||||||
|
const Paint* target;
|
||||||
|
auto method = shape->composite(&target);
|
||||||
|
if (!target || method == tvg::CompositeMethod::ClipPath) return false;
|
||||||
|
if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
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;
|
||||||
return rd;
|
return rd;
|
||||||
|
|
Loading…
Add table
Reference in a new issue