mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
sw_engine rle: fix RLE intersect.
IntersectSpansRegion() wasn't working correctly, as it didn't take care of some corner cases. This fix makes the algorithm more accurate.
This commit is contained in:
parent
b26672a1f6
commit
bd695c6631
1 changed files with 33 additions and 35 deletions
|
@ -773,54 +773,52 @@ static int _genRle(RleWorker& rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
static SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *target, SwSpan *outSpans)
|
||||||
{
|
{
|
||||||
auto out = outSpans;
|
auto out = outSpans;
|
||||||
auto spans = targetRle->spans;
|
auto spans = target->spans;
|
||||||
auto end = targetRle->spans + targetRle->size;
|
auto end = target->spans + target->size;
|
||||||
auto clipSpans = clip->spans;
|
auto clipSpans = clip->spans;
|
||||||
auto clipEnd = clip->spans + clip->size;
|
auto clipEnd = clip->spans + clip->size;
|
||||||
|
|
||||||
while (spanCnt > 0 && spans < end) {
|
while (spans < end && clipSpans < clipEnd) {
|
||||||
if (clipSpans == clipEnd) {
|
//align y cooridnates.
|
||||||
spans = end;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (clipSpans->y > spans->y) {
|
if (clipSpans->y > spans->y) {
|
||||||
++spans;
|
++spans;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (spans->y != clipSpans->y) {
|
if (spans->y > clipSpans->y) {
|
||||||
++clipSpans;
|
++clipSpans;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto sx1 = spans->x;
|
|
||||||
auto sx2 = sx1 + spans->len;
|
|
||||||
auto cx1 = clipSpans->x;
|
|
||||||
auto cx2 = cx1 + clipSpans->len;
|
|
||||||
|
|
||||||
if (cx1 < sx1 && cx2 < sx1) {
|
//Try clipping with all clip spans which have a same y coordinate.
|
||||||
++clipSpans;
|
auto temp = clipSpans;
|
||||||
continue;
|
while(temp->y == clipSpans->y) {
|
||||||
|
auto sx1 = spans->x;
|
||||||
|
auto sx2 = sx1 + spans->len;
|
||||||
|
auto cx1 = temp->x;
|
||||||
|
auto cx2 = cx1 + temp->len;
|
||||||
|
|
||||||
|
//The span must be left(x1) to right(x2) direction. Not intersected.
|
||||||
|
if (cx2 < sx1 || sx2 < cx1) {
|
||||||
|
++temp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//clip span region.
|
||||||
|
auto x = sx1 > cx1 ? sx1 : cx1;
|
||||||
|
auto len = (sx2 < cx2 ? sx2 : cx2) - x;
|
||||||
|
if (len > 0) {
|
||||||
|
out->x = x;
|
||||||
|
out->y = temp->y;
|
||||||
|
out->len = len;
|
||||||
|
out->coverage = (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8);
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
++temp;
|
||||||
}
|
}
|
||||||
else if (sx1 < cx1 && sx2 < cx1) {
|
++spans;
|
||||||
++spans;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto x = sx1 > cx1 ? sx1 : cx1;
|
|
||||||
auto len = (sx2 < cx2 ? sx2 : cx2) - x;
|
|
||||||
if (len) {
|
|
||||||
auto spansCorverage = spans->coverage;
|
|
||||||
auto clipSpansCoverage = clipSpans->coverage;
|
|
||||||
out->x = sx1 > cx1 ? sx1 : cx1;
|
|
||||||
out->len = (sx2 < cx2 ? sx2 : cx2) - out->x;
|
|
||||||
out->y = spans->y;
|
|
||||||
out->coverage = (uint8_t)(((spansCorverage * clipSpansCoverage) + 0xff) >> 8);
|
|
||||||
++out;
|
|
||||||
--spanCnt;
|
|
||||||
}
|
|
||||||
if (sx2 < cx2) ++spans;
|
|
||||||
else ++clipSpans;
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -1122,7 +1120,7 @@ void rleClipPath(SwRleData *rle, const SwRleData *clip)
|
||||||
if (rle->size == 0 || clip->size == 0) return;
|
if (rle->size == 0 || clip->size == 0) return;
|
||||||
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);
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue