mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
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 <mira@lottiefiles.com>
This commit is contained in:
parent
e395961f3b
commit
01f4d6304a
3 changed files with 15 additions and 15 deletions
|
@ -543,8 +543,8 @@ SwRle* rleRender(const SwBBox* bbox);
|
||||||
void rleFree(SwRle* rle);
|
void rleFree(SwRle* rle);
|
||||||
void rleReset(SwRle* rle);
|
void rleReset(SwRle* rle);
|
||||||
void rleMerge(SwRle* rle, SwRle* clip1, SwRle* clip2);
|
void rleMerge(SwRle* rle, SwRle* clip1, SwRle* clip2);
|
||||||
void rleClip(SwRle* rle, const SwRle* clip);
|
bool rleClip(SwRle* rle, const SwRle* clip);
|
||||||
void rleClip(SwRle* rle, const SwBBox* clip);
|
bool rleClip(SwRle* rle, const SwBBox* clip);
|
||||||
|
|
||||||
SwMpool* mpoolInit(uint32_t threads);
|
SwMpool* mpoolInit(uint32_t threads);
|
||||||
bool mpoolTerm(SwMpool* mpool);
|
bool mpoolTerm(SwMpool* mpool);
|
||||||
|
|
|
@ -103,11 +103,9 @@ struct SwShapeTask : SwTask
|
||||||
|
|
||||||
bool clip(SwRle* target) override
|
bool clip(SwRle* target) override
|
||||||
{
|
{
|
||||||
if (shape.fastTrack) rleClip(target, &bbox);
|
if (shape.fastTrack) return rleClip(target, &bbox);
|
||||||
else if (shape.rle) rleClip(target, shape.rle);
|
else if (shape.rle) return rleClip(target, shape.rle);
|
||||||
else return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(unsigned tid) override
|
void run(unsigned tid) override
|
||||||
|
@ -176,10 +174,8 @@ struct SwShapeTask : SwTask
|
||||||
//Clip Path
|
//Clip Path
|
||||||
for (auto clip = clips.begin(); clip < clips.end(); ++clip) {
|
for (auto clip = clips.begin(); clip < clips.end(); ++clip) {
|
||||||
auto clipper = static_cast<SwTask*>(*clip);
|
auto clipper = static_cast<SwTask*>(*clip);
|
||||||
//Clip shape rle
|
if (shape.rle && !clipper->clip(shape.rle)) goto err; //Clip shape rle
|
||||||
if (shape.rle && !clipper->clip(shape.rle)) goto err;
|
if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err; //Clip stroke rle
|
||||||
//Clip stroke rle
|
|
||||||
if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bbox = renderRegion; //sync
|
bbox = renderRegion; //sync
|
||||||
|
|
|
@ -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 spanCnt = rle->size > clip->size ? rle->size : clip->size;
|
||||||
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
|
||||||
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
||||||
|
@ -1030,17 +1030,21 @@ void rleClip(SwRle *rle, const SwRle *clip)
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
|
||||||
TVGLOG("SW_ENGINE", "Using Path Clipping!");
|
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<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
|
||||||
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
|
||||||
TVGLOG("SW_ENGINE", "Using Box Clipping!");
|
TVGLOG("SW_ENGINE", "Using Box Clipping!");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue