From 2a396175274f3c7d0ae6648bf224c33efd5741ca Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 15 Apr 2020 02:11:18 +0900 Subject: [PATCH] implement rle path parts. Change-Id: I7200d80320404d6e7fb722042b8f330961bee76d --- src/lib/sw_engine/tvgSwCommon.h | 29 ++- src/lib/sw_engine/tvgSwRle.cpp | 440 ++++++++++++++++++++++++++++++--------- src/lib/sw_engine/tvgSwShape.cpp | 46 ++-- test/testShape.cpp | 2 +- 4 files changed, 395 insertions(+), 122 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 2269cfb..576a0b8 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -20,12 +20,33 @@ #include "tvgCommon.h" using namespace tvg; -using SwPoint = Point; -constexpr auto SW_CURVE_TAG_CONIC = 0; constexpr auto SW_CURVE_TAG_ON = 1; constexpr auto SW_CURVE_TAG_CUBIC = 2; +using SwCoord = signed long; + +struct SwPoint +{ + SwCoord x, y; + + SwPoint operator+(const SwPoint& rhs) const { + return {x + rhs.x, y + rhs.y}; + } + + SwPoint operator-(const SwPoint& rhs) const { + return {x - rhs.x, y - rhs.y}; + } + + bool operator==(const SwPoint& rhs ) const { + return (x == rhs.x && y == rhs.y); + } + + bool operator!=(const SwPoint& rhs) const { + return (x != rhs.x || y != rhs.y); + } +}; + struct SwOutline { size_t* cntrs; //the contour end points @@ -55,8 +76,8 @@ struct SwRleData struct SwBBox { - size_t xMin, yMin; - size_t xMax, yMax; + SwPoint min; + SwPoint max; }; struct SwShape diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index d208c53..f8292c6 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -18,58 +18,57 @@ #define _TVG_SW_RLE_H_ #include +#include #include "tvgSwCommon.h" /************************************************************************/ /* 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); + -using SwPtrDist = ptrdiff_t; -using TPos = long; -using TCoord = long; -using TArea = int; +using Area = long; -struct TBand +struct Band { - TPos min, max; + SwCoord min, max; }; -struct TCell +struct Cell { - TPos x; - TCoord cover; - TArea area; - TCell *next; + SwCoord x; + SwCoord cover; + Area area; + Cell *next; }; struct RleWorker { - TCoord ex, ey; - TPos exMin, exMax; - TPos eyMin, eyMax; - TPos exCnt, eyCnt; + SwPoint cellPos; + SwPoint cellMin; + SwPoint cellMax; + SwCoord cellXCnt; + SwCoord cellYCnt; - TArea area; - TCoord cover; + Area area; + SwCoord cover; - TCell* cells; - SwPtrDist maxCells; - SwPtrDist numCells; + Cell* cells; + ptrdiff_t maxCells; + ptrdiff_t cellsCnt; - TPos x, y; + SwPoint pos; - Point bezStack[32 * 3 + 1]; - int levStack[32]; + SwPoint bezStack[32 * 3 + 1]; + int levStack[32]; SwOutline* outline; - //SwBBox clipBox; SwSpan spans[MAX_SPANS]; int spansCnt; - - //render_span - //render_span_data; int ySpan; int bandSize; @@ -80,42 +79,311 @@ struct RleWorker void* buffer; long bufferSize; - TCell** yCells; - TPos yCnt; + Cell** yCells; + SwCoord yCnt; bool invalid; }; -static bool rleSweep(RleWorker& rw) + +static inline SwPoint UPSCALE(const SwPoint& pt) +{ + return {pt.x << (PIXEL_BITS - 6), pt.y << (PIXEL_BITS - 6)}; +} + + +static inline SwPoint DOWNSCALE(const SwPoint& pt) +{ + return {pt.x >> (PIXEL_BITS - 6), pt.y >> (PIXEL_BITS - 6)}; +} + + +static inline SwPoint TRUNC(const SwPoint& pt) +{ + return { pt.x >> PIXEL_BITS, pt.y >> PIXEL_BITS }; +} + + +static inline SwPoint SUBPIXELS(const SwPoint& pt) +{ + return {pt.x << PIXEL_BITS, pt.y << PIXEL_BITS }; +} + + +static inline SwCoord SUBPIXELS(const SwCoord x) +{ + return (x << PIXEL_BITS); +} + + +static void horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoord acount) { //TODO: - return true; } -static bool moveTo(SwPoint& pt) + +static void genSpan(RleWorker& rw) { - printf("moveTo = %f %f\n", pt.x, pt.y); - return true; + //TODO: } -static bool lineTo(SwPoint& pt) +static void sweep(RleWorker& rw) { - printf("lineTo = %f %f\n", pt.x, pt.y); - return true; + if (rw.cellsCnt == 0) return; + + rw.spansCnt = 0; + + for (int y = 0; y < rw.yCnt; ++y) { + + auto cover = 0; + auto x = 0; + auto cell = rw.yCells[y]; + + while (cell) { + + horizLine(rw, x, y, cover * (ONE_PIXEL * 2), cell->x - x); + cover += cell->cover; + auto area = cover * (ONE_PIXEL * 2) - cell->area; + + if (area != 0 && cell->x >= 0) + horizLine(rw, cell->x, y, area, 1); + + x = cell->x + 1; + cell = cell->next; + } + + if (cover != 0) + horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x); + } + + if (rw.spansCnt > 0) genSpan(rw); +} + + +static Cell* findCell(RleWorker& rw) +{ + auto x = rw.cellPos.x; + if (x > rw.cellXCnt) x = rw.cellXCnt; + + auto pcell = &rw.yCells[rw.cellPos.y]; + assert(pcell); + + while(true) { + Cell* cell = *pcell; + if (!cell || cell->x > x) break; + if (cell->x == x) return cell; + pcell = &cell->next; + } + + if (rw.cellsCnt >= rw.maxCells) longjmp(rw.jmpBuf, 1); + + auto cell = rw.cells + rw.cellsCnt++; + assert(cell); + cell->x = x; + cell->area = 0; + cell->cover = 0; + cell->next = *pcell; + *pcell = cell; + + return cell; +} + + +static void recordCell(RleWorker& rw) +{ + if (rw.area | rw.cover) { + auto cell = findCell(rw); + assert(cell); + cell->area += rw.area; + cell->cover += rw.cover; + } } +static void setCell(RleWorker& rw, SwPoint pos) +{ + /* 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 */ + /* in during the render phase. This means that: */ + /* */ + /* . the new vertical position must be within min_ey..max_ey-1. */ + /* . the new horizontal position must be strictly less than max_ex */ + /* */ + /* Note that if a cell is to the left of the clipping region, it is */ + /* actually set to the (min_ex-1) horizontal position. */ + + /* All cells that are on the left of the clipping region go to the + min_ex - 1 horizontal position. */ + pos.y -= rw.cellMin.y; + + if (pos.x > rw.cellMax.x) pos.x = rw.cellMax.x; + pos.x -= rw.cellMin.x; + if (pos.x < 0) pos.x = -1; + + //Are we moving to a different cell? + if (pos != rw.cellPos) { + if (!rw.invalid) recordCell(rw); + } -static bool cubicTo(SwPoint& ctrl1, SwPoint& ctrl2, SwPoint& pt) + rw.area = 0; + rw.cover = 0; + rw.cellPos = pos; + rw.invalid = ((unsigned)pos.y >= (unsigned)rw.cellYCnt || pos.x >= rw.cellXCnt); +} + + +static void startCell(RleWorker& rw, SwPoint pos) +{ + if (pos.x > rw.cellMax.x) pos.x = rw.cellMax.x; + if (pos.x < rw.cellMin.x) pos.x = rw.cellMin.x; + + rw.area = 0; + rw.cover = 0; + rw.cellPos = pos - rw.cellMin; + rw.invalid = false; + + setCell(rw, pos); +} + + +static void moveTo(RleWorker& rw, const SwPoint& to) +{ + //record current cell, if any */ + if (!rw.invalid) recordCell(rw); + + //start to a new position + startCell(rw, TRUNC(to)); + + rw.pos = to; +} + + +static void lineTo(RleWorker& rw, const SwPoint& to) +{ +#define SW_UDIV(a, b) \ + static_cast(((unsigned long)(a) * (unsigned long)(b)) >> \ + (sizeof(long) * CHAR_BIT - PIXEL_BITS)) + + auto e1 = TRUNC(rw.pos); + auto e2 = TRUNC(to); + + //vertical clipping + if ((e1.y >= rw.cellMax.y && e2.y >= rw.cellMax.y) || + (e1.y < rw.cellMin.y && e2.y >= rw.cellMin.y)) { + rw.pos = to; + return; + } + + auto diff = to - rw.pos; + auto f1 = rw.pos - SUBPIXELS(e1); + SwPoint f2; + + //inside one cell + if (e1 == e2) { + ; + //any horizontal line + } else if (diff.y == 0) { + e1.x = e2.x; + setCell(rw, e1); + } else if (diff.x == 0) { + //vertical line up + if (diff.y > 0) { + do { + f2.y = ONE_PIXEL; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * f1.x * 2; + f1.y = 0; + ++e1.y; + setCell(rw, e1); + } while(e1.y != e2.y); + //vertical line down + } else { + do { + f2.y = 0; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * f1.x * 2; + f1.y = ONE_PIXEL; + --e1.y; + setCell(rw, e1); + } while(e1.y != e2.y); + } + //any other line + } else { + Area prod = diff.x * f1.y - diff.y * f1.x; + + /* These macros speed up repetitive divisions by replacing them + with multiplications and right shifts. */ + auto dx_r = (ULONG_MAX >> PIXEL_BITS) / (diff.x); + auto dy_r = (ULONG_MAX >> PIXEL_BITS) / (diff.y); + + /* The fundamental value `prod' determines which side and the */ + /* exact coordinate where the line exits current cell. It is */ + /* also easily updated when moving from one cell to the next. */ + do { + auto px = diff.x * ONE_PIXEL; + auto py = diff.y * ONE_PIXEL; + + //left + if (prod <= 0 && prod - px) { + f2 = {0, SW_UDIV(-prod, -dx_r)}; + prod -= py; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {ONE_PIXEL, f2.y}; + --e1.x; + //up + } else if (prod - px <= 0 && prod - px + py > 0) { + prod -= px; + f2 = {SW_UDIV(-prod, dy_r), ONE_PIXEL}; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {f2.x, 0}; + ++e1.y; + //right + } else if (prod - px + py <= 0 && prod + py >= 0) { + prod += py; + f2 = {ONE_PIXEL, SW_UDIV(prod, dx_r)}; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {0, f2.y}; + ++e1.x; + //down + } else { + f2 = {SW_UDIV(prod, -dy_r), 0}; + prod += px; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {f2.x, ONE_PIXEL}; + --e1.y; + } + + setCell(rw, e1); + + } while(e1 != e2); + } + + f2 = {to.x - SUBPIXELS(e2.x), to.y - SUBPIXELS(e2.y)}; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + rw.pos = to; +} + + +static bool renderCubic(RleWorker& rw, SwPoint& ctrl1, SwPoint& ctrl2, SwPoint& to) { - printf("cubicTo = ctrl1(%f %f) ctrl2(%f %f) pt(%f %f)\n", ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, pt.x, pt.y); return true; } +static bool cubicTo(RleWorker& rw, SwPoint& ctrl1, SwPoint& ctrl2, SwPoint& to) +{ + return renderCubic(rw, ctrl1, ctrl2, to); +} + + static bool decomposeOutline(RleWorker& rw) { - printf("decomposOutline\n"); + // printf("decomposOutline\n"); auto outline = rw.outline; assert(outline); @@ -134,7 +402,7 @@ static bool decomposeOutline(RleWorker& rw) /* A contour cannot start with a cubic control point! */ if (tags[0] == SW_CURVE_TAG_CUBIC) goto invalid_outline; - if (!moveTo(outline->pts[first])) return false; + moveTo(rw, UPSCALE(outline->pts[first])); while (pt < limit) { assert(++pt); @@ -142,8 +410,7 @@ static bool decomposeOutline(RleWorker& rw) //emit a single line_to if (tags[0] == SW_CURVE_TAG_ON) { - if (!lineTo(*pt)) return false; - continue; + lineTo(rw, UPSCALE(*pt)); //tag cubic } else { if (pt + 1 > limit || tags[1] != SW_CURVE_TAG_CUBIC) @@ -153,16 +420,16 @@ static bool decomposeOutline(RleWorker& rw) tags += 2; if (pt <= limit) { - if (!cubicTo(pt[-2], pt[-1], pt[0])) return false; + if (!cubicTo(rw, pt[-2], pt[-1], pt[0])) return false; continue; } - if (!cubicTo(pt[-2], pt[-1], outline->pts[first])) return false; + if (!cubicTo(rw, pt[-2], pt[-1], outline->pts[first])) return false; goto close; } } //Close the contour with a line segment? - //if (!lineTo(outline->pts[first])); + //if (!lineTo(rw, outline->pts[first])); close: first = last + 1; } @@ -175,24 +442,6 @@ invalid_outline: } -static TCell* findCell(RleWorker& rw) -{ - //TODO: - return nullptr; -} - - -static void recordCell(RleWorker& rw) -{ - if (rw.area | rw.cover) { - TCell* cell = findCell(rw); - assert(cell); - cell->area += rw.area; - cell->cover += rw.cover; - } -} - - static bool genRle(RleWorker& rw) { bool ret = false; @@ -214,7 +463,7 @@ static bool genRle(RleWorker& rw) bool rleRender(SwShape& sdata) { constexpr auto RENDER_POOL_SIZE = 16384L; - constexpr auto BAND_SIZE = 40; + constexpr auto BAND_SIZE = 39; auto outline = sdata.outline; assert(outline); @@ -226,42 +475,39 @@ bool rleRender(SwShape& sdata) //TODO: We can preserve several static workers in advance RleWorker rw; - TCell buffer[RENDER_POOL_SIZE / sizeof(TCell)]; + Cell buffer[RENDER_POOL_SIZE / sizeof(Cell)]; //Init Cells rw.buffer = buffer; rw.bufferSize = sizeof(buffer); - rw.yCells = reinterpret_cast(buffer); + rw.yCells = reinterpret_cast(buffer); rw.cells = nullptr; rw.maxCells = 0; - rw.numCells = 0; + rw.cellsCnt = 0; rw.area = 0; rw.cover = 0; rw.invalid = true; - rw.exMin = sdata.bbox.xMin; - rw.exMax = sdata.bbox.xMax; - rw.eyMin = sdata.bbox.yMin; - rw.eyMax = sdata.bbox.yMax; - rw.exCnt = rw.exMax - rw.exMin; - rw.eyCnt = rw.eyMax - rw.eyMin; + rw.cellMin = sdata.bbox.min; + rw.cellMax = sdata.bbox.max; + rw.cellXCnt = rw.cellMax.x - rw.cellMin.x; + rw.cellYCnt = rw.cellMax.y - rw.cellMin.y; rw.outline = outline; - rw.bandSize = rw.bufferSize / (sizeof(TCell) * 8); //bandSize: 64 + rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64 rw.bandShoot = 0; - //printf("bufferSize = %d, bbox(%d %d %d %d), exCnt(%d), eyCnt(%d), bandSize(%d)\n", rw.bufferSize, rw.exMin, rw.eyMin, rw.exMax, rw.eyMax, rw.exCnt, rw.eyCnt, rw.bandSize); + //printf("bufferSize = %d, bbox(%f %f %f %f), exCnt(%f), eyCnt(%f), bandSize(%d)\n", rw.bufferSize, rw.exMin, rw.eyMin, rw.exMax, rw.eyMax, rw.exCnt, rw.eyCnt, rw.bandSize); //Generate RLE - TBand bands[BAND_SIZE]; - TBand* band; + Band bands[BAND_SIZE]; + Band* band; /* set up vertical bands */ - auto bandCnt = (rw.eyMax - rw.eyMin) / rw.bandSize; + auto bandCnt = static_cast((rw.cellMax.y - rw.cellMin.y) / rw.bandSize); if (bandCnt == 0) bandCnt = 1; - else if (bandCnt >= BAND_SIZE) bandCnt = BAND_SIZE - 1; + else if (bandCnt >= BAND_SIZE) bandCnt = BAND_SIZE; - auto min = rw.eyMin; - auto yMax = rw.eyMax; - TPos max; -//printf("bandCnt(%d)\n", bandCnt); + auto min = rw.cellMin.y; + auto yMax = rw.cellMax.y; + SwCoord max; for (int n = 0; n < bandCnt; ++n, min = max) { max = min + rw.bandSize; @@ -272,20 +518,20 @@ bool rleRender(SwShape& sdata) band = bands; while (band >= bands) { - rw.yCells = static_cast(rw.buffer); + rw.yCells = static_cast(rw.buffer); rw.yCnt = band->max - band->min; - auto cellStart = sizeof(TCell*) * rw.yCnt; - auto cellMod = cellStart % sizeof(TCell); + auto cellStart = sizeof(Cell*) * (int)rw.yCnt; + auto cellMod = cellStart % sizeof(Cell); - if (cellMod > 0) cellStart += sizeof(TCell) - cellMod; + if (cellMod > 0) cellStart += sizeof(Cell) - cellMod; auto cellEnd = rw.bufferSize; - cellEnd -= cellEnd % sizeof(TCell); + cellEnd -= cellEnd % sizeof(Cell); //printf("n:%d, cellStart(%d), cellEnd(%d) cellMod(%d)\n", n, cellStart, cellEnd, cellMod); - auto cellsMax = reinterpret_cast((char*)rw.buffer + cellEnd); - rw.cells = reinterpret_cast((char*)rw.buffer + cellStart); + auto cellsMax = reinterpret_cast((char*)rw.buffer + cellEnd); + rw.cells = reinterpret_cast((char*)rw.buffer + cellStart); if (rw.cells >= cellsMax) goto reduce_bands; @@ -295,15 +541,15 @@ bool rleRender(SwShape& sdata) for (auto y = 0; y < rw.yCnt; ++y) rw.yCells[y] = nullptr; - rw.numCells = 0; + rw.cellsCnt = 0; rw.invalid = true; - rw.eyMin = band->min; - rw.eyMax = band->max; - rw.eyCnt = band->max - band->min; + rw.cellMin.y = band->min; + rw.cellMax.y = band->max; + rw.cellYCnt = band->max - band->min; if (!genRle(rw)) return -1; - rleSweep(rw); + sweep(rw); --band; continue; @@ -328,7 +574,7 @@ bool rleRender(SwShape& sdata) } if (rw.bandShoot > 8 && rw.bandSize > 16) - rw.bandSize = rw.bandSize / 2; + rw.bandSize = (rw.bandSize >> 1); return true; } diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 746fa89..0f2a6fa 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -23,6 +23,12 @@ /* Internal Class Implementation */ /************************************************************************/ +static inline SwPoint TO_SWPOINT(const Point* pt) +{ + return {SwCoord(pt->x * 64), SwCoord(pt->y * 64)}; +} + + static void growOutlineContour(SwOutline& outline, size_t n) { if (n == 0) { @@ -57,7 +63,7 @@ static void growOutlinePoint(SwOutline& outline, size_t n) cout << "Grow Pts: " << outline.reservedPtsCnt << " -> " << outline.ptsCnt + n << endl; outline.reservedPtsCnt = n; - outline.pts = static_cast(realloc(outline.pts, n * sizeof(Point))); + outline.pts = static_cast(realloc(outline.pts, n * sizeof(SwPoint))); assert(outline.pts); outline.tags = static_cast(realloc(outline.tags, n * sizeof(char))); assert(outline.tags); @@ -74,13 +80,13 @@ static void outlineEnd(SwOutline& outline) } -static void outlineMoveTo(SwOutline& outline, const Point* pt) +static void outlineMoveTo(SwOutline& outline, const Point* to) { - assert(pt); + assert(to); growOutlinePoint(outline, 1); - outline.pts[outline.ptsCnt] = *pt; + outline.pts[outline.ptsCnt] = TO_SWPOINT(to); outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON; if (outline.ptsCnt > 0) { @@ -93,34 +99,34 @@ static void outlineMoveTo(SwOutline& outline, const Point* pt) } -static void outlineLineTo(SwOutline& outline, const Point* pt) +static void outlineLineTo(SwOutline& outline, const Point* to) { - assert(pt); + assert(to); growOutlinePoint(outline, 1); - outline.pts[outline.ptsCnt] = *pt; + outline.pts[outline.ptsCnt] = TO_SWPOINT(to); outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON; ++outline.ptsCnt; } -static void outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* pt) +static void outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* to) { - assert(ctrl1 && ctrl2 && pt); + assert(ctrl1 && ctrl2 && to); growOutlinePoint(outline, 3); - outline.pts[outline.ptsCnt] = *ctrl1; + outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl1); outline.tags[outline.ptsCnt] = SW_CURVE_TAG_CUBIC; ++outline.ptsCnt; - outline.pts[outline.ptsCnt] = *ctrl2; + outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl2); outline.tags[outline.ptsCnt] = SW_CURVE_TAG_CUBIC; ++outline.ptsCnt; - outline.pts[outline.ptsCnt] = *ctrl1; + outline.pts[outline.ptsCnt] = TO_SWPOINT(to); outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON; ++outline.ptsCnt; } @@ -152,8 +158,8 @@ static bool outlineClose(SwOutline& outline) static void initBBox(SwShape& sdata) { - sdata.bbox.xMin = sdata.bbox.yMin = 0; - sdata.bbox.xMax = sdata.bbox.yMax = 0; + sdata.bbox.min.x = sdata.bbox.min.y = 0; + sdata.bbox.max.x = sdata.bbox.max.y = 0; } @@ -171,7 +177,7 @@ static bool updateBBox(SwShape& sdata) } auto xMin = pt->x; - auto xMax = pt->y; + auto xMax = pt->x; auto yMin = pt->y; auto yMax = pt->y; @@ -180,14 +186,14 @@ static bool updateBBox(SwShape& sdata) for(size_t i = 1; i < outline->ptsCnt; ++i, ++pt) { assert(pt); if (xMin > pt->x) xMin = pt->x; - if (xMax < pt->y) xMax = pt->x; + if (xMax < pt->x) xMax = pt->x; if (yMin > pt->y) yMin = pt->y; if (yMax < pt->y) yMax = pt->y; } - sdata.bbox.xMin = round(xMin - 0.49); - sdata.bbox.xMax = round(xMax + 0.49); - sdata.bbox.yMin = round(yMin - 0.49); - sdata.bbox.yMax = round(yMax + 0.49); + sdata.bbox.min.x = xMin >> 6; + sdata.bbox.max.x = (xMax + 63) >> 6; + sdata.bbox.min.y = yMin >> 6; + sdata.bbox.max.y = (yMax + 63) >> 6; if (xMax - xMin < 1 || yMax - yMin < 1) return false; diff --git a/test/testShape.cpp b/test/testShape.cpp index 64603ae..d1da21e 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -18,7 +18,7 @@ int main(int argc, char **argv) //Prepare a Shape (Rectangle) auto shape1 = tvg::ShapeNode::gen(); shape1->appendRect(0, 0, 400, 400, 0); //x, y, w, h, corner_radius - shape1->fill(0, 255, 0, 255); //r, g, b, a + shape1->fill(0, 255, 0, 255); //r, g, b, a /* Push the shape into the Canvas drawing list When this shape is into the canvas list, the shape could update & prepare -- 2.7.4