Home | History | Annotate | Download | only in samplecode
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SampleCode.h"
      9 #include "SkView.h"
     10 #include "SkCanvas.h"
     11 #include "SkGradientShader.h"
     12 #include "SkPath.h"
     13 #include "SkRegion.h"
     14 #include "SkShader.h"
     15 #include "SkUtils.h"
     16 #include "SkImageDecoder.h"
     17 
     18 #ifdef SK_BUILD_FOR_WIN
     19 // windows doesn't have roundf
     20 inline float roundf(float x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
     21 #endif
     22 
     23 #ifdef SK_DEBUG
     24 static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
     25                      size_t count, int32_t runs[]) {
     26     SkIRect r;
     27     r.set(left, top, right, bottom);
     28 
     29     rgn->debugSetRuns(runs, count);
     30     SkASSERT(rgn->getBounds() == r);
     31 }
     32 
     33 static void test_union_bug_1505668(SkRegion* ra, SkRegion* rb, SkRegion* rc) {
     34     static int32_t dataA[] = {
     35         0x00000001, 0x000001dd,
     36         0x00000001, 0x0000000c, 0x0000000d, 0x00000025,
     37         0x7fffffff, 0x000001de, 0x00000001, 0x00000025,
     38         0x7fffffff, 0x000004b3, 0x00000001, 0x00000026,
     39         0x7fffffff, 0x000004b4, 0x0000000c, 0x00000026,
     40         0x7fffffff, 0x00000579, 0x00000000, 0x0000013a,
     41         0x7fffffff, 0x000005d8, 0x00000000, 0x0000013b,
     42         0x7fffffff, 0x7fffffff
     43     };
     44     make_rgn(ra, 0, 1, 315, 1496, SK_ARRAY_COUNT(dataA), dataA);
     45 
     46     static int32_t dataB[] = {
     47         0x000000b6, 0x000000c4,
     48         0x000000a1, 0x000000f0, 0x7fffffff, 0x000000d6,
     49         0x7fffffff, 0x000000e4, 0x00000070, 0x00000079,
     50         0x000000a1, 0x000000b0, 0x7fffffff, 0x000000e6,
     51         0x7fffffff, 0x000000f4, 0x00000070, 0x00000079,
     52         0x000000a1, 0x000000b0, 0x7fffffff, 0x000000f6,
     53         0x7fffffff, 0x00000104, 0x000000a1, 0x000000b0,
     54         0x7fffffff, 0x7fffffff
     55     };
     56     make_rgn(rb, 112, 182, 240, 260, SK_ARRAY_COUNT(dataB), dataB);
     57 
     58     rc->op(*ra, *rb, SkRegion::kUnion_Op);
     59 }
     60 #endif
     61 
     62 static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
     63     dst->fLeft = (int)::roundf(src.fLeft * scale);
     64     dst->fTop = (int)::roundf(src.fTop * scale);
     65     dst->fRight = (int)::roundf(src.fRight * scale);
     66     dst->fBottom = (int)::roundf(src.fBottom * scale);
     67 }
     68 
     69 static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
     70     SkRegion tmp;
     71     SkRegion::Iterator iter(src);
     72 
     73     for (; !iter.done(); iter.next()) {
     74         SkIRect r;
     75         scale_rect(&r, iter.rect(), scale);
     76         tmp.op(r, SkRegion::kUnion_Op);
     77     }
     78     dst->swap(tmp);
     79 }
     80 
     81 static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn,
     82                       const SkPaint& paint) {
     83     SkRegion scaled;
     84     scale_rgn(&scaled, rgn, 0.5f);
     85 
     86     SkRegion::Iterator  iter(rgn);
     87 
     88     for (; !iter.done(); iter.next())
     89     {
     90         SkRect    r;
     91         r.set(iter.rect());
     92         canvas->drawRect(r, paint);
     93     }
     94 }
     95 
     96 class RegionView : public SampleView {
     97 public:
     98 	RegionView() {
     99         fBase.set(100, 100, 150, 150);
    100         fRect = fBase;
    101         fRect.inset(5, 5);
    102         fRect.offset(25, 25);
    103         this->setBGColor(0xFFDDDDDD);
    104     }
    105 
    106     void build_rgn(SkRegion* rgn, SkRegion::Op op) {
    107         rgn->setRect(fBase);
    108         SkIRect r = fBase;
    109         r.offset(75, 20);
    110         rgn->op(r, SkRegion::kUnion_Op);
    111         rgn->op(fRect, op);
    112     }
    113 
    114 
    115 protected:
    116     // overrides from SkEventSink
    117     virtual bool onQuery(SkEvent* evt) {
    118         if (SampleCode::TitleQ(*evt)) {
    119             SampleCode::TitleR(evt, "Regions");
    120             return true;
    121         }
    122         return this->INHERITED::onQuery(evt);
    123     }
    124 
    125     void drawOrig(SkCanvas* canvas, bool bg) {
    126         SkRect      r;
    127         SkPaint     paint;
    128 
    129         paint.setStyle(SkPaint::kStroke_Style);
    130         if (bg)
    131             paint.setColor(0xFFBBBBBB);
    132 
    133         r.set(fBase);
    134         canvas->drawRect(r, paint);
    135         r.set(fRect);
    136         canvas->drawRect(r, paint);
    137     }
    138 
    139     void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
    140         SkRegion    rgn;
    141 
    142         this->build_rgn(&rgn, op);
    143 
    144         {
    145             SkRegion tmp, tmp2(rgn);
    146 
    147             tmp = tmp2;
    148             tmp.translate(5, -3);
    149 
    150             {
    151                 char    buffer[1000];
    152                 size_t  size = tmp.flatten(NULL);
    153                 SkASSERT(size <= sizeof(buffer));
    154                 size_t  size2 = tmp.flatten(buffer);
    155                 SkASSERT(size == size2);
    156 
    157                 SkRegion    tmp3;
    158                 size2 = tmp3.unflatten(buffer);
    159                 SkASSERT(size == size2);
    160 
    161                 SkASSERT(tmp3 == tmp);
    162             }
    163 
    164             rgn.translate(20, 30, &tmp);
    165             SkASSERT(rgn.isEmpty() || tmp != rgn);
    166             tmp.translate(-20, -30);
    167             SkASSERT(tmp == rgn);
    168         }
    169 
    170         this->drawOrig(canvas, true);
    171 
    172         SkPaint paint;
    173         paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
    174         paint_rgn(canvas, rgn, paint);
    175 
    176         paint.setStyle(SkPaint::kStroke_Style);
    177         paint.setColor(color);
    178         paint_rgn(canvas, rgn, paint);
    179     }
    180 
    181     void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
    182         SkRegion    rgn;
    183         SkPath      path;
    184 
    185         this->build_rgn(&rgn, op);
    186         rgn.getBoundaryPath(&path);
    187 
    188         this->drawOrig(canvas, true);
    189 
    190         SkPaint paint;
    191 
    192         paint.setStyle(SkPaint::kFill_Style);
    193         paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
    194         canvas->drawPath(path, paint);
    195         paint.setColor(color);
    196         paint.setStyle(SkPaint::kStroke_Style);
    197         canvas->drawPath(path, paint);
    198     }
    199 
    200     virtual void onDrawContent(SkCanvas* canvas) {
    201 #ifdef SK_DEBUG
    202         if (true) {
    203             SkRegion a, b, c;
    204             test_union_bug_1505668(&a, &b, &c);
    205 
    206             if (false) {    // draw the result of the test
    207                 SkPaint paint;
    208 
    209                 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
    210                 paint.setColor(SK_ColorRED);
    211                 paint_rgn(canvas, a, paint);
    212                 paint.setColor(0x800000FF);
    213                 paint_rgn(canvas, b, paint);
    214                 paint.setColor(SK_ColorBLACK);
    215                 paint.setStyle(SkPaint::kStroke_Style);
    216              //   paint_rgn(canvas, c, paint);
    217                 return;
    218             }
    219         }
    220 #endif
    221 
    222         static const struct {
    223             SkColor         fColor;
    224             const char*     fName;
    225             SkRegion::Op    fOp;
    226         } gOps[] = {
    227             { SK_ColorBLACK,    "Difference",   SkRegion::kDifference_Op    },
    228             { SK_ColorRED,      "Intersect",    SkRegion::kIntersect_Op     },
    229             { 0xFF008800,       "Union",        SkRegion::kUnion_Op         },
    230             { SK_ColorBLUE,     "XOR",          SkRegion::kXOR_Op           }
    231         };
    232 
    233         SkPaint textPaint;
    234         textPaint.setAntiAlias(true);
    235         textPaint.setTextSize(SK_Scalar1*24);
    236 
    237         this->drawOrig(canvas, false);
    238         canvas->save();
    239             canvas->translate(SkIntToScalar(200), 0);
    240             this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
    241         canvas->restore();
    242 
    243         canvas->translate(0, SkIntToScalar(200));
    244 
    245         for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
    246             canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
    247 
    248             this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
    249 
    250             canvas->save();
    251             canvas->translate(0, SkIntToScalar(200));
    252             this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
    253             canvas->restore();
    254 
    255             canvas->translate(SkIntToScalar(200), 0);
    256         }
    257     }
    258 
    259     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
    260         return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : NULL;
    261     }
    262 
    263     virtual bool onClick(Click* click) {
    264         fRect.offset(click->fICurr.fX - click->fIPrev.fX,
    265                      click->fICurr.fY - click->fIPrev.fY);
    266         this->inval(NULL);
    267         return true;
    268     }
    269 
    270 private:
    271     SkIRect    fBase, fRect;
    272 
    273     typedef SampleView INHERITED;
    274 };
    275 
    276 //////////////////////////////////////////////////////////////////////////////
    277 
    278 static SkView* MyFactory() { return new RegionView; }
    279 static SkViewRegister reg(MyFactory);
    280 
    281