Home | History | Annotate | Download | only in gm
      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 "gm.h"
      9 #include "SkCanvas.h"
     10 //#include "SkParsePath.h"
     11 #include "SkPath.h"
     12 //#include "SkRandom.h"
     13 
     14 namespace skiagm {
     15 
     16 static const SkColor gPathColor = SK_ColorBLACK;
     17 static const SkColor gClipAColor = SK_ColorBLUE;
     18 static const SkColor gClipBColor = SK_ColorRED;
     19 
     20 class ComplexClipGM : public GM {
     21 public:
     22     ComplexClipGM(bool aaclip, bool saveLayer, bool invertDraw)
     23     : fDoAAClip(aaclip)
     24     , fDoSaveLayer(saveLayer)
     25     , fInvertDraw(invertDraw) {
     26         this->setBGColor(0xFFDDDDDD);
     27     }
     28 
     29 protected:
     30 
     31 
     32     SkString onShortName() {
     33         SkString str;
     34         str.printf("complexclip_%s%s%s",
     35                    fDoAAClip ? "aa" : "bw",
     36                    fDoSaveLayer ? "_layer" : "",
     37                    fInvertDraw ? "_invert" : "");
     38         return str;
     39     }
     40 
     41     SkISize onISize() { return SkISize::Make(970, 780); }
     42 
     43     virtual void onDraw(SkCanvas* canvas) {
     44         SkPath path;
     45         path.moveTo(SkIntToScalar(0),   SkIntToScalar(50));
     46         path.quadTo(SkIntToScalar(0),   SkIntToScalar(0),   SkIntToScalar(50),  SkIntToScalar(0));
     47         path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
     48         path.quadTo(SkIntToScalar(200), SkIntToScalar(0),   SkIntToScalar(200), SkIntToScalar(25));
     49         path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
     50         path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
     51         path.lineTo(SkIntToScalar(0),   SkIntToScalar(200));
     52         path.close();
     53         path.moveTo(SkIntToScalar(50),  SkIntToScalar(50));
     54         path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
     55         path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
     56         path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
     57         path.lineTo(SkIntToScalar(50),  SkIntToScalar(150));
     58         path.close();
     59         if (fInvertDraw) {
     60             path.setFillType(SkPath::kInverseEvenOdd_FillType);
     61         } else {
     62             path.setFillType(SkPath::kEvenOdd_FillType);
     63         }
     64         SkPaint pathPaint;
     65         pathPaint.setAntiAlias(true);
     66         pathPaint.setColor(gPathColor);
     67 
     68         SkPath clipA;
     69         clipA.moveTo(SkIntToScalar(10),  SkIntToScalar(20));
     70         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
     71         clipA.lineTo(SkIntToScalar(70),  SkIntToScalar(105));
     72         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
     73         clipA.lineTo(SkIntToScalar(-5),  SkIntToScalar(180));
     74         clipA.close();
     75 
     76         SkPath clipB;
     77         clipB.moveTo(SkIntToScalar(40),  SkIntToScalar(10));
     78         clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
     79         clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
     80         clipB.lineTo(SkIntToScalar(40),  SkIntToScalar(185));
     81         clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
     82         clipB.close();
     83 
     84         SkPaint paint;
     85         paint.setAntiAlias(true);
     86         sk_tool_utils::set_portable_typeface(&paint);
     87         paint.setTextSize(SkIntToScalar(20));
     88 
     89         static const struct {
     90             SkRegion::Op fOp;
     91             const char*  fName;
     92         } gOps[] = { //extra spaces in names for measureText
     93             {SkRegion::kIntersect_Op,         "Isect "},
     94             {SkRegion::kDifference_Op,        "Diff " },
     95             {SkRegion::kUnion_Op,             "Union "},
     96             {SkRegion::kXOR_Op,               "Xor "  },
     97             {SkRegion::kReverseDifference_Op, "RDiff "}
     98         };
     99 
    100         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
    101         canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
    102 
    103         if (fDoSaveLayer) {
    104             // We want the layer to appear symmetric relative to actual
    105             // device boundaries so we need to "undo" the effect of the
    106             // scale and translate
    107             SkRect bounds = SkRect::MakeLTRB(
    108               4.0f/3.0f * -20,
    109               4.0f/3.0f * -20,
    110               4.0f/3.0f * (this->getISize().fWidth - 20),
    111               4.0f/3.0f * (this->getISize().fHeight - 20));
    112 
    113             bounds.inset(SkIntToScalar(100), SkIntToScalar(100));
    114             SkPaint boundPaint;
    115             boundPaint.setColor(SK_ColorRED);
    116             boundPaint.setStyle(SkPaint::kStroke_Style);
    117             canvas->drawRect(bounds, boundPaint);
    118             canvas->saveLayer(&bounds, NULL);
    119         }
    120 
    121         for (int invBits = 0; invBits < 4; ++invBits) {
    122             canvas->save();
    123             for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
    124                 this->drawHairlines(canvas, path, clipA, clipB);
    125 
    126                 bool doInvA = SkToBool(invBits & 1);
    127                 bool doInvB = SkToBool(invBits & 2);
    128                 canvas->save();
    129                     // set clip
    130                     clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
    131                                       SkPath::kEvenOdd_FillType);
    132                     clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
    133                                       SkPath::kEvenOdd_FillType);
    134                     canvas->clipPath(clipA, SkRegion::kIntersect_Op, fDoAAClip);
    135                     canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
    136 
    137                     // In the inverse case we need to prevent the draw from covering the whole
    138                     // canvas.
    139                     if (fInvertDraw) {
    140                         SkRect rectClip = clipA.getBounds();
    141                         rectClip.join(path.getBounds());
    142                         rectClip.join(path.getBounds());
    143                         rectClip.outset(5, 5);
    144                         canvas->clipRect(rectClip);
    145                     }
    146 
    147                     // draw path clipped
    148                     canvas->drawPath(path, pathPaint);
    149                 canvas->restore();
    150 
    151 
    152                 SkScalar txtX = SkIntToScalar(45);
    153                 paint.setColor(gClipAColor);
    154                 const char* aTxt = doInvA ? "InvA " : "A ";
    155                 canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
    156                 txtX += paint.measureText(aTxt, strlen(aTxt));
    157                 paint.setColor(SK_ColorBLACK);
    158                 canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
    159                                     txtX, SkIntToScalar(220), paint);
    160                 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
    161                 paint.setColor(gClipBColor);
    162                 const char* bTxt = doInvB ? "InvB " : "B ";
    163                 canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint);
    164 
    165                 canvas->translate(SkIntToScalar(250),0);
    166             }
    167             canvas->restore();
    168             canvas->translate(0, SkIntToScalar(250));
    169         }
    170 
    171         if (fDoSaveLayer) {
    172             canvas->restore();
    173         }
    174     }
    175 private:
    176     void drawHairlines(SkCanvas* canvas, const SkPath& path,
    177                        const SkPath& clipA, const SkPath& clipB) {
    178         SkPaint paint;
    179         paint.setAntiAlias(true);
    180         paint.setStyle(SkPaint::kStroke_Style);
    181         const SkAlpha fade = 0x33;
    182 
    183         // draw path in hairline
    184         paint.setColor(gPathColor); paint.setAlpha(fade);
    185         canvas->drawPath(path, paint);
    186 
    187         // draw clips in hair line
    188         paint.setColor(gClipAColor); paint.setAlpha(fade);
    189         canvas->drawPath(clipA, paint);
    190         paint.setColor(gClipBColor); paint.setAlpha(fade);
    191         canvas->drawPath(clipB, paint);
    192     }
    193 
    194     bool fDoAAClip;
    195     bool fDoSaveLayer;
    196     bool fInvertDraw;
    197 
    198     typedef GM INHERITED;
    199 };
    200 
    201 //////////////////////////////////////////////////////////////////////////////
    202 
    203 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (false, false, false)); )
    204 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (false, false, true));  )
    205 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (false, true,  false)); )
    206 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (false, true,  true));  )
    207 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (true,  false, false)); )
    208 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (true,  false, true));  )
    209 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (true,  true,  false)); )
    210 DEF_GM( return SkNEW_ARGS(ComplexClipGM, (true,  true,  true));  )
    211 
    212 }
    213