sw_engine: replaced longjmp with returns

Since longjmp is not yet fully supported on Wasm (emscripten uses
JS to make the jumps and requires slow jumps), but also because
longjmp is hard to reason about, this patch replaces it with
return values. The logic stays exactly the same.
This commit is contained in:
Dragoș Tiselice 2024-11-28 11:28:03 +02:00 committed by Mira Grudzinska
parent 52cf31a79d
commit c5a7d76109
2 changed files with 55 additions and 36 deletions

View file

@ -22,7 +22,7 @@ Rafał Mikrut <mikrutrafal@protonmail.com>
Martin Capitanio <capnm@capitanio.org> Martin Capitanio <capnm@capitanio.org>
RuiwenTang <tangruiwen1989@gmail.com> RuiwenTang <tangruiwen1989@gmail.com>
YouJin Lee <ol-of@naver.com> YouJin Lee <ol-of@naver.com>
SergeyLebedkin <sergii@lottiefiles.com> Sergii Liebodkin <sergii@lottiefiles.com>
Jinny You <jinny@lottiefiles.com> Jinny You <jinny@lottiefiles.com>
Nattu Adnan <nattu@reallynattu.com> Nattu Adnan <nattu@reallynattu.com>
Gabor Kiss-Vamosi <kisvegabor@gmail.com> Gabor Kiss-Vamosi <kisvegabor@gmail.com>
@ -35,3 +35,6 @@ Thaddeus Crews <repiteo@outlook.com>
Josh Soref <jsoref@gmail.com> Josh Soref <jsoref@gmail.com>
Elliott Sales de Andrade <quantum.analyst@gmail.com> Elliott Sales de Andrade <quantum.analyst@gmail.com>
Łukasz Pomietło <oficjalnyadreslukasza@gmail.com> Łukasz Pomietło <oficjalnyadreslukasza@gmail.com>
Kelly Loh <kelly@lottiefiles.com>
Dragoș Tiselice <dragos@lottiefiles.com>

View file

@ -188,7 +188,6 @@
* http://www.freetype.org * http://www.freetype.org
*/ */
#include <setjmp.h>
#include <limits.h> #include <limits.h>
#include <memory.h> #include <memory.h>
#include "tvgSwCommon.h" #include "tvgSwCommon.h"
@ -243,8 +242,6 @@ struct RleWorker
int bandSize; int bandSize;
int bandShoot; int bandShoot;
jmp_buf jmpBuf;
void* buffer; void* buffer;
long bufferSize; long bufferSize;
@ -418,7 +415,7 @@ static Cell* _findCell(RleWorker& rw)
pcell = &cell->next; pcell = &cell->next;
} }
if (rw.cellsCnt >= rw.maxCells) longjmp(rw.jmpBuf, 1); if (rw.cellsCnt >= rw.maxCells) return nullptr;
auto cell = rw.cells + rw.cellsCnt++; auto cell = rw.cells + rw.cellsCnt++;
cell->x = x; cell->x = x;
@ -431,17 +428,22 @@ static Cell* _findCell(RleWorker& rw)
} }
static void _recordCell(RleWorker& rw) static bool _recordCell(RleWorker& rw)
{ {
if (rw.area | rw.cover) { if (rw.area | rw.cover) {
auto cell = _findCell(rw); auto cell = _findCell(rw);
if (cell == nullptr) return false;
cell->area += rw.area; cell->area += rw.area;
cell->cover += rw.cover; cell->cover += rw.cover;
} }
return true;
} }
static void _setCell(RleWorker& rw, SwPoint pos) static bool _setCell(RleWorker& rw, SwPoint pos)
{ {
/* Move the cell pointer to a new position. We set the `invalid' */ /* Move the cell pointer to a new position. We set the `invalid' */
/* flag to indicate that the cell isn't part of those we're interested */ /* flag to indicate that the cell isn't part of those we're interested */
@ -463,17 +465,21 @@ static void _setCell(RleWorker& rw, SwPoint pos)
//Are we moving to a different cell? //Are we moving to a different cell?
if (pos != rw.cellPos) { if (pos != rw.cellPos) {
//Record the current one if it is valid //Record the current one if it is valid
if (!rw.invalid) _recordCell(rw); if (!rw.invalid) {
if (!_recordCell(rw)) return false;
}
} }
rw.area = 0; rw.area = 0;
rw.cover = 0; rw.cover = 0;
rw.cellPos = pos; rw.cellPos = pos;
rw.invalid = ((unsigned)pos.y >= (unsigned)rw.cellYCnt || pos.x >= rw.cellXCnt); rw.invalid = ((unsigned)pos.y >= (unsigned)rw.cellYCnt || pos.x >= rw.cellXCnt);
return true;
} }
static void _startCell(RleWorker& rw, SwPoint pos) static bool _startCell(RleWorker& rw, SwPoint pos)
{ {
if (pos.x > rw.cellMax.x) pos.x = rw.cellMax.x; if (pos.x > rw.cellMax.x) pos.x = rw.cellMax.x;
if (pos.x < rw.cellMin.x) pos.x = rw.cellMin.x; if (pos.x < rw.cellMin.x) pos.x = rw.cellMin.x;
@ -483,23 +489,27 @@ static void _startCell(RleWorker& rw, SwPoint pos)
rw.cellPos = pos - rw.cellMin; rw.cellPos = pos - rw.cellMin;
rw.invalid = false; rw.invalid = false;
_setCell(rw, pos); return _setCell(rw, pos);
} }
static void _moveTo(RleWorker& rw, const SwPoint& to) static bool _moveTo(RleWorker& rw, const SwPoint& to)
{ {
//record current cell, if any */ //record current cell, if any */
if (!rw.invalid) _recordCell(rw); if (!rw.invalid) {
if (!_recordCell(rw)) return false;
}
//start to a new position //start to a new position
_startCell(rw, TRUNC(to)); if (!_startCell(rw, TRUNC(to))) return false;
rw.pos = to; rw.pos = to;
return true;
} }
static void _lineTo(RleWorker& rw, const SwPoint& to) static bool _lineTo(RleWorker& rw, const SwPoint& to)
{ {
#define SW_UDIV(a, b) \ #define SW_UDIV(a, b) \
static_cast<SwCoord>(((unsigned long)(a) * (unsigned long)(b)) >> \ static_cast<SwCoord>(((unsigned long)(a) * (unsigned long)(b)) >> \
@ -511,7 +521,7 @@ static void _lineTo(RleWorker& rw, const SwPoint& to)
//vertical clipping //vertical clipping
if ((e1.y >= rw.cellMax.y && e2.y >= rw.cellMax.y) || (e1.y < rw.cellMin.y && e2.y < rw.cellMin.y)) { if ((e1.y >= rw.cellMax.y && e2.y >= rw.cellMax.y) || (e1.y < rw.cellMin.y && e2.y < rw.cellMin.y)) {
rw.pos = to; rw.pos = to;
return; return true;
} }
auto line = rw.lineStack; auto line = rw.lineStack;
@ -539,7 +549,7 @@ static void _lineTo(RleWorker& rw, const SwPoint& to)
//any horizontal line //any horizontal line
} else if (diff.y == 0) { } else if (diff.y == 0) {
e1.x = e2.x; e1.x = e2.x;
_setCell(rw, e1); if (!_setCell(rw, e1)) return false;
} else if (diff.x == 0) { } else if (diff.x == 0) {
//vertical line up //vertical line up
if (diff.y > 0) { if (diff.y > 0) {
@ -549,7 +559,7 @@ static void _lineTo(RleWorker& rw, const SwPoint& to)
rw.area += (f2.y - f1.y) * f1.x * 2; rw.area += (f2.y - f1.y) * f1.x * 2;
f1.y = 0; f1.y = 0;
++e1.y; ++e1.y;
_setCell(rw, e1); if (!_setCell(rw, e1)) return false;
} while(e1.y != e2.y); } while(e1.y != e2.y);
//vertical line down //vertical line down
} else { } else {
@ -559,7 +569,7 @@ static void _lineTo(RleWorker& rw, const SwPoint& to)
rw.area += (f2.y - f1.y) * f1.x * 2; rw.area += (f2.y - f1.y) * f1.x * 2;
f1.y = ONE_PIXEL; f1.y = ONE_PIXEL;
--e1.y; --e1.y;
_setCell(rw, e1); if (!_setCell(rw, e1)) return false;
} while(e1.y != e2.y); } while(e1.y != e2.y);
} }
//any other line //any other line
@ -612,7 +622,7 @@ static void _lineTo(RleWorker& rw, const SwPoint& to)
--e1.y; --e1.y;
} }
_setCell(rw, e1); if (!_setCell(rw, e1)) return false;
} while(e1 != e2); } while(e1 != e2);
} }
@ -622,12 +632,12 @@ static void _lineTo(RleWorker& rw, const SwPoint& to)
rw.area += (f2.y - f1.y) * (f1.x + f2.x); rw.area += (f2.y - f1.y) * (f1.x + f2.x);
rw.pos = line[0]; rw.pos = line[0];
if (line-- == rw.lineStack) return; if (line-- == rw.lineStack) return true;
} }
} }
static void _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to) static bool _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to)
{ {
auto arc = rw.bezStack; auto arc = rw.bezStack;
arc[0] = to; arc[0] = to;
@ -691,14 +701,14 @@ static void _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2,
continue; continue;
draw: draw:
_lineTo(rw, arc[0]); if (!_lineTo(rw, arc[0])) return false;
if (arc == rw.bezStack) return; if (arc == rw.bezStack) return true;
arc -= 3; arc -= 3;
} }
} }
static void _decomposeOutline(RleWorker& rw) static bool _decomposeOutline(RleWorker& rw)
{ {
auto outline = rw.outline; auto outline = rw.outline;
auto first = 0; //index of first point in contour auto first = 0; //index of first point in contour
@ -711,38 +721,43 @@ static void _decomposeOutline(RleWorker& rw)
auto types = outline->types.data + first; auto types = outline->types.data + first;
++types; ++types;
_moveTo(rw, UPSCALE(outline->pts[first])); if (!_moveTo(rw, UPSCALE(outline->pts[first]))) return false;
while (pt < limit) { while (pt < limit) {
//emit a single line_to //emit a single line_to
if (types[0] == SW_CURVE_TYPE_POINT) { if (types[0] == SW_CURVE_TYPE_POINT) {
++pt; ++pt;
++types; ++types;
_lineTo(rw, UPSCALE(*pt)); if (!_lineTo(rw, UPSCALE(*pt))) return false;
//types cubic //types cubic
} else { } else {
pt += 3; pt += 3;
types += 3; types += 3;
if (pt <= limit) _cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), UPSCALE(pt[0])); if (pt <= limit) {
else if (pt - 1 == limit) _cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), start); if (!_cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), UPSCALE(pt[0]))) return false;
}
else if (pt - 1 == limit) {
if (!_cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), start)) return false;
}
else goto close; else goto close;
} }
} }
close: close:
_lineTo(rw, start); if (!_lineTo(rw, start)) return false;
first = last + 1; first = last + 1;
} }
return true;
} }
static int _genRle(RleWorker& rw) static int _genRle(RleWorker& rw)
{ {
if (setjmp(rw.jmpBuf) == 0) { if (!_decomposeOutline(rw)) return -1;
_decomposeOutline(rw); if (!rw.invalid) {
if (!rw.invalid) _recordCell(rw); if (!_recordCell(rw)) return -1;
return 0;
} }
return -1; //lack of cell memory return 0;
} }
@ -1028,3 +1043,4 @@ void rleClip(SwRle *rle, const SwBBox* clip)
TVGLOG("SW_ENGINE", "Using Box Clipping!"); TVGLOG("SW_ENGINE", "Using Box Clipping!");
} }