diff --git a/inc/thorvg.h b/inc/thorvg.h index dd5c05fe..ab036986 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -70,6 +70,7 @@ protected: \ #define _TVG_DECLARE_ACCESSOR() \ friend Canvas; \ friend Scene; \ + friend Shape; \ friend Picture; \ friend Accessor; \ friend IteratorAccessor @@ -81,6 +82,7 @@ namespace tvg class RenderMethod; class IteratorAccessor; class Scene; +class Shape; class Picture; class Canvas; class Accessor; diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 1caf3a4c..e527cf06 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -142,8 +142,9 @@ struct Picture::Impl const Paint* target; auto method = picture->composite(&target); if (!target || method == tvg::CompositeMethod::ClipPath) return false; - if (target->pImpl->opacity < 255 && target->pImpl->opacity > 0) return true; - return false; + if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false; + + return true; } RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag, bool clipper) diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index 114ff61e..56dfa2b7 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -32,7 +32,7 @@ constexpr auto PATH_KAPPA = 0.552284f; /* External Class Implementation */ /************************************************************************/ -Shape :: Shape() : pImpl(new Impl()) +Shape :: Shape() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_SHAPE; Paint::pImpl->method(new PaintMethod(pImpl)); diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index da288756..a8a1d211 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -35,6 +35,12 @@ struct Shape::Impl RenderShape rs; //shape data RenderData rd = nullptr; //engine data uint32_t flag = RenderUpdateFlag::None; + Shape* shape; + bool needComp; //for composition + + Impl(Shape* s) : shape(s) + { + } bool dispose(RenderMethod& renderer) { @@ -45,11 +51,40 @@ struct Shape::Impl 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& clips, RenderUpdateFlag pFlag, bool clipper) { + needComp = needComposition(opacity); + rd = renderer.prepare(rs, rd, transform, opacity, clips, static_cast(pFlag | flag), clipper); flag = RenderUpdateFlag::None; return rd;