add optional bitflags to control which aspect of each layer's paint is applied



git-svn-id: http://skia.googlecode.com/svn/trunk@1083 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/effects/SkLayerDrawLooper.h b/include/effects/SkLayerDrawLooper.h
index d35d70d..682a9dc 100644
--- a/include/effects/SkLayerDrawLooper.h
+++ b/include/effects/SkLayerDrawLooper.h
@@ -9,17 +9,38 @@
 public:
             SkLayerDrawLooper();
     virtual ~SkLayerDrawLooper();
+
+    enum Bits {
+        kAlpha_Bit      = 1 << 0,   //!< use this layer's alpha
+        kColor_Bit      = 1 << 1,   //!< use this layer's color
+        kStyle_Bit      = 1 << 2,   //!< use this layer's Style/stroke settings
+        kTextSkewX_Bit  = 1 << 3,   //!< use this layer's textskewx
+        kPathEffect_Bit = 1 << 4,   //!< use this layer's patheffect
+        kMaskFilter_Bit = 1 << 5,   //!< use this layer's maskfilter
+        kShader_Bit     = 1 << 6,   //!< use this layer's shader
+        kColorFilter_Bit = 1 << 7,  //!< use this layer's colorfilter
+        kXfermode_Bit   = 1 << 8,   //!< use this layer's xfermode
+        
+        kEntirePaint_Bits = -1,      //!< use this layer's paint entirely
+    };
+    typedef int32_t BitFlags;
     
-    /** Call for each layer you want to add (from top to bottom).
-        This returns a paint you can modify, but that ptr is only valid until
-        the next call made to this object.
+    /**
+     *  Call for each layer you want to add (from top to bottom).
+     *  This returns a paint you can modify, but that ptr is only valid until
+     *  the next call made to this object.
+     *
+     *  The optional bits parameter specifies which aspects of this paint
+     *  should replace the paint that is passed to the draw call. If 0 is
+     *  specified, then this layer's paint will be ignored.
      */
-    SkPaint* addLayer(SkScalar dx, SkScalar dy);
+    SkPaint* addLayer(SkScalar dx, SkScalar dy, BitFlags = kEntirePaint_Bits);
     
-    /** Helper for addLayer() which passes (0, 0) for the offset parameters
+    /**
+     *  Helper for addLayer() which passes (0, 0) for the offset parameters
      */
-    SkPaint* addLayer() {
-        return this->addLayer(0, 0);
+    SkPaint* addLayer(BitFlags bits = kEntirePaint_Bits) {
+        return this->addLayer(0, 0, bits);
     }
     
     // overrides from SkDrawLooper
@@ -43,6 +64,7 @@
         Rec*    fNext;
         SkPaint fPaint;
         SkPoint fOffset;
+        uint32_t fBits;
         
         static Rec* Reverse(Rec*);
     };
@@ -51,7 +73,9 @@
 
     // state-machine during the init/next cycle
     Rec* fCurrRec;
-    
+
+    static void ApplyBits(SkPaint* dst, const SkPaint& src, BitFlags bits);
+
     class MyRegistrar : public SkFlattenable::Registrar {
     public:
         MyRegistrar();
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index 32b56d6..ee0fc98 100644
--- a/src/effects/SkLayerDrawLooper.cpp
+++ b/src/effects/SkLayerDrawLooper.cpp
@@ -16,12 +16,13 @@
     }
 }
     
-SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
+SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy, BitFlags bits) {
     fCount += 1;
 
     Rec* rec = SkNEW(Rec);
     rec->fNext = fRecs;
     rec->fOffset.set(dx, dy);
+    rec->fBits = bits;
     fRecs = rec;
 
     return &rec->fPaint;
@@ -32,13 +33,73 @@
     canvas->save(SkCanvas::kMatrix_SaveFlag);
 }
 
+void SkLayerDrawLooper::ApplyBits(SkPaint* dst, const SkPaint& src,
+                                  BitFlags bits) {
+    if (kEntirePaint_Bits == bits) {
+        *dst = src;
+        return;
+    }
+
+    SkColor c = dst->getColor();
+    if (bits & kAlpha_Bit) {
+        c &= 0x00FFFFFF;
+        c |= src.getColor() & 0xFF000000;
+    }
+    if (bits & kColor_Bit) {
+        c &= 0xFF000000;
+        c |= src.getColor() & 0x00FFFFFF;
+    }
+    dst->setColor(c);
+
+    if (bits & kStyle_Bit) {
+        dst->setStyle(src.getStyle());
+        dst->setStrokeWidth(src.getStrokeWidth());
+        dst->setStrokeMiter(src.getStrokeMiter());
+        dst->setStrokeCap(src.getStrokeCap());
+        dst->setStrokeJoin(src.getStrokeJoin());
+    }
+
+    if (bits & kTextSkewX_Bit) {
+        dst->setTextSkewX(src.getTextSkewX());
+    }
+
+    if (bits & kPathEffect_Bit) {
+        dst->setPathEffect(src.getPathEffect());
+    }
+    if (bits & kMaskFilter_Bit) {
+        dst->setMaskFilter(src.getMaskFilter());
+    }
+    if (bits & kShader_Bit) {
+        dst->setShader(src.getShader());
+    }
+    if (bits & kColorFilter_Bit) {
+        dst->setColorFilter(src.getColorFilter());
+    }
+    if (bits & kXfermode_Bit) {
+        dst->setXfermode(src.getXfermode());
+    }
+
+    // we never copy these
+#if 0
+    dst->setFlags(src.getFlags());
+    dst->setTypeface(src.getTypeface());
+    dst->setTextSize(src.getTextSize());
+    dst->setTextScaleX(src.getTextScaleX());
+    dst->setTextSkewX(src.getTextSkewX());
+    dst->setRasterizer(src.getRasterizer());
+    dst->setLooper(src.getLooper());
+    dst->setTextEncoding(src.getTextEncoding());
+    dst->setHinting(src.getHinting());
+#endif
+}
+
 bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
     canvas->restore();
     if (NULL == fCurrRec) {
         return false;
     }
 
-    *paint = fCurrRec->fPaint;
+    ApplyBits(paint, fCurrRec->fPaint, fCurrRec->fBits);
     canvas->save(SkCanvas::kMatrix_SaveFlag);
     canvas->translate(fCurrRec->fOffset.fX, fCurrRec->fOffset.fY);
     fCurrRec = fCurrRec->fNext;