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     bool fDoAAClip;
     22     bool fDoSaveLayer;
     23 public:
     24     ComplexClipGM(bool aaclip, bool saveLayer)
     25     : fDoAAClip(aaclip)
     26     , fDoSaveLayer(saveLayer) {
     27         this->setBGColor(0xFFDDDDDD);
     28 //        this->setBGColor(SkColorSetRGB(0xB0,0xDD,0xB0));
     29     }
     30 
     31 protected:
     32 
     33     SkString onShortName() {
     34         SkString str;
     35         str.printf("complexclip_%s%s",
     36                    fDoAAClip ? "aa" : "bw",
     37                    fDoSaveLayer ? "_layer" : "");
     38         return str;
     39     }
     40 
     41     SkISize onISize() { return make_isize(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         path.setFillType(SkPath::kEvenOdd_FillType);
     60         SkPaint pathPaint;
     61         pathPaint.setAntiAlias(true);
     62         pathPaint.setColor(gPathColor);
     63 
     64         SkPath clipA;
     65         clipA.moveTo(SkIntToScalar(10),  SkIntToScalar(20));
     66         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
     67         clipA.lineTo(SkIntToScalar(70),  SkIntToScalar(105));
     68         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
     69         clipA.lineTo(SkIntToScalar(-5),  SkIntToScalar(180));
     70         clipA.close();
     71 
     72         SkPath clipB;
     73         clipB.moveTo(SkIntToScalar(40),  SkIntToScalar(10));
     74         clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
     75         clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
     76         clipB.lineTo(SkIntToScalar(40),  SkIntToScalar(185));
     77         clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
     78         clipB.close();
     79 
     80         SkPaint paint;
     81         paint.setAntiAlias(true);
     82         paint.setTextSize(SkIntToScalar(20));
     83 
     84         static const struct {
     85             SkRegion::Op fOp;
     86             const char*  fName;
     87         } gOps[] = { //extra spaces in names for measureText
     88             {SkRegion::kIntersect_Op,         "Isect "},
     89             {SkRegion::kDifference_Op,        "Diff " },
     90             {SkRegion::kUnion_Op,             "Union "},
     91             {SkRegion::kXOR_Op,               "Xor "  },
     92             {SkRegion::kReverseDifference_Op, "RDiff "}
     93         };
     94 
     95         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
     96         canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
     97 
     98         if (fDoSaveLayer) {
     99             // We want the layer to appear symmetric relative to actual
    100             // device boundaries so we need to "undo" the effect of the
    101             // scale and translate
    102             SkRect bounds = SkRect::MakeLTRB(
    103               4.0f/3.0f * -20,
    104               4.0f/3.0f * -20,
    105               4.0f/3.0f * (this->getISize().fWidth - 20),
    106               4.0f/3.0f * (this->getISize().fHeight - 20));
    107 
    108             bounds.inset(SkIntToScalar(100), SkIntToScalar(100));
    109             SkPaint boundPaint;
    110             boundPaint.setColor(SK_ColorRED);
    111             boundPaint.setStyle(SkPaint::kStroke_Style);
    112             canvas->drawRect(bounds, boundPaint);
    113             canvas->saveLayer(&bounds, NULL);
    114         }
    115 
    116         for (int invBits = 0; invBits < 4; ++invBits) {
    117             canvas->save();
    118             for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
    119                 this->drawHairlines(canvas, path, clipA, clipB);
    120 
    121                 bool doInvA = SkToBool(invBits & 1);
    122                 bool doInvB = SkToBool(invBits & 2);
    123                 canvas->save();
    124                     // set clip
    125                     clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
    126                                       SkPath::kEvenOdd_FillType);
    127                     clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
    128                                       SkPath::kEvenOdd_FillType);
    129                     canvas->clipPath(clipA, SkRegion::kIntersect_Op, fDoAAClip);
    130                     canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
    131 
    132                     // draw path clipped
    133                     canvas->drawPath(path, pathPaint);
    134                 canvas->restore();
    135 
    136 
    137                 SkScalar txtX = SkIntToScalar(45);
    138                 paint.setColor(gClipAColor);
    139                 const char* aTxt = doInvA ? "InvA " : "A ";
    140                 canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
    141                 txtX += paint.measureText(aTxt, strlen(aTxt));
    142                 paint.setColor(SK_ColorBLACK);
    143                 canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
    144                                     txtX, SkIntToScalar(220), paint);
    145                 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
    146                 paint.setColor(gClipBColor);
    147                 const char* bTxt = doInvB ? "InvB " : "B ";
    148                 canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint);
    149 
    150                 canvas->translate(SkIntToScalar(250),0);
    151             }
    152             canvas->restore();
    153             canvas->translate(0, SkIntToScalar(250));
    154         }
    155 
    156         if (fDoSaveLayer) {
    157             canvas->restore();
    158         }
    159     }
    160 private:
    161     void drawHairlines(SkCanvas* canvas, const SkPath& path,
    162                        const SkPath& clipA, const SkPath& clipB) {
    163         SkPaint paint;
    164         paint.setAntiAlias(true);
    165         paint.setStyle(SkPaint::kStroke_Style);
    166         const SkAlpha fade = 0x33;
    167 
    168         // draw path in hairline
    169         paint.setColor(gPathColor); paint.setAlpha(fade);
    170         canvas->drawPath(path, paint);
    171 
    172         // draw clips in hair line
    173         paint.setColor(gClipAColor); paint.setAlpha(fade);
    174         canvas->drawPath(clipA, paint);
    175         paint.setColor(gClipBColor); paint.setAlpha(fade);
    176         canvas->drawPath(clipB, paint);
    177     }
    178 
    179     typedef GM INHERITED;
    180 };
    181 
    182 //////////////////////////////////////////////////////////////////////////////
    183 
    184 // aliased and anti-aliased w/o a layer
    185 static GM* gFact0(void*) { return new ComplexClipGM(false, false); }
    186 static GM* gFact1(void*) { return new ComplexClipGM(true, false); }
    187 
    188 // aliased and anti-aliased w/ a layer
    189 static GM* gFact2(void*) { return new ComplexClipGM(false, true); }
    190 static GM* gFact3(void*) { return new ComplexClipGM(true, true); }
    191 
    192 static GMRegistry gReg0(gFact0);
    193 static GMRegistry gReg1(gFact1);
    194 static GMRegistry gReg2(gFact2);
    195 static GMRegistry gReg3(gFact3);
    196 
    197 }
    198