diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 0bc0052d..0b800815 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -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); diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp index f8d7f5eb..80a139f2 100644 --- a/src/lib/sw_engine/tvgSwImage.cpp +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -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; } diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index 60e36aad..03f9cbf2 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -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; +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index fe679169..549f6746 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -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(*clip)->shape; diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index 27906c4b..5c4719a4 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -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(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(calloc(1, sizeof(SwRleData))); diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index afb7f1cd..cd951ddd 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -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; -} - +} \ No newline at end of file