grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleRegion.cpp b/samplecode/SampleRegion.cpp
new file mode 100644
index 0000000..8958c82
--- /dev/null
+++ b/samplecode/SampleRegion.cpp
@@ -0,0 +1,329 @@
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkImageDecoder.h"
+
+#ifdef SK_DEBUG
+static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
+                     size_t count, int32_t runs[]) {
+    SkIRect r;
+    r.set(left, top, right, bottom);
+    
+    rgn->debugSetRuns(runs, count);
+    SkASSERT(rgn->getBounds() == r);
+}
+
+static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
+    static int32_t dataA[] = {
+        0x00000001, 0x000001dd,
+        0x00000001, 0x0000000c, 0x0000000d, 0x00000025,
+        0x7fffffff, 0x000001de, 0x00000001, 0x00000025,
+        0x7fffffff, 0x000004b3, 0x00000001, 0x00000026,
+        0x7fffffff, 0x000004b4, 0x0000000c, 0x00000026,
+        0x7fffffff, 0x00000579, 0x00000000, 0x0000013a,
+        0x7fffffff, 0x000005d8, 0x00000000, 0x0000013b,
+        0x7fffffff, 0x7fffffff
+    };
+    make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);
+
+    static int32_t dataB[] = {
+        0x000000b6, 0x000000c4,
+        0x000000a1, 0x000000f0, 0x7fffffff, 0x000000d6,
+        0x7fffffff, 0x000000e4, 0x00000070, 0x00000079,
+        0x000000a1, 0x000000b0, 0x7fffffff, 0x000000e6,
+        0x7fffffff, 0x000000f4, 0x00000070, 0x00000079,
+        0x000000a1, 0x000000b0, 0x7fffffff, 0x000000f6,
+        0x7fffffff, 0x00000104, 0x000000a1, 0x000000b0,
+        0x7fffffff, 0x7fffffff
+    };
+    make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);
+    
+    rc->op(*ra, *rb, SkRegion::kUnion_Op);
+}
+#endif
+
+static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn, const SkPaint& paint)
+{
+    SkRegion::Iterator  iter(rgn);
+    
+    for (; !iter.done(); iter.next())
+    {
+        SkRect    r;
+        r.set(iter.rect());
+        canvas->drawRect(r, paint);
+    }
+}
+
+class RegionView : public SkView {
+public:
+	RegionView() 
+	{
+        fBase.set(100, 100, 150, 150);
+        fRect = fBase;
+        fRect.inset(5, 5);
+        fRect.offset(25, 25);
+    }
+
+    void build_rgn(SkRegion* rgn, SkRegion::Op op)
+    {
+        rgn->setRect(fBase);
+        SkIRect r = fBase;
+        r.offset(75, 20);
+        rgn->op(r, SkRegion::kUnion_Op);
+        rgn->op(fRect, op);
+    }
+
+
+protected:
+    // overrides from SkEventSink
+    virtual bool onQuery(SkEvent* evt)
+    {
+        if (SampleCode::TitleQ(*evt))
+        {
+            SampleCode::TitleR(evt, "Regions");
+            return true;
+        }
+        return this->INHERITED::onQuery(evt);
+    }
+    
+    void drawOrig(SkCanvas* canvas, bool bg)
+    {
+        SkRect      r;
+        SkPaint     paint;
+        
+        paint.setStyle(SkPaint::kStroke_Style);
+        if (bg)
+            paint.setColor(0xFFBBBBBB);
+        
+        r.set(fBase);
+        canvas->drawRect(r, paint);
+        r.set(fRect);
+        canvas->drawRect(r, paint);
+    }
+    
+    void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
+    {
+        SkRegion    rgn;
+
+        this->build_rgn(&rgn, op);
+        
+        {
+            SkRegion tmp, tmp2(rgn);
+            
+            tmp = tmp2;
+            tmp.translate(5, -3);
+            
+            {
+                char    buffer[1000];
+                size_t  size = tmp.flatten(NULL);
+                SkASSERT(size <= sizeof(buffer));
+                size_t  size2 = tmp.flatten(buffer);
+                SkASSERT(size == size2);
+                
+                SkRegion    tmp3;
+                size2 = tmp3.unflatten(buffer);
+                SkASSERT(size == size2);
+                
+                SkASSERT(tmp3 == tmp);
+            }
+
+            rgn.translate(20, 30, &tmp);
+            SkASSERT(rgn.isEmpty() || tmp != rgn);
+            tmp.translate(-20, -30);
+            SkASSERT(tmp == rgn);
+        }
+
+        this->drawOrig(canvas, true);
+
+        SkPaint paint;
+        paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
+        paint_rgn(canvas, rgn, paint);
+
+        paint.setStyle(SkPaint::kStroke_Style);
+        paint.setColor(color);
+        paint_rgn(canvas, rgn, paint);
+    }
+    
+    void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color)
+    {
+        SkRegion    rgn;
+        SkPath      path;
+
+        this->build_rgn(&rgn, op);
+        rgn.getBoundaryPath(&path);
+
+        this->drawOrig(canvas, true);
+
+        SkPaint paint;
+
+        paint.setStyle(SkPaint::kFill_Style);
+        paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
+        canvas->drawPath(path, paint);
+        paint.setColor(color);
+        paint.setStyle(SkPaint::kStroke_Style);
+        canvas->drawPath(path, paint);
+    }
+    
+    void drawBG(SkCanvas* canvas)
+    {
+        canvas->drawColor(0xFFDDDDDD);
+        return;
+
+#if 0
+        SkColorTable    ct;
+        SkPMColor       colors[] = { SK_ColorRED, SK_ColorBLUE };
+        ct.setColors(colors, 2);
+        ct.setFlags(ct.getFlags() | SkColorTable::kColorsAreOpaque_Flag);
+
+        SkBitmap        bm;
+        bm.setConfig(SkBitmap::kIndex8_Config, 20, 20, 21);
+        bm.setColorTable(&ct);
+        bm.allocPixels();
+        sk_memset16((uint16_t*)bm.getAddr8(0, 0), 0x0001, bm.rowBytes() * bm.height() / 2);
+#endif
+#if 0
+        SkBitmap        bm;
+        bm.setConfig(SkBitmap::kRGB_565_Config, 20, 20, 42);
+        bm.allocPixels();
+        sk_memset32((uint32_t*)bm.getAddr16(0, 0), 0x0000FFFF, bm.rowBytes() * bm.height() / 4);
+#endif
+#if 1
+        SkBitmap        bm;
+        bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
+        bm.allocPixels();
+        sk_memset32((uint32_t*)bm.getAddr32(0, 0), 0xFFDDDDDD, bm.rowBytes() * bm.height() / 4);
+#endif
+
+        SkPaint paint;
+
+//        SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kBilinear_FilterType, SkShader::kRepeat_TileMode);
+        SkPoint pts[] = { 0, 0, SkIntToScalar(100), SkIntToScalar(0) };
+        SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
+        SkShader* shader = SkGradientShader::CreateLinear(pts, colors, nil, 2, SkShader::kMirror_TileMode);
+        paint.setShader(shader)->unref();
+
+        canvas->drawPaint(paint);
+    }
+
+    virtual void onDraw(SkCanvas* canvas)
+    {
+        if (true) {
+            SkRect r = { 0, 0, 1 << 30, 1 << 30 };
+            bool open = canvas->clipRect(r);
+            SkDebugf("---- giant clip is %d\n", open);
+        }
+        this->drawBG(canvas);
+        
+#ifdef SK_DEBUG
+        if (true) {
+            SkRegion a, b, c;
+            test_union_bug_1505668(&a, &b, &c);
+            
+            if (false) {    // draw the result of the test
+                SkPaint paint;
+                
+                canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
+                paint.setColor(SK_ColorRED);
+                paint_rgn(canvas, a, paint);
+                paint.setColor(0x800000FF);
+                paint_rgn(canvas, b, paint);
+                paint.setColor(SK_ColorBLACK);
+                paint.setStyle(SkPaint::kStroke_Style);
+             //   paint_rgn(canvas, c, paint);
+                return;
+            }
+        }
+#endif
+
+        static const struct {
+            SkColor         fColor;
+            const char*     fName;
+            SkRegion::Op    fOp;
+        } gOps[] = {
+            { SK_ColorBLACK,    "Difference",   SkRegion::kDifference_Op    },
+            { SK_ColorRED,      "Intersect",    SkRegion::kIntersect_Op     },
+            { 0xFF008800,       "Union",        SkRegion::kUnion_Op         },
+            { SK_ColorBLUE,     "XOR",          SkRegion::kXOR_Op           }
+        };
+
+        SkPaint textPaint;
+        textPaint.setAntiAlias(true);
+        textPaint.setTextSize(SK_Scalar1*24);
+
+        this->drawOrig(canvas, false);
+        canvas->save();
+            canvas->translate(SkIntToScalar(200), 0);
+            this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
+        canvas->restore();
+        
+        canvas->translate(0, SkIntToScalar(200));
+
+        for (int op = 0; op < SK_ARRAY_COUNT(gOps); op++)
+        {
+            canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
+
+            this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
+
+            if (true)
+            {
+                canvas->save();
+                canvas->translate(0, SkIntToScalar(200));
+                this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
+                canvas->restore();
+            }
+            
+            canvas->translate(SkIntToScalar(200), 0);
+        }
+
+        if (false)
+        {
+            SkBitmap    bitmap;
+            
+            bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+            bitmap.allocPixels();
+            bitmap.eraseColor(0);
+
+            SkCanvas    canvas(bitmap);
+            SkPaint     paint;
+            SkRect      r;
+            
+            paint.setAntiAlias(true);
+            paint.setARGB(0xFF, 0xFF, 0, 0xFF);
+            r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
+            canvas.drawOval(r, paint);
+
+            SkImageEncoder* en = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
+            en->encodeFile("testfile.png", bitmap);
+            delete en;
+        }
+    }
+    
+    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) 
+    {
+        return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : nil;
+    }
+    
+    virtual bool onClick(Click* click) 
+    {
+        fRect.offset(click->fICurr.fX - click->fIPrev.fX,
+                     click->fICurr.fY - click->fIPrev.fY);
+        this->inval(nil);
+        return true;
+    }
+    
+private:
+    SkIRect    fBase, fRect;
+    
+    typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new RegionView; }
+static SkViewRegister reg(MyFactory);
+