From 8585b27abfa112a339a1b9348e5005224b4c07d9 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 14 Dec 2024 01:02:12 +0900 Subject: [PATCH] sw_engine: fixed a rendering bug when the invalid clipper is applied. Shapes with boundaries outside the rendering area are ignored as non-visible. The issue arises when such a shape serves as a clipper. The expected behavior is for the entire clipee to be cut out, but previously, the clipee remained fully visible as if no clip was applied. The fix identifies these clippers and skips rendering clipees. Please note that we can skip rendering at the Paint update stage if the clipper's viewport is outside the canvas. This optimization can improve performance, but only for this specific case. The downside of the approach is that it disrupts multi-processing for clipper updates. As a result, that approach was discarded. issue: https://github.com/thorvg/thorvg/issues/3003 issue: https://github.com/thorvg/thorvg/issues/2684 Co-Authored-By: Mira Grudzinska --- src/renderer/sw_engine/tvgSwCommon.h | 4 ++-- src/renderer/sw_engine/tvgSwRenderer.cpp | 14 +++++--------- src/renderer/sw_engine/tvgSwRle.cpp | 12 ++++++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index 5b63e3a6..e0f6a848 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -547,8 +547,8 @@ SwRle* rleRender(const SwBBox* bbox); void rleFree(SwRle* rle); void rleReset(SwRle* rle); void rleMerge(SwRle* rle, SwRle* clip1, SwRle* clip2); -void rleClip(SwRle* rle, const SwRle* clip); -void rleClip(SwRle* rle, const SwBBox* clip); +bool rleClip(SwRle* rle, const SwRle* clip); +bool rleClip(SwRle* rle, const SwBBox* clip); SwMpool* mpoolInit(uint32_t threads); bool mpoolTerm(SwMpool* mpool); diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index fd4cf871..8257ba55 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -103,11 +103,9 @@ struct SwShapeTask : SwTask bool clip(SwRle* target) override { - if (shape.fastTrack) rleClip(target, &bbox); - else if (shape.rle) rleClip(target, shape.rle); - else return false; - - return true; + if (shape.fastTrack) return rleClip(target, &bbox); + else if (shape.rle) return rleClip(target, shape.rle); + return false; } void run(unsigned tid) override @@ -177,10 +175,8 @@ struct SwShapeTask : SwTask //Clip Path for (auto clip = clips.begin(); clip < clips.end(); ++clip) { auto clipper = static_cast(*clip); - //Clip shape rle - if (shape.rle && !clipper->clip(shape.rle)) goto err; - //Clip stroke rle - if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err; + if (shape.rle && !clipper->clip(shape.rle)) goto err; //Clip shape rle + if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err; //Clip stroke rle } bbox = renderRegion; //sync diff --git a/src/renderer/sw_engine/tvgSwRle.cpp b/src/renderer/sw_engine/tvgSwRle.cpp index c57e98bc..90b536af 100644 --- a/src/renderer/sw_engine/tvgSwRle.cpp +++ b/src/renderer/sw_engine/tvgSwRle.cpp @@ -1020,9 +1020,9 @@ void rleFree(SwRle* rle) } -void rleClip(SwRle *rle, const SwRle *clip) +bool rleClip(SwRle *rle, const SwRle *clip) { - if (rle->size == 0 || clip->size == 0) return; + if (rle->size == 0 || clip->size == 0) return false; auto spanCnt = rle->size > clip->size ? rle->size : clip->size; auto spans = static_cast(malloc(sizeof(SwSpan) * (spanCnt))); auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt); @@ -1030,17 +1030,21 @@ void rleClip(SwRle *rle, const SwRle *clip) _replaceClipSpan(rle, spans, spansEnd - spans); TVGLOG("SW_ENGINE", "Using Path Clipping!"); + + return true; } -void rleClip(SwRle *rle, const SwBBox* clip) +bool rleClip(SwRle *rle, const SwBBox* clip) { - if (rle->size == 0) return; + if (rle->size == 0) return false; auto spans = static_cast(malloc(sizeof(SwSpan) * (rle->size))); auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size); _replaceClipSpan(rle, spans, spansEnd - spans); TVGLOG("SW_ENGINE", "Using Box Clipping!"); + + return true; }