aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-01-27 15:39:32 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-27 21:13:53 +0000
commit0bd8f36309293720b44af92f113f6ebe96d54779 (patch)
tree085a099af622bd60fad3420cd1d4a445728e5442
parent86cc841e23a81af69269de87224c57be274f40d1 (diff)
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 <fmalita@chromium.org> Reviewed-by: Herb Derby <herb@google.com>
-rw-r--r--src/core/SkLinearBitmapPipeline_tile.h16
1 files changed, 10 insertions, 6 deletions
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