Upstream mulDiv255Ceil() from WebKit to the skia repository.
authorsenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 7 Dec 2010 21:07:56 +0000 (21:07 +0000)
committersenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 7 Dec 2010 21:07:56 +0000 (21:07 +0000)
(Patch by Noel Gordon (noel.gordon@gmail.com))

Review URL:  http://codereview.appspot.com/3466042

git-svn-id: http://skia.googlecode.com/svn/trunk@632 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkMath.h
tests/MathTest.cpp

index e0f23617ee61fdf29343c2e40122721ea5e306be..22ebd6074894e704f53cb8d5785180407a197092 100644 (file)
@@ -213,6 +213,16 @@ static inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) {
     return (prod + (prod >> 8)) >> 8;
 }
 
+/** Return (a*b)/255, taking the ceiling of any fractional bits. Only valid if
+    both a and b are 0..255. The expected result equals (a * b + 254) / 255.
+ */
+static inline U8CPU SkMulDiv255Ceiling(U8CPU a, U8CPU b) {
+    SkASSERT((uint8_t)a == a);
+    SkASSERT((uint8_t)b == b);
+    unsigned prod = SkMulS16(a, b) + 255;
+    return (prod + (prod >> 8)) >> 8;
+}
+
 /** Return a*b/((1 << shift) - 1), rounding any fractional bits.
     Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
 */
index 4bfbd94283f3ec8eacd78bdf71c5a78d3f4a9341..2555d7386681d7ec82259c5bf184acd5e88ffa00 100644 (file)
@@ -171,6 +171,19 @@ static void test_muldiv255(skiatest::Reporter* reporter) {
 #endif
 }
 
+static void test_muldiv255ceiling(skiatest::Reporter* reporter) {
+    for (int c = 0; c <= 255; c++) {
+        for (int a = 0; a <= 255; a++) {
+            int product = (c * a + 255);
+            int expected_ceiling = (product + (product >> 8)) >> 8;
+            int webkit_ceiling = (c * a + 254) / 255;
+            REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling);
+            int skia_ceiling = SkMulDiv255Ceiling(c, a);
+            REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling);
+        }
+    }
+}
+
 static void test_copysign(skiatest::Reporter* reporter) {
     static const int32_t gTriples[] = {
         // x, y, expected result
@@ -237,6 +250,7 @@ static void TestMath(skiatest::Reporter* reporter) {
 #endif
 
     test_muldiv255(reporter);
+    test_muldiv255ceiling(reporter);
     test_copysign(reporter);
 
     {