From 0bd8f36309293720b44af92f113f6ebe96d54779 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Fri, 27 Jan 2017 15:39:32 -0500 Subject: Add missing nextafter() clamping to SkLinearBitmapPipeline tile procs Fixes the asserts trigered in https://skia-review.googlesource.com/c/7615 Change-Id: I7e1802bc699becf85396445fe0df4cb110ab69c4 Reviewed-on: https://skia-review.googlesource.com/7720 Commit-Queue: Florin Malita Reviewed-by: Herb Derby --- src/core/SkLinearBitmapPipeline_tile.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/core/SkLinearBitmapPipeline_tile.h') diff --git a/src/core/SkLinearBitmapPipeline_tile.h b/src/core/SkLinearBitmapPipeline_tile.h index 716b9bd14c..e18f7a1a5d 100644 --- a/src/core/SkLinearBitmapPipeline_tile.h +++ b/src/core/SkLinearBitmapPipeline_tile.h @@ -143,8 +143,10 @@ private: const SkScalar fYMaxPixel; }; -SkScalar tile_mod(SkScalar x, SkScalar base) { - return x - SkScalarFloorToScalar(x / base) * base; +SkScalar tile_mod(SkScalar x, SkScalar base, SkScalar cap) { + // When x is a negative number *very* close to zero, the difference becomes 0 - (-base) = base + // which is an out of bound value. The min() corrects these problematic values. + return std::min(x - SkScalarFloorToScalar(x / base) * base, cap); } class XRepeatStrategy { @@ -167,7 +169,7 @@ public: SkPoint start; SkScalar length; int count; std::tie(start, length, count) = originalSpan; // Make x and y in range on the tile. - SkScalar x = tile_mod(X(start), fXMax); + SkScalar x = tile_mod(X(start), fXMax, fXCap); SkScalar y = Y(start); SkScalar dx = length / (count - 1); @@ -261,7 +263,7 @@ public: SkPoint start; SkScalar length; int count; std::tie(start, length, count) = originalSpan; // Make x and y in range on the tile. - SkScalar x = tile_mod(X(start), fXMax); + SkScalar x = tile_mod(X(start), fXMax, fXCap); SkScalar y = Y(start); // No need trying to go fast because the steps are larger than a tile or there is one point. @@ -326,23 +328,25 @@ class YRepeatStrategy { public: YRepeatStrategy(int32_t max) : fYMax{SkScalar(max)} + , fYCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} , fYsInvMax{1.0f / SkScalar(max)} { } void tileYPoints(Sk4s* ys) { Sk4s divY = *ys * fYsInvMax; Sk4s modY = *ys - divY.floor() * fYMax; - *ys = modY; + *ys = Sk4s::Min(fYCap, modY); assertTiled(*ys, fYMax); } SkScalar tileY(SkScalar y) { - SkScalar answer = tile_mod(y, fYMax); + SkScalar answer = tile_mod(y, fYMax, fYCap); SkASSERT(0 <= answer && answer < fYMax); return answer; } private: const SkScalar fYMax; + const SkScalar fYCap; const SkScalar fYsInvMax; }; // max = 40 -- cgit v1.2.3