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:
Hermet Park 2021-03-24 18:48:39 +09:00 committed by GitHub
parent 19fc4f4b37
commit 4a8f45577a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 146 deletions

View file

@ -53,25 +53,30 @@ struct SwPoint
{ {
SwCoord x, y; SwCoord x, y;
SwPoint& operator+=(const SwPoint& rhs) { SwPoint& operator+=(const SwPoint& rhs)
{
x += rhs.x; x += rhs.x;
y += rhs.y; y += rhs.y;
return *this; return *this;
} }
SwPoint operator+(const SwPoint& rhs) const { SwPoint operator+(const SwPoint& rhs) const
{
return {x + rhs.x, y + rhs.y}; 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}; 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); 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); return (x != rhs.x || y != rhs.y);
} }
@ -125,6 +130,11 @@ struct SwRleData
struct SwBBox struct SwBBox
{ {
SwPoint min, max; SwPoint min, max;
void reset()
{
min.x = min.y = max.x = max.y = 0;
}
}; };
struct SwFill struct SwFill
@ -286,12 +296,13 @@ SwFixed mathLength(const SwPoint& pt);
bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut); bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
SwFixed mathMean(SwFixed angle1, SwFixed angle2); SwFixed mathMean(SwFixed angle1, SwFixed angle2);
SwPoint mathTransform(const Point* to, const Matrix* transform); SwPoint mathTransform(const Point* to, const Matrix* transform);
bool mathUpdateOutlineBBox(const SwOutline* outline, SwBBox& bbox, const SwSize& clip);
void shapeReset(SwShape* shape); void shapeReset(SwShape* shape);
bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform); 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 shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
bool shapePrepared(const SwShape* shape); 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 shapeDelOutline(SwShape* shape, uint32_t tid);
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform); 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); 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 imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
bool imagePrepared(const SwImage* image); 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 imageDelOutline(SwImage* image, uint32_t tid);
void imageReset(SwImage* image); void imageReset(SwImage* image);
bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform); 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 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); 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 rleFree(SwRleData* rle);
void rleReset(SwRleData* rle); void rleReset(SwRleData* rle);
void rleClipPath(SwRleData *rle, const SwRleData *clip); void rleClipPath(SwRleData *rle, const SwRleData *clip);

View file

@ -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 */ /* 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) 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 (!imageGenOutline(image, pdata, tid, transform)) return false;
if (!mathUpdateOutlineBBox(image->outline, bbox, clip)) return false;
if (!_updateBBox(image->outline, bbox, clip)) return false; //Guarantee boundary from mathUpdateOutlineBBox()
bbox.min.x = max(bbox.min.x, TO_SWCOORD(0));
if (!_checkValid(image->outline, bbox, clip)) return false; bbox.min.y = max(bbox.min.y, TO_SWCOORD(0));
return true; 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; return false;
} }

View file

@ -427,3 +427,46 @@ SwPoint mathTransform(const Point* to, const Matrix* transform)
return {TO_SWCOORD(tx), TO_SWCOORD(ty)}; 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;
}

View file

@ -100,7 +100,7 @@ struct SwShapeTask : SwTask
shape outline below stroke could be full covered by stroke drawing. shape outline below stroke could be full covered by stroke drawing.
Thus it turns off antialising in that condition. */ Thus it turns off antialising in that condition. */
auto antiAlias = (strokeAlpha == 255 && strokeWidth > 2) ? false : true; 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; ++addStroking;
} }
} }
@ -189,7 +189,7 @@ struct SwImageTask : SwTask
//Clip Path? //Clip Path?
if (clips.count > 0) { 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) { if (image.rle) {
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape; auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;

View file

@ -87,8 +87,6 @@ struct RleWorker
Cell** yCells; Cell** yCells;
SwCoord yCnt; SwCoord yCnt;
SwSize clip;
bool invalid; bool invalid;
bool antiAlias; bool antiAlias;
}; };
@ -161,8 +159,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
y += rw.cellMin.y; y += rw.cellMin.y;
//Clip Y range //Clip Y range
if (y < 0) return; if (y < 0 || y >= rw.cellMax.y) return;
if (y >= rw.clip.h) return;
/* compute the coverage line's coverage, depending on the outline fill rule */ /* compute the coverage line's coverage, depending on the outline fill rule */
/* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ /* 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 //Clip x range
SwCoord xOver = 0; 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; if (x < 0) xOver += x;
//span->len += (acount + xOver) - 1; //span->len += (acount + xOver) - 1;
@ -219,7 +216,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
//Clip x range //Clip x range
SwCoord xOver = 0; 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) { if (x < 0) {
xOver += x; xOver += x;
x = 0; x = 0;
@ -785,7 +782,7 @@ void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
/* External Class Implementation */ /* 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 RENDER_POOL_SIZE = 16384L;
constexpr auto BAND_SIZE = 40; 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.outline = const_cast<SwOutline*>(outline);
rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64 rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64
rw.bandShoot = 0; rw.bandShoot = 0;
rw.clip = clip;
rw.antiAlias = antiAlias; rw.antiAlias = antiAlias;
if (!rle) rw.rle = reinterpret_cast<SwRleData*>(calloc(1, sizeof(SwRleData))); if (!rle) rw.rle = reinterpret_cast<SwRleData*>(calloc(1, sizeof(SwRleData)));

View file

@ -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) static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* transform)
{ {
_growOutlinePoint(*dash.outline, dash.outline->ptsCnt >> 1); _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) 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 (!shapeGenOutline(shape, sdata, tid, transform)) return false;
if (!mathUpdateOutlineBBox(shape->outline, shape->bbox, clip)) return false;
if (!_updateBBox(shape->outline, shape->bbox)) return false;
if (!_checkValid(shape->outline, shape->bbox, clip)) return false;
bbox = shape->bbox; 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? //FIXME: Should we draw it?
//Case: Stroke Line //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 //Case A: Fast Track Rectangle Drawing
if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true; if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true;
//Case B: Normale Shape RLE Drawing //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; return false;
} }
@ -467,7 +411,7 @@ void shapeReset(SwShape* shape)
rleReset(shape->rle); rleReset(shape->rle);
rleReset(shape->strokeRle); rleReset(shape->strokeRle);
shape->rect = false; 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; goto fail;
} }
_updateBBox(strokeOutline, bbox); if (!mathUpdateOutlineBBox(strokeOutline, bbox, clip)) {
if (!_checkValid(strokeOutline, bbox, clip)) {
ret = false; ret = false;
goto fail; goto fail;
} }
shape->strokeRle = rleRender(shape->strokeRle, strokeOutline, bbox, clip, true); shape->strokeRle = rleRender(shape->strokeRle, strokeOutline, bbox, true);
fail: fail:
if (freeOutline) { if (freeOutline) {
@ -690,4 +632,3 @@ void shapeDelStrokeFill(SwShape* shape)
fillFree(shape->stroke->fill); fillFree(shape->stroke->fill);
shape->stroke->fill = nullptr; shape->stroke->fill = nullptr;
} }