aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkBitmapProcState_matrixProcs.cpp
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-13 19:39:03 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-13 19:39:03 +0000
commit4d0078aa5115fab8ccd8ef59519a8937ea4e8854 (patch)
tree7206ce8675f4a03b82ec3d975dd02f83c22f0578 /src/core/SkBitmapProcState_matrixProcs.cpp
parent4d73ac22a1b99402fc8cff78a4eb4b27aa8fe019 (diff)
Fix calling (and checking) the decal_ functions when the input is SkFractionalInt.
The bug was to cast to SkFixed from SkFractionalInt, when what we needed to do was shift the fractional guy down to fixed. This bug was only caught on an android device w/o neon, since other configs have assembly for their matrixproc that didn't have this bug. Review URL: https://codereview.appspot.com/6303074 git-svn-id: http://skia.googlecode.com/svn/trunk@4256 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkBitmapProcState_matrixProcs.cpp')
-rw-r--r--src/core/SkBitmapProcState_matrixProcs.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp
index c043e8610c..1e12f9a921 100644
--- a/src/core/SkBitmapProcState_matrixProcs.cpp
+++ b/src/core/SkBitmapProcState_matrixProcs.cpp
@@ -35,6 +35,35 @@ static inline int sk_int_mod(int x, int n) {
return x;
}
+/*
+ * The decal_ functions require that
+ * 1. dx > 0
+ * 2. [fx, fx+dx, fx+2dx, fx+3dx, ... fx+(count-1)dx] are all <= maxX
+ *
+ * In addition, we use SkFractionalInt to keep more fractional precision than
+ * just SkFixed, so we will abort the decal_ call if dx is very small, since
+ * the decal_ function just operates on SkFixed. If that were changed, we could
+ * skip the very_small test here.
+ */
+static inline bool can_truncate_to_fixed_for_decal(SkFractionalInt frX,
+ SkFractionalInt frDx,
+ int count, unsigned max) {
+ SkFixed dx = SkFractionalIntToFixed(frDx);
+
+ // if decal_ kept SkFractionalInt precision, this would just be dx <= 0
+ // I just made up the 1/256. Just don't want to perceive accumulated error
+ // if we truncate frDx and lose its low bits.
+ if (dx <= SK_Fixed1 / 256) {
+ return false;
+ }
+
+ // We cast to unsigned so we don't have to check for negative values, which
+ // will now appear as very large positive values, and thus fail our test!
+ SkFixed fx = SkFractionalIntToFixed(frX);
+ return (unsigned)SkFixedFloorToInt(fx) <= max &&
+ (unsigned)SkFixedFloorToInt(fx + dx * (count - 1)) < max;
+}
+
void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);