mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
sw_engine: code refactoring
1. unified clip & bounding box in rle processing 2. unified outline boundingbox functions between shape & image.
This commit is contained in:
parent
19fc4f4b37
commit
4a8f45577a
6 changed files with 81 additions and 146 deletions
|
@ -53,25 +53,30 @@ struct SwPoint
|
|||
{
|
||||
SwCoord x, y;
|
||||
|
||||
SwPoint& operator+=(const SwPoint& rhs) {
|
||||
SwPoint& operator+=(const SwPoint& rhs)
|
||||
{
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SwPoint operator+(const SwPoint& rhs) const {
|
||||
SwPoint operator+(const SwPoint& rhs) const
|
||||
{
|
||||
return {x + rhs.x, y + rhs.y};
|
||||
}
|
||||
|
||||
SwPoint operator-(const SwPoint& rhs) const {
|
||||
SwPoint operator-(const SwPoint& rhs) const
|
||||
{
|
||||
return {x - rhs.x, y - rhs.y};
|
||||
}
|
||||
|
||||
bool operator==(const SwPoint& rhs ) const {
|
||||
bool operator==(const SwPoint& rhs ) const
|
||||
{
|
||||
return (x == rhs.x && y == rhs.y);
|
||||
}
|
||||
|
||||
bool operator!=(const SwPoint& rhs) const {
|
||||
bool operator!=(const SwPoint& rhs) const
|
||||
{
|
||||
return (x != rhs.x || y != rhs.y);
|
||||
}
|
||||
|
||||
|
@ -125,6 +130,11 @@ struct SwRleData
|
|||
struct SwBBox
|
||||
{
|
||||
SwPoint min, max;
|
||||
|
||||
void reset()
|
||||
{
|
||||
min.x = min.y = max.x = max.y = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SwFill
|
||||
|
@ -286,12 +296,13 @@ SwFixed mathLength(const SwPoint& pt);
|
|||
bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
|
||||
SwFixed mathMean(SwFixed angle1, SwFixed angle2);
|
||||
SwPoint mathTransform(const Point* to, const Matrix* transform);
|
||||
bool mathUpdateOutlineBBox(const SwOutline* outline, SwBBox& bbox, const SwSize& clip);
|
||||
|
||||
void shapeReset(SwShape* shape);
|
||||
bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform);
|
||||
bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
|
||||
bool shapePrepared(const SwShape* shape);
|
||||
bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite);
|
||||
bool shapeGenRle(SwShape* shape, const Shape* sdata, bool antiAlias, bool hasComposite);
|
||||
void shapeDelOutline(SwShape* shape, uint32_t tid);
|
||||
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
|
||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip, SwBBox& bbox);
|
||||
|
@ -311,7 +322,7 @@ void strokeFree(SwStroke* stroke);
|
|||
|
||||
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
|
||||
bool imagePrepared(const SwImage* image);
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, const SwBBox& bbox, bool antiAlias, bool hasComposite);
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwBBox& bbox, bool antiAlias, bool hasComposite);
|
||||
void imageDelOutline(SwImage* image, uint32_t tid);
|
||||
void imageReset(SwImage* image);
|
||||
bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform);
|
||||
|
@ -323,7 +334,7 @@ void fillFree(SwFill* fill);
|
|||
void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len);
|
||||
void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
|
||||
|
||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias);
|
||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& bbox, bool antiAlias);
|
||||
void rleFree(SwRleData* rle);
|
||||
void rleReset(SwRleData* rle);
|
||||
void rleClipPath(SwRleData *rle, const SwRleData *clip);
|
||||
|
|
|
@ -27,63 +27,6 @@
|
|||
/************************************************************************/
|
||||
|
||||
|
||||
static void _initBBox(SwBBox& bbox)
|
||||
{
|
||||
bbox.min.x = bbox.min.y = 0;
|
||||
bbox.max.x = bbox.max.y = 0;
|
||||
}
|
||||
|
||||
|
||||
static bool _updateBBox(const SwOutline* outline, SwBBox& bbox, const SwSize& clip)
|
||||
{
|
||||
if (!outline) return false;
|
||||
|
||||
auto pt = outline->pts;
|
||||
|
||||
if (outline->ptsCnt <= 0) {
|
||||
_initBBox(bbox);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto xMin = pt->x;
|
||||
auto xMax = pt->x;
|
||||
auto yMin = pt->y;
|
||||
auto yMax = pt->y;
|
||||
|
||||
++pt;
|
||||
|
||||
for(uint32_t i = 1; i < outline->ptsCnt; ++i, ++pt) {
|
||||
if (xMin > pt->x) xMin = pt->x;
|
||||
if (xMax < pt->x) xMax = pt->x;
|
||||
if (yMin > pt->y) yMin = pt->y;
|
||||
if (yMax < pt->y) yMax = pt->y;
|
||||
}
|
||||
bbox.min.x = xMin >> 6;
|
||||
bbox.max.x = (xMax + 63) >> 6;
|
||||
bbox.min.y = yMin >> 6;
|
||||
bbox.max.y = (yMax + 63) >> 6;
|
||||
|
||||
bbox.min.x = max(bbox.min.x, TO_SWCOORD(0));
|
||||
bbox.min.y = max(bbox.min.y, TO_SWCOORD(0));
|
||||
bbox.max.x = min(bbox.max.x, clip.w);
|
||||
bbox.max.y = min(bbox.max.y, clip.h);
|
||||
|
||||
if (xMax - xMin < 1 && yMax - yMin < 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip)
|
||||
{
|
||||
if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) return false;
|
||||
|
||||
//Check boundary
|
||||
if (bbox.min.x >= clip.w || bbox.min.y >= clip.h || bbox.max.x <= 0 || bbox.max.y <= 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
|
@ -93,10 +36,11 @@ static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSi
|
|||
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox)
|
||||
{
|
||||
if (!imageGenOutline(image, pdata, tid, transform)) return false;
|
||||
if (!mathUpdateOutlineBBox(image->outline, bbox, clip)) return false;
|
||||
|
||||
if (!_updateBBox(image->outline, bbox, clip)) return false;
|
||||
|
||||
if (!_checkValid(image->outline, bbox, clip)) return false;
|
||||
//Guarantee boundary from mathUpdateOutlineBBox()
|
||||
bbox.min.x = max(bbox.min.x, TO_SWCOORD(0));
|
||||
bbox.min.y = max(bbox.min.y, TO_SWCOORD(0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -108,9 +52,9 @@ bool imagePrepared(const SwImage* image)
|
|||
}
|
||||
|
||||
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, const SwBBox& bbox, bool antiAlias, TVG_UNUSED bool hasComposite)
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwBBox& bbox, bool antiAlias, TVG_UNUSED bool hasComposite)
|
||||
{
|
||||
if ((image->rle = rleRender(image->rle, image->outline, bbox, clip, antiAlias))) return true;
|
||||
if ((image->rle = rleRender(image->rle, image->outline, bbox, antiAlias))) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -427,3 +427,46 @@ SwPoint mathTransform(const Point* to, const Matrix* transform)
|
|||
|
||||
return {TO_SWCOORD(tx), TO_SWCOORD(ty)};
|
||||
}
|
||||
|
||||
|
||||
bool mathUpdateOutlineBBox(const SwOutline* outline, SwBBox& bbox, const SwSize& clip)
|
||||
{
|
||||
if (!outline) return false;
|
||||
|
||||
auto pt = outline->pts;
|
||||
|
||||
if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) {
|
||||
bbox.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto xMin = pt->x;
|
||||
auto xMax = pt->x;
|
||||
auto yMin = pt->y;
|
||||
auto yMax = pt->y;
|
||||
|
||||
++pt;
|
||||
|
||||
for(uint32_t i = 1; i < outline->ptsCnt; ++i, ++pt) {
|
||||
if (xMin > pt->x) xMin = pt->x;
|
||||
if (xMax < pt->x) xMax = pt->x;
|
||||
if (yMin > pt->y) yMin = pt->y;
|
||||
if (yMax < pt->y) yMax = pt->y;
|
||||
}
|
||||
bbox.min.x = xMin >> 6;
|
||||
bbox.max.x = (xMax + 63) >> 6;
|
||||
bbox.min.y = yMin >> 6;
|
||||
bbox.max.y = (yMax + 63) >> 6;
|
||||
|
||||
//Guarantee surface boundary
|
||||
bbox.max.x = min(bbox.max.x, clip.w);
|
||||
bbox.max.y = min(bbox.max.y, clip.h);
|
||||
|
||||
//Check valid region
|
||||
if (bbox.max.x - bbox.min.x < 1 && bbox.max.y - bbox.min.y < 1) return false;
|
||||
|
||||
//Check boundary
|
||||
if (bbox.min.x >= clip.w || bbox.min.y >= clip.h || bbox.max.x <= 0 || bbox.max.y <= 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -100,7 +100,7 @@ struct SwShapeTask : SwTask
|
|||
shape outline below stroke could be full covered by stroke drawing.
|
||||
Thus it turns off antialising in that condition. */
|
||||
auto antiAlias = (strokeAlpha == 255 && strokeWidth > 2) ? false : true;
|
||||
if (!shapeGenRle(&shape, sdata, clip, antiAlias, clips.count > 0 ? true : false)) goto err;
|
||||
if (!shapeGenRle(&shape, sdata, antiAlias, clips.count > 0 ? true : false)) goto err;
|
||||
++addStroking;
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ struct SwImageTask : SwTask
|
|||
|
||||
//Clip Path?
|
||||
if (clips.count > 0) {
|
||||
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
|
||||
if (!imageGenRle(&image, pdata, bbox, false, true)) goto end;
|
||||
if (image.rle) {
|
||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
||||
|
|
|
@ -87,8 +87,6 @@ struct RleWorker
|
|||
Cell** yCells;
|
||||
SwCoord yCnt;
|
||||
|
||||
SwSize clip;
|
||||
|
||||
bool invalid;
|
||||
bool antiAlias;
|
||||
};
|
||||
|
@ -161,8 +159,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
|||
y += rw.cellMin.y;
|
||||
|
||||
//Clip Y range
|
||||
if (y < 0) return;
|
||||
if (y >= rw.clip.h) return;
|
||||
if (y < 0 || y >= rw.cellMax.y) return;
|
||||
|
||||
/* compute the coverage line's coverage, depending on the outline fill rule */
|
||||
/* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
|
||||
|
@ -200,7 +197,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
|||
|
||||
//Clip x range
|
||||
SwCoord xOver = 0;
|
||||
if (x + acount >= rw.clip.w) xOver -= (x + acount - rw.clip.w);
|
||||
if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x);
|
||||
if (x < 0) xOver += x;
|
||||
|
||||
//span->len += (acount + xOver) - 1;
|
||||
|
@ -219,7 +216,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
|||
|
||||
//Clip x range
|
||||
SwCoord xOver = 0;
|
||||
if (x + acount >= rw.clip.w) xOver -= (x + acount - rw.clip.w);
|
||||
if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x);
|
||||
if (x < 0) {
|
||||
xOver += x;
|
||||
x = 0;
|
||||
|
@ -785,7 +782,7 @@ void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias)
|
||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& bbox, bool antiAlias)
|
||||
{
|
||||
constexpr auto RENDER_POOL_SIZE = 16384L;
|
||||
constexpr auto BAND_SIZE = 40;
|
||||
|
@ -812,7 +809,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& bbo
|
|||
rw.outline = const_cast<SwOutline*>(outline);
|
||||
rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64
|
||||
rw.bandShoot = 0;
|
||||
rw.clip = clip;
|
||||
rw.antiAlias = antiAlias;
|
||||
|
||||
if (!rle) rw.rle = reinterpret_cast<SwRleData*>(calloc(1, sizeof(SwRleData)));
|
||||
|
|
|
@ -157,59 +157,6 @@ static void _outlineClose(SwOutline& outline)
|
|||
}
|
||||
|
||||
|
||||
static void _initBBox(SwBBox& bbox)
|
||||
{
|
||||
bbox.min.x = bbox.min.y = 0;
|
||||
bbox.max.x = bbox.max.y = 0;
|
||||
}
|
||||
|
||||
|
||||
static bool _updateBBox(const SwOutline* outline, SwBBox& bbox)
|
||||
{
|
||||
if (!outline) return false;
|
||||
|
||||
auto pt = outline->pts;
|
||||
|
||||
if (outline->ptsCnt <= 0) {
|
||||
_initBBox(bbox);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto xMin = pt->x;
|
||||
auto xMax = pt->x;
|
||||
auto yMin = pt->y;
|
||||
auto yMax = pt->y;
|
||||
|
||||
++pt;
|
||||
|
||||
for(uint32_t i = 1; i < outline->ptsCnt; ++i, ++pt) {
|
||||
if (xMin > pt->x) xMin = pt->x;
|
||||
if (xMax < pt->x) xMax = pt->x;
|
||||
if (yMin > pt->y) yMin = pt->y;
|
||||
if (yMax < pt->y) yMax = pt->y;
|
||||
}
|
||||
bbox.min.x = xMin >> 6;
|
||||
bbox.max.x = (xMax + 63) >> 6;
|
||||
bbox.min.y = yMin >> 6;
|
||||
bbox.max.y = (yMax + 63) >> 6;
|
||||
|
||||
if (xMax - xMin < 1 && yMax - yMin < 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip)
|
||||
{
|
||||
if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) return false;
|
||||
|
||||
//Check boundary
|
||||
if (bbox.min.x >= clip.w || bbox.min.y >= clip.h || bbox.max.x <= 0 || bbox.max.y <= 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* transform)
|
||||
{
|
||||
_growOutlinePoint(*dash.outline, dash.outline->ptsCnt >> 1);
|
||||
|
@ -423,10 +370,7 @@ bool _fastTrack(const SwOutline* outline)
|
|||
bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox)
|
||||
{
|
||||
if (!shapeGenOutline(shape, sdata, tid, transform)) return false;
|
||||
|
||||
if (!_updateBBox(shape->outline, shape->bbox)) return false;
|
||||
|
||||
if (!_checkValid(shape->outline, shape->bbox, clip)) return false;
|
||||
if (!mathUpdateOutlineBBox(shape->outline, shape->bbox, clip)) return false;
|
||||
|
||||
bbox = shape->bbox;
|
||||
|
||||
|
@ -440,7 +384,7 @@ bool shapePrepared(const SwShape* shape)
|
|||
}
|
||||
|
||||
|
||||
bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite)
|
||||
bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias, bool hasComposite)
|
||||
{
|
||||
//FIXME: Should we draw it?
|
||||
//Case: Stroke Line
|
||||
|
@ -449,7 +393,7 @@ bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, const SwSize& cl
|
|||
//Case A: Fast Track Rectangle Drawing
|
||||
if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true;
|
||||
//Case B: Normale Shape RLE Drawing
|
||||
if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, clip, antiAlias))) return true;
|
||||
if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, antiAlias))) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -467,7 +411,7 @@ void shapeReset(SwShape* shape)
|
|||
rleReset(shape->rle);
|
||||
rleReset(shape->strokeRle);
|
||||
shape->rect = false;
|
||||
_initBBox(shape->bbox);
|
||||
shape->bbox.reset();
|
||||
}
|
||||
|
||||
|
||||
|
@ -622,14 +566,12 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const M
|
|||
goto fail;
|
||||
}
|
||||
|
||||
_updateBBox(strokeOutline, bbox);
|
||||
|
||||
if (!_checkValid(strokeOutline, bbox, clip)) {
|
||||
if (!mathUpdateOutlineBBox(strokeOutline, bbox, clip)) {
|
||||
ret = false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
shape->strokeRle = rleRender(shape->strokeRle, strokeOutline, bbox, clip, true);
|
||||
shape->strokeRle = rleRender(shape->strokeRle, strokeOutline, bbox, true);
|
||||
|
||||
fail:
|
||||
if (freeOutline) {
|
||||
|
@ -689,5 +631,4 @@ void shapeDelStrokeFill(SwShape* shape)
|
|||
if (!shape->stroke->fill) return;
|
||||
fillFree(shape->stroke->fill);
|
||||
shape->stroke->fill = nullptr;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue