1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "gm.h"
10#include "SkCanvas.h"
11#include "SkAAClip.h"
12
13namespace skiagm {
14
15static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip,
16                      const SkPaint& paint) {
17    SkMask mask;
18    SkBitmap bm;
19
20    clip.copyToMask(&mask);
21
22    SkAutoMaskFreeImage amfi(mask.fImage);
23
24    bm.installMaskPixels(mask);
25
26    // need to copy for deferred drawing test to work
27    SkBitmap bm2;
28
29    bm.deepCopyTo(&bm2);
30
31    canvas->drawBitmap(bm2,
32                       SK_Scalar1 * mask.fBounds.fLeft,
33                       SK_Scalar1 * mask.fBounds.fTop,
34                       &paint);
35}
36
37//////////////////////////////////////////////////////////////////////////////
38/*
39 * This GM tests anti aliased single operation booleans with SkAAClips,
40 * SkRect and SkPaths.
41 */
42class SimpleClipGM : public GM {
43public:
44    enum SkGeomTypes {
45        kRect_GeomType,
46        kPath_GeomType,
47        kAAClip_GeomType
48    };
49
50    SimpleClipGM(SkGeomTypes geomType)
51    : fGeomType(geomType) {
52
53        // offset the rects a bit so we get anti-aliasing in the rect case
54        fBase.set(100.65f,
55                  100.65f,
56                  150.65f,
57                  150.65f);
58        fRect = fBase;
59        fRect.inset(5, 5);
60        fRect.offset(25, 25);
61
62        fBasePath.addRoundRect(fBase, SkIntToScalar(5), SkIntToScalar(5));
63        fRectPath.addRoundRect(fRect, SkIntToScalar(5), SkIntToScalar(5));
64        INHERITED::setBGColor(0xFFDDDDDD);
65    }
66
67protected:
68    void buildRgn(SkAAClip* clip, SkRegion::Op op) {
69        clip->setPath(fBasePath, NULL, true);
70
71        SkAAClip clip2;
72        clip2.setPath(fRectPath, NULL, true);
73        clip->op(clip2, op);
74    }
75
76    void drawOrig(SkCanvas* canvas) {
77        SkPaint     paint;
78
79        paint.setStyle(SkPaint::kStroke_Style);
80        paint.setColor(SK_ColorBLACK);
81
82        canvas->drawRect(fBase, paint);
83        canvas->drawRect(fRect, paint);
84    }
85
86    void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
87
88        SkAAClip clip;
89
90        this->buildRgn(&clip, op);
91        this->drawOrig(canvas);
92
93        SkPaint paint;
94        paint.setColor(color);
95        paint_rgn(canvas, clip, paint);
96    }
97
98    void drawPathsOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
99
100        this->drawOrig(canvas);
101
102        canvas->save();
103
104        // create the clip mask with the supplied boolean op
105        if (kPath_GeomType == fGeomType) {
106            // path-based case
107            canvas->clipPath(fBasePath, SkRegion::kReplace_Op, true);
108            canvas->clipPath(fRectPath, op, true);
109        } else {
110            // rect-based case
111            canvas->clipRect(fBase, SkRegion::kReplace_Op, true);
112            canvas->clipRect(fRect, op, true);
113        }
114
115        // draw a rect that will entirely cover the clip mask area
116        SkPaint paint;
117        paint.setColor(color);
118
119        SkRect r = SkRect::MakeLTRB(SkIntToScalar(90),  SkIntToScalar(90),
120                                    SkIntToScalar(180), SkIntToScalar(180));
121
122        canvas->drawRect(r, paint);
123
124        canvas->restore();
125    }
126
127    virtual SkString onShortName() {
128        SkString str;
129        str.printf("simpleaaclip_%s",
130                    kRect_GeomType == fGeomType ? "rect" :
131                    (kPath_GeomType == fGeomType ? "path" :
132                    "aaclip"));
133        return str;
134    }
135
136    virtual SkISize onISize() {
137        return SkISize::Make(640, 480);
138    }
139
140    virtual void onDraw(SkCanvas* canvas) {
141
142        static const struct {
143            SkColor         fColor;
144            const char*     fName;
145            SkRegion::Op    fOp;
146        } gOps[] = {
147            { SK_ColorBLACK,    "Difference", SkRegion::kDifference_Op    },
148            { SK_ColorRED,      "Intersect",  SkRegion::kIntersect_Op     },
149            { 0xFF008800,       "Union",      SkRegion::kUnion_Op         },
150            { SK_ColorGREEN,    "Rev Diff",   SkRegion::kReverseDifference_Op },
151            { SK_ColorYELLOW,   "Replace",    SkRegion::kReplace_Op       },
152            { SK_ColorBLUE,     "XOR",        SkRegion::kXOR_Op           },
153        };
154
155        SkPaint textPaint;
156        textPaint.setAntiAlias(true);
157        sk_tool_utils::set_portable_typeface(&textPaint);
158        textPaint.setTextSize(SK_Scalar1*24);
159        int xOff = 0;
160
161        for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
162            canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
163                             SkIntToScalar(75), SkIntToScalar(50),
164                             textPaint);
165
166            if (kAAClip_GeomType == fGeomType) {
167                this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
168            } else {
169                this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor);
170            }
171
172            if (xOff >= 400) {
173                canvas->translate(SkIntToScalar(-400), SkIntToScalar(250));
174                xOff = 0;
175            } else {
176                canvas->translate(SkIntToScalar(200), 0);
177                xOff += 200;
178            }
179        }
180    }
181private:
182
183    SkGeomTypes fGeomType;
184
185    SkRect fBase;
186    SkRect fRect;
187
188    SkPath fBasePath;       // fBase as a round rect
189    SkPath fRectPath;       // fRect as a round rect
190
191    typedef GM INHERITED;
192};
193
194//////////////////////////////////////////////////////////////////////////////
195
196// rects
197DEF_GM( return new SimpleClipGM(SimpleClipGM::kRect_GeomType); )
198DEF_GM( return new SimpleClipGM(SimpleClipGM::kPath_GeomType); )
199DEF_GM( return new SimpleClipGM(SimpleClipGM::kAAClip_GeomType); )
200
201}
202