add ADD xfermode
safely handle (don't draw) if the size of SkMask exceeds 31bits



git-svn-id: http://skia.googlecode.com/svn/trunk@159 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 7c336c2..9514bfa 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -45,6 +45,16 @@
 }
 #endif
 
+static unsigned saturated_add(unsigned a, unsigned b) {
+    SkASSERT(a <= 255);
+    SkASSERT(b <= 255);
+    unsigned sum = a + b;
+    if (sum > 255) {
+        sum = 255;
+    }
+    return sum;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
@@ -500,6 +510,14 @@
     return SkPackARGB32(a, r, g, b);
 }
 
+static SkPMColor add_modeproc(SkPMColor src, SkPMColor dst) {
+    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
+    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
+    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
+    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
+    return SkPackARGB32(a, r, g, b);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 class SkClearXfermode : public SkProcCoeffXfermode {
@@ -701,6 +719,8 @@
     SkXfermode::Coeff   fDC;
 };
 
+#define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
+
 static const ProcCoeff gProcCoeffs[] = {
     { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
     { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
@@ -714,12 +734,11 @@
     { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
     { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
     { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
-    // these two can't be represented as coefficients
-    { darken_modeproc,  SkXfermode::Coeff(-1),      SkXfermode::Coeff(-1) },
-    { lighten_modeproc, SkXfermode::Coeff(-1),      SkXfermode::Coeff(-1) },
-    // these can use coefficients
+    { darken_modeproc,  CANNOT_USE_COEFF,           CANNOT_USE_COEFF },
+    { lighten_modeproc, CANNOT_USE_COEFF,           CANNOT_USE_COEFF },
     { mult_modeproc,    SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
-    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff }
+    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
+    { add_modeproc,     CANNOT_USE_COEFF,           CANNOT_USE_COEFF }
 };
 
 SkXfermode* SkPorterDuff::CreateXfermode(SkPorterDuff::Mode mode) {