From d701f6dae4d76ad8988ffc88ddfe5e2cf4e1f23a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 28 Jan 2023 11:36:54 +0900 Subject: [PATCH] common: enhance clipping behavior. If a paint is used as a clipper, it must be determined in the paint behavior. Propagate its decision to the immediate derived classes so that not only shapes but also scenes must be dealt as a clipper properly. This revised this change 0de3872be33793d2c8db03d5b85da38670410626 for better a solution. --- src/lib/gl_engine/tvgGlRenderer.cpp | 2 +- src/lib/gl_engine/tvgGlRenderer.h | 2 +- src/lib/sw_engine/tvgSwRenderer.cpp | 14 +++++++------- src/lib/sw_engine/tvgSwRenderer.h | 2 +- src/lib/tvgPaint.cpp | 9 +++++---- src/lib/tvgPaint.h | 8 ++++---- src/lib/tvgPictureImpl.h | 4 ++-- src/lib/tvgRender.h | 2 +- src/lib/tvgSceneImpl.h | 4 ++-- src/lib/tvgShapeImpl.h | 4 ++-- 10 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 5537cc2e..e2c436ea 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -197,7 +197,7 @@ RenderData GlRenderer::prepare(TVG_UNUSED Surface* image, TVG_UNUSED Polygon* tr } -RenderData GlRenderer::prepare(const Shape& shape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array& clips, RenderUpdateFlag flags) +RenderData GlRenderer::prepare(const Shape& shape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array& clips, RenderUpdateFlag flags, TVG_UNUSED bool clipper) { //prepare shape data GlShape* sdata = static_cast(data); diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index 8542913a..26885663 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -30,7 +30,7 @@ class GlRenderer : public RenderMethod public: Surface surface = {nullptr, 0, 0, 0}; - RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; + RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) override; RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; bool preRender() override; bool renderShape(RenderData data) override; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index a303d2d3..93d0d5dd 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -74,12 +74,11 @@ struct SwShapeTask : SwTask SwShape shape; const Shape* sdata = nullptr; bool cmpStroking = false; + bool clipper = false; void run(unsigned tid) override - { - auto compMethod = CompositeMethod::None; - auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath); - if (opacity == 0 && !usedAsClip) return; //Invisible + { + if (opacity == 0 && !clipper) return; //Invisible uint8_t strokeAlpha = 0; auto visibleStroke = false; @@ -101,7 +100,7 @@ struct SwShapeTask : SwTask sdata->fillColor(nullptr, nullptr, nullptr, &alpha); alpha = static_cast(static_cast(alpha) * opacity / 255); visibleFill = (alpha > 0 || sdata->fill()); - if (visibleFill || visibleStroke || usedAsClip) { + if (visibleFill || visibleStroke || clipper) { shapeReset(&shape); if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err; } @@ -113,7 +112,7 @@ struct SwShapeTask : SwTask //Fill if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { - if (visibleFill || usedAsClip) { + if (visibleFill || clipper) { /* We assume that if stroke width is bigger than 2, shape outline below stroke could be full covered by stroke drawing. Thus it turns off antialising in that condition. @@ -644,13 +643,14 @@ RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t tria } -RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) +RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) { //prepare task auto task = static_cast(data); if (!task) { task = new SwShapeTask; task->sdata = &sdata; + task->clipper = clipper; } return prepareCommon(task, transform, opacity, clips, flags); } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 460659c6..819141f2 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -36,7 +36,7 @@ namespace tvg class SwRenderer : public RenderMethod { public: - RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; + RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) override; RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; bool preRender() override; bool renderShape(RenderData data) override; diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index ba5b0500..0b491223 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -184,7 +184,7 @@ bool Paint::Impl::render(RenderMethod& renderer) } -void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, uint32_t pFlag) +void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, uint32_t pFlag, bool clipper) { if (renderFlag & RenderUpdateFlag::Transform) { if (!rTransform) return nullptr; @@ -224,7 +224,8 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } } if (!compFastTrack) { - tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag); + auto clipper = compData->method == CompositeMethod::ClipPath ? true : false; + tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag, clipper); if (method == CompositeMethod::ClipPath) clips.push(tdata); } } @@ -237,10 +238,10 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf if (rTransform && pTransform) { RenderTransform outTransform(pTransform, rTransform); - edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag); + edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag, clipper); } else { auto outTransform = pTransform ? pTransform : rTransform; - edata = smethod->update(renderer, outTransform, opacity, clips, newFlag); + edata = smethod->update(renderer, outTransform, opacity, clips, newFlag, clipper); } /* 3. Composition Post Processing */ diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index a0bd3c96..45c679d2 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -43,7 +43,7 @@ namespace tvg virtual ~StrategyMethod() {} virtual bool dispose(RenderMethod& renderer) = 0; - virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) = 0; //Return engine data if it has. + virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has. virtual bool render(RenderMethod& renderer) = 0; virtual bool bounds(float* x, float* y, float* w, float* h) = 0; virtual RenderRegion bounds(RenderMethod& renderer) const = 0; @@ -149,7 +149,7 @@ namespace tvg bool scale(float factor); bool translate(float x, float y); bool bounds(float* x, float* y, float* w, float* h, bool transformed); - void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, uint32_t pFlag); + void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, uint32_t pFlag, bool clipper = false); bool render(RenderMethod& renderer); Paint* duplicate(); }; @@ -178,9 +178,9 @@ namespace tvg return inst->dispose(renderer); } - void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag renderFlag) override + void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag renderFlag, bool clipper) override { - return inst->update(renderer, transform, opacity, clips, renderFlag); + return inst->update(renderer, transform, opacity, clips, renderFlag, clipper); } bool render(RenderMethod& renderer) override diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index e0395325..b7e2ba03 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -126,7 +126,7 @@ struct Picture::Impl else return RenderTransform(pTransform, &tmp); } - void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) + void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag, bool clipper) { auto flag = reload(); @@ -138,7 +138,7 @@ struct Picture::Impl loader->resize(paint, w, h); resizing = false; } - rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast(pFlag | flag)); + rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast(pFlag | flag), clipper); } return rdata; } diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 34e3101c..88fe5025 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -90,7 +90,7 @@ class RenderMethod { public: virtual ~RenderMethod() {} - virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; + virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) = 0; virtual RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; virtual bool preRender() = 0; virtual bool renderShape(RenderData data) = 0; diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 8c9b50ee..4265ff7f 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -102,7 +102,7 @@ struct Scene::Impl return false; } - void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flag) + void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flag, bool clipper) { /* Overriding opacity value. If this scene is half-translucent, It must do intermeidate composition with that opacity value. */ @@ -110,7 +110,7 @@ struct Scene::Impl if (needComposition(opacity)) opacity = 255; for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { - (*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast(flag)); + (*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast(flag), clipper); } /* FXIME: it requires to return list of children engine data diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index 8e1fe08b..fa2786f1 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -235,9 +235,9 @@ struct Shape::Impl return renderer.renderShape(rdata); } - void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag) + void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag pFlag, bool clipper) { - this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast(pFlag | flag)); + this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast(pFlag | flag), clipper); flag = RenderUpdateFlag::None; return this->rdata; }