add test for different srcover implementations



git-svn-id: http://skia.googlecode.com/svn/trunk@103 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/Makefile b/Makefile
index 9dd85f5..bb122ef 100644
--- a/Makefile
+++ b/Makefile
@@ -92,8 +92,8 @@
 
 TESTS_SRCS := GeometryTest.cpp MathTest.cpp MatrixTest.cpp PackBitsTest.cpp \
               Sk64Test.cpp StringTest.cpp Test.cpp UtilsTest.cpp PathTest.cpp \
-	      ClipCubicTest.cpp \
-              main.cpp
+              ClipCubicTest.cpp SrcOverTest.cpp main.cpp
+
 TESTS_SRCS := $(addprefix tests/, $(TESTS_SRCS))
 
 TESTS_OBJS := $(TESTS_SRCS:.cpp=.o)
diff --git a/tests/SrcOverTest.cpp b/tests/SrcOverTest.cpp
new file mode 100644
index 0000000..cf429de
--- /dev/null
+++ b/tests/SrcOverTest.cpp
@@ -0,0 +1,71 @@
+#include "Test.h"
+#include "SkColorPriv.h"
+#include "SkXfermode.h"
+
+// our std SkAlpha255To256
+static int test_srcover0(unsigned dst, unsigned alpha) {
+    return alpha + SkAlphaMul(dst, SkAlpha255To256(255 - alpha));
+}
+
+// faster hack +1
+static int test_srcover1(unsigned dst, unsigned alpha) {
+    return alpha + SkAlphaMul(dst, 256 - alpha);
+}
+
+// slower "correct"
+static int test_srcover2(unsigned dst, unsigned alpha) {
+    return alpha + SkMulDiv255Round(dst, 255 - alpha);
+}
+
+static void test_srcover_hack(skiatest::Reporter* reporter) {
+    /*  Here's the idea. Can we ensure that when we blend on top of an opaque
+        dst, that the result always stay's opaque (i.e. exactly 255)?
+     */
+    
+    unsigned i;
+    int opaqueCounter0 = 0;
+    int opaqueCounter1 = 0;
+    int opaqueCounter2 = 0;
+    for (i = 0; i <= 255; i++) {
+        unsigned result0 = test_srcover0(0xFF, i);
+        unsigned result1 = test_srcover1(0xFF, i);
+        unsigned result2 = test_srcover2(0xFF, i);
+        opaqueCounter0 += (result0 == 0xFF);
+        opaqueCounter1 += (result1 == 0xFF);
+        opaqueCounter2 += (result2 == 0xFF);
+    }
+#if 0
+    SkDebugf("---- opaque test: [%d %d %d]\n",
+             opaqueCounter0, opaqueCounter1, opaqueCounter2);
+#endif
+    // we acknowledge that technique0 does not always return opaque
+    REPORTER_ASSERT(reporter, opaqueCounter0 == 129);
+    REPORTER_ASSERT(reporter, opaqueCounter1 == 256);
+    REPORTER_ASSERT(reporter, opaqueCounter2 == 256);
+    
+    // Now ensure that we never over/underflow a byte
+    for (i = 0; i <= 255; i++) {
+        for (unsigned dst = 0; dst <= 255; dst++) {
+            unsigned r0 = test_srcover0(dst, i);
+            unsigned r1 = test_srcover1(dst, i);
+            unsigned r2 = test_srcover2(dst, i);
+            unsigned max = SkMax32(dst, i);
+            // ignore the known failure
+            if (dst != 255) {
+                REPORTER_ASSERT(reporter, r0 <= 255 && r0 >= max);
+            }
+            REPORTER_ASSERT(reporter, r1 <= 255 && r1 >= max);
+            REPORTER_ASSERT(reporter, r2 <= 255 && r2 >= max);
+            
+#if 0
+            // this shows where r1 (faster) differs from r2 (more exact)
+            if (r1 != r2) {
+                SkDebugf("--- dst=%d i=%d r1=%d r2=%d exact=%g\n", dst, i, r1, r2, i + dst - dst*i/255.0f);
+            }
+#endif
+        }
+    }
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("SrcOver", SrcOverTestClass, test_srcover_hack)
diff --git a/tests/TestXCode/Tests.xcodeproj/project.pbxproj b/tests/TestXCode/Tests.xcodeproj/project.pbxproj
index cc2448a..ec2c171 100644
--- a/tests/TestXCode/Tests.xcodeproj/project.pbxproj
+++ b/tests/TestXCode/Tests.xcodeproj/project.pbxproj
@@ -15,6 +15,8 @@
 		008634DC0F579B7A0044DA64 /* PackBitsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008634DB0F579B7A0044DA64 /* PackBitsTest.cpp */; };
 		008634F10F579E410044DA64 /* MatrixTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008634F00F579E410044DA64 /* MatrixTest.cpp */; };
 		0086350F0F57A3140044DA64 /* UtilsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0086350E0F57A3140044DA64 /* UtilsTest.cpp */; };
+		009CC7840F5DAE2B002185BE /* SrcOverTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 009CC7830F5DAE2B002185BE /* SrcOverTest.cpp */; };
+		009CC7880F5DAF16002185BE /* ClipCubicTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 009CC7870F5DAF16002185BE /* ClipCubicTest.cpp */; };
 		00A9BF860F584CF30091AD2D /* Sk64Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A9BF850F584CF30091AD2D /* Sk64Test.cpp */; };
 		00A9BFA30F584E150091AD2D /* StringTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A9BFA20F584E150091AD2D /* StringTest.cpp */; };
 		00A9BFBC0F5851570091AD2D /* GeometryTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A9BFBB0F5851570091AD2D /* GeometryTest.cpp */; };
@@ -76,6 +78,8 @@
 		008634DB0F579B7A0044DA64 /* PackBitsTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PackBitsTest.cpp; path = ../PackBitsTest.cpp; sourceTree = SOURCE_ROOT; };
 		008634F00F579E410044DA64 /* MatrixTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MatrixTest.cpp; path = ../MatrixTest.cpp; sourceTree = SOURCE_ROOT; };
 		0086350E0F57A3140044DA64 /* UtilsTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UtilsTest.cpp; path = ../UtilsTest.cpp; sourceTree = SOURCE_ROOT; };
+		009CC7830F5DAE2B002185BE /* SrcOverTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SrcOverTest.cpp; path = ../SrcOverTest.cpp; sourceTree = SOURCE_ROOT; };
+		009CC7870F5DAF16002185BE /* ClipCubicTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClipCubicTest.cpp; path = ../ClipCubicTest.cpp; sourceTree = SOURCE_ROOT; };
 		00A9BF850F584CF30091AD2D /* Sk64Test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Sk64Test.cpp; path = ../Sk64Test.cpp; sourceTree = SOURCE_ROOT; };
 		00A9BFA20F584E150091AD2D /* StringTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringTest.cpp; path = ../StringTest.cpp; sourceTree = SOURCE_ROOT; };
 		00A9BFA60F584F200091AD2D /* TestClassDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestClassDef.h; path = ../TestClassDef.h; sourceTree = SOURCE_ROOT; };
@@ -129,6 +133,7 @@
 		08FB7795FE84155DC02AAC07 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				009CC7870F5DAF16002185BE /* ClipCubicTest.cpp */,
 				276D93070F5B9FEA0081B3B9 /* PathTest.cpp */,
 				00A9BF850F584CF30091AD2D /* Sk64Test.cpp */,
 				00A9BFBB0F5851570091AD2D /* GeometryTest.cpp */,
@@ -141,6 +146,7 @@
 				008634F00F579E410044DA64 /* MatrixTest.cpp */,
 				00A9BFA60F584F200091AD2D /* TestClassDef.h */,
 				008634DB0F579B7A0044DA64 /* PackBitsTest.cpp */,
+				009CC7830F5DAE2B002185BE /* SrcOverTest.cpp */,
 			);
 			name = Source;
 			sourceTree = "<group>";
@@ -243,6 +249,8 @@
 				00A9BFA30F584E150091AD2D /* StringTest.cpp in Sources */,
 				00A9BFBC0F5851570091AD2D /* GeometryTest.cpp in Sources */,
 				276D93080F5B9FEA0081B3B9 /* PathTest.cpp in Sources */,
+				009CC7840F5DAE2B002185BE /* SrcOverTest.cpp in Sources */,
+				009CC7880F5DAF16002185BE /* ClipCubicTest.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/xcode/core/core.xcodeproj/project.pbxproj b/xcode/core/core.xcodeproj/project.pbxproj
index 74a431a..af3f3c0 100644
--- a/xcode/core/core.xcodeproj/project.pbxproj
+++ b/xcode/core/core.xcodeproj/project.pbxproj
@@ -126,6 +126,7 @@
 		005F25E70EF94F7900582A90 /* SkXfermode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 005F256E0EF94F7900582A90 /* SkXfermode.cpp */; };
 		005F26960EF955D400582A90 /* SkComposeShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 005F26950EF955D400582A90 /* SkComposeShader.cpp */; };
 		007C786A0F3B4D5F0004B142 /* SkQuadClipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007C78690F3B4D5F0004B142 /* SkQuadClipper.cpp */; };
+		009CC7920F5DAF4B002185BE /* SkCubicClipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 009CC7910F5DAF4B002185BE /* SkCubicClipper.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
@@ -248,6 +249,7 @@
 		005F256E0EF94F7900582A90 /* SkXfermode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkXfermode.cpp; path = ../../src/core/SkXfermode.cpp; sourceTree = SOURCE_ROOT; };
 		005F26950EF955D400582A90 /* SkComposeShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkComposeShader.cpp; path = ../../src/core/SkComposeShader.cpp; sourceTree = SOURCE_ROOT; };
 		007C78690F3B4D5F0004B142 /* SkQuadClipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkQuadClipper.cpp; path = ../../src/core/SkQuadClipper.cpp; sourceTree = SOURCE_ROOT; };
+		009CC7910F5DAF4B002185BE /* SkCubicClipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkCubicClipper.cpp; path = ../../src/core/SkCubicClipper.cpp; sourceTree = SOURCE_ROOT; };
 		D2AAC046055464E500DB518D /* libcore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcore.a; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
@@ -275,6 +277,7 @@
 		08FB7795FE84155DC02AAC07 /* src */ = {
 			isa = PBXGroup;
 			children = (
+				009CC7910F5DAF4B002185BE /* SkCubicClipper.cpp */,
 				007C78690F3B4D5F0004B142 /* SkQuadClipper.cpp */,
 				002884D40EFAB8F80083E387 /* SkStream.cpp */,
 				002884C70EFAB8B90083E387 /* SkMMapStream.cpp */,
@@ -584,6 +587,7 @@
 				002884C80EFAB8B90083E387 /* SkMMapStream.cpp in Sources */,
 				002884D50EFAB8F80083E387 /* SkStream.cpp in Sources */,
 				007C786A0F3B4D5F0004B142 /* SkQuadClipper.cpp in Sources */,
+				009CC7920F5DAF4B002185BE /* SkCubicClipper.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};