From df64a7b0dc51c97c318d0b4eca5edca76834f89e Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 17 Dec 2021 17:23:55 +0900 Subject: [PATCH] sw_engine raster: fix a crash at the texmap clipping. Handle correctly duplicated spans from the multiple y span data. Previous logic only expected the one single y span data from the rle. However rle might have multiple y span data if the anti-aliasing is applied. This patch also removed the bad design of the common engine which handles the anti-alising option to ignore the anti-aliasing rle generation. Just realized, it's difficult to control that condition due to scene-composition. --- src/lib/sw_engine/tvgSwRasterTexmapInternal.h | 33 ++++++++++++------- src/lib/sw_engine/tvgSwRenderer.cpp | 4 +-- src/lib/tvgPaint.cpp | 10 +----- src/lib/tvgRender.h | 2 +- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h index 782c8f6c..0c6bf13d 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h +++ b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h @@ -30,7 +30,7 @@ int32_t dw = surface->stride; int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; int32_t vv = 0, uu = 0; - int32_t minx = 0, maxx = 0; + int32_t minx, maxx; float dx, u, v, iptr; uint32_t* buf; SwSpan* span = nullptr; //used only when rle based. @@ -42,24 +42,36 @@ if (!_arrange(image, region, yStart, yEnd)) return; //Loop through all lines in the segment - y = yStart; + uint32_t spanIdx = 0; if (region) { minx = region->min.x; maxx = region->max.x; } else { - span = image->rle->spans + (yStart - image->rle->spans->y); + span = image->rle->spans; + while (span->y < yStart) { + ++span; + ++spanIdx; + } } + y = yStart; + while (y < yEnd) { x1 = _xa; x2 = _xb; if (!region) { - minx = span->x; - maxx = span->x + span->len; + minx = INT32_MAX; + maxx = INT32_MIN; + //one single row, could be consisted of multiple spans. + while (span->y == y && spanIdx < image->rle->size) { + if (minx > span->x) minx = span->x; + if (maxx < span->x + span->len) maxx = span->x + span->len; + ++span; + ++spanIdx; + } } - if (x1 < minx) x1 = minx; if (x2 > maxx) x2 = maxx; @@ -138,12 +150,9 @@ next: _ua += _dudya; _va += _dvdya; - if (span) { - ++span; - y = span->y; - } else { - y++; - } + if (!region && spanIdx >= image->rle->size) break; + + ++y; } xa = _xa; xb = _xb; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 672b9388..78537e77 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -111,13 +111,11 @@ struct SwShapeTask : SwTask //Fill if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { if (visibleFill) { - auto antiAlias = (flags & RenderUpdateFlag::IgnoreAliasing) ? false : true; - /* 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. Also, it shouldn't be dash style. */ - if (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) antiAlias = false; + auto antiAlias = (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) ? false : true; if (!shapeGenRle(&shape, sdata, antiAlias)) goto err; } diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index d258dd54..30e82fbc 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -223,15 +223,7 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } } if (!compFastTrack) { - //Bad design!: ignore anti-aliasing if the bitmap image is the source of the clip-path! - auto tempFlag = pFlag; - - if (id == TVG_CLASS_ID_PICTURE) { - auto picture = static_cast(compData->source); - if (picture->data(nullptr, nullptr)) tempFlag |= RenderUpdateFlag::IgnoreAliasing; - } - - tdata = target->pImpl->update(renderer, pTransform, 255, clips, tempFlag); + tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag); if (method == CompositeMethod::ClipPath) clips.push(tdata); } } diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 7621fe20..f927947a 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -28,7 +28,7 @@ namespace tvg { -enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255, IgnoreAliasing = 256}; +enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255}; struct Surface {