diff --git a/src/renderer/sw_engine/tvgSwRle.cpp b/src/renderer/sw_engine/tvgSwRle.cpp index 12f4a230..bc5ec707 100644 --- a/src/renderer/sw_engine/tvgSwRle.cpp +++ b/src/renderer/sw_engine/tvgSwRle.cpp @@ -197,7 +197,6 @@ /* Internal Class Implementation */ /************************************************************************/ -constexpr auto MAX_SPANS = 256; constexpr auto PIXEL_BITS = 8; //must be at least 6 bits! constexpr auto ONE_PIXEL = (1L << PIXEL_BITS); @@ -240,10 +239,6 @@ struct RleWorker SwOutline* outline; - SwSpan spans[MAX_SPANS]; - int spansCnt; - int ySpan; - int bandSize; int bandShoot; @@ -301,26 +296,6 @@ static inline SwCoord HYPOT(SwPoint pt) return ((pt.x > pt.y) ? (pt.x + (3 * pt.y >> 3)) : (pt.y + (3 * pt.x >> 3))); } -static void _genSpan(SwRleData* rle, const SwSpan* spans, uint32_t count) -{ - auto newSize = rle->size + count; - - /* allocate enough memory for new spans */ - /* alloc is required to prevent free and reallocation */ - /* when the rle needs to be regenerated because of attribute change. */ - if (rle->alloc < newSize) { - rle->alloc = (newSize * 2); - //OPTIMIZE: use mempool! - rle->spans = static_cast(realloc(rle->spans, rle->alloc * sizeof(SwSpan))); - } - - //copy the new spans to the allocated memory - SwSpan* lastSpan = rle->spans + rle->size; - memcpy(lastSpan, spans, count * sizeof(SwSpan)); - - rle->size = newSize; -} - static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoord aCount) { @@ -344,25 +319,26 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor if (coverage > 255) coverage = 255; } + if (coverage == 0) return; + //span has ushort coordinates. check limit overflow if (x >= SHRT_MAX) { TVGERR("SW_ENGINE", "X-coordinate overflow!"); - x = SHRT_MAX; + return; } if (y >= SHRT_MAX) { TVGERR("SW_ENGINE", "Y-coordinate overflow!"); - y = SHRT_MAX; + return; } - if (coverage > 0) { - if (!rw.antiAlias) coverage = 255; - auto count = rw.spansCnt; - auto span = rw.spans + count - 1; + auto rle = rw.rle; - //see whether we can add this span to the current list - if ((count > 0) && (rw.ySpan == y) && - (span->x + span->len == x) && (span->coverage == coverage)) { + if (!rw.antiAlias) coverage = 255; + //see whether we can add this span to the current list + if (rle->size > 0) { + auto span = rle->spans + rle->size - 1; + if ((span->coverage == coverage) && (span->y == y) && (span->x + span->len == x)) { //Clip x range SwCoord xOver = 0; if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x); @@ -372,35 +348,35 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor span->len += (aCount + xOver); return; } - - if (count >= MAX_SPANS) { - _genSpan(rw.rle, rw.spans, count); - rw.spansCnt = 0; - rw.ySpan = 0; - span = rw.spans; - } else { - ++span; - } - - //Clip x range - SwCoord xOver = 0; - if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x); - if (x < rw.cellMin.x) { - xOver -= (rw.cellMin.x - x); - x = rw.cellMin.x; - } - - //Nothing to draw - if (aCount + xOver <= 0) return; - - //add a span to the current list - span->x = x; - span->y = y; - span->len = (aCount + xOver); - span->coverage = coverage; - ++rw.spansCnt; - rw.ySpan = y; } + + //span pool is full, grow it. + if (rle->size >= rle->alloc) { + auto newSize = (rle->size > 0) ? (rle->size * 2) : 256; + if (rle->alloc < newSize) { + rle->alloc = newSize; + rle->spans = static_cast(realloc(rle->spans, rle->alloc * sizeof(SwSpan))); + } + } + + //Clip x range + SwCoord xOver = 0; + if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x); + if (x < rw.cellMin.x) { + xOver -= (rw.cellMin.x - x); + x = rw.cellMin.x; + } + + //Nothing to draw + if (aCount + xOver <= 0) return; + + //add a span to the current list + auto span = rle->spans + rle->size; + span->x = x; + span->y = y; + span->len = (aCount + xOver); + span->coverage = coverage; + rle->size++; } @@ -408,9 +384,6 @@ static void _sweep(RleWorker& rw) { if (rw.cellsCnt == 0) return; - rw.spansCnt = 0; - rw.ySpan = 0; - for (int y = 0; y < rw.yCnt; ++y) { auto cover = 0; auto x = 0; @@ -427,8 +400,6 @@ static void _sweep(RleWorker& rw) if (cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x); } - - if (rw.spansCnt > 0) _genSpan(rw.rle, rw.spans, rw.spansCnt); } @@ -926,7 +897,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren rw.cellMax = renderRegion.max; rw.cellXCnt = rw.cellMax.x - rw.cellMin.x; rw.cellYCnt = rw.cellMax.y - rw.cellMin.y; - rw.ySpan = 0; rw.outline = const_cast(outline); rw.bandSize = rw.bufferSize / (sizeof(Cell) * 2); //bandSize: 256 rw.bandShoot = 0; @@ -1019,7 +989,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren error: free(rw.rle); - rw.rle = nullptr; return nullptr; }