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 
13 namespace skiagm {
14 
paint_rgn(SkCanvas * canvas,const SkAAClip & clip,const SkPaint & paint)15 static 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  */
42 class SimpleClipGM : public GM {
43 public:
44     enum SkGeomTypes {
45         kRect_GeomType,
46         kPath_GeomType,
47         kAAClip_GeomType
48     };
49 
SimpleClipGM(SkGeomTypes geomType)50     SimpleClipGM(SkGeomTypes geomType)
51     : fGeomType(geomType) {
52     }
53 
54 protected:
onOnceBeforeDraw()55     void onOnceBeforeDraw() override {
56         // offset the rects a bit so we get anti-aliasing in the rect case
57         fBase.set(100.65f,
58                   100.65f,
59                   150.65f,
60                   150.65f);
61         fRect = fBase;
62         fRect.inset(5, 5);
63         fRect.offset(25, 25);
64 
65         fBasePath.addRoundRect(fBase, SkIntToScalar(5), SkIntToScalar(5));
66         fRectPath.addRoundRect(fRect, SkIntToScalar(5), SkIntToScalar(5));
67         INHERITED::setBGColor(0xFFDDDDDD);
68     }
69 
buildRgn(SkAAClip * clip,SkRegion::Op op)70     void buildRgn(SkAAClip* clip, SkRegion::Op op) {
71         clip->setPath(fBasePath, NULL, true);
72 
73         SkAAClip clip2;
74         clip2.setPath(fRectPath, NULL, true);
75         clip->op(clip2, op);
76     }
77 
drawOrig(SkCanvas * canvas)78     void drawOrig(SkCanvas* canvas) {
79         SkPaint     paint;
80 
81         paint.setStyle(SkPaint::kStroke_Style);
82         paint.setColor(SK_ColorBLACK);
83 
84         canvas->drawRect(fBase, paint);
85         canvas->drawRect(fRect, paint);
86     }
87 
drawRgnOped(SkCanvas * canvas,SkRegion::Op op,SkColor color)88     void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
89 
90         SkAAClip clip;
91 
92         this->buildRgn(&clip, op);
93         this->drawOrig(canvas);
94 
95         SkPaint paint;
96         paint.setColor(color);
97         paint_rgn(canvas, clip, paint);
98     }
99 
drawPathsOped(SkCanvas * canvas,SkRegion::Op op,SkColor color)100     void drawPathsOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
101 
102         this->drawOrig(canvas);
103 
104         canvas->save();
105 
106         // create the clip mask with the supplied boolean op
107         if (kPath_GeomType == fGeomType) {
108             // path-based case
109             canvas->clipPath(fBasePath, SkRegion::kReplace_Op, true);
110             canvas->clipPath(fRectPath, op, true);
111         } else {
112             // rect-based case
113             canvas->clipRect(fBase, SkRegion::kReplace_Op, true);
114             canvas->clipRect(fRect, op, true);
115         }
116 
117         // draw a rect that will entirely cover the clip mask area
118         SkPaint paint;
119         paint.setColor(color);
120 
121         SkRect r = SkRect::MakeLTRB(SkIntToScalar(90),  SkIntToScalar(90),
122                                     SkIntToScalar(180), SkIntToScalar(180));
123 
124         canvas->drawRect(r, paint);
125 
126         canvas->restore();
127     }
128 
onShortName()129     virtual SkString onShortName() {
130         SkString str;
131         str.printf("simpleaaclip_%s",
132                     kRect_GeomType == fGeomType ? "rect" :
133                     (kPath_GeomType == fGeomType ? "path" :
134                     "aaclip"));
135         return str;
136     }
137 
onISize()138     virtual SkISize onISize() {
139         return SkISize::Make(640, 480);
140     }
141 
onDraw(SkCanvas * canvas)142     virtual void onDraw(SkCanvas* canvas) {
143 
144         static const struct {
145             SkColor         fColor;
146             const char*     fName;
147             SkRegion::Op    fOp;
148         } gOps[] = {
149             { SK_ColorBLACK,    "Difference", SkRegion::kDifference_Op    },
150             { SK_ColorRED,      "Intersect",  SkRegion::kIntersect_Op     },
151             { 0xFF008800,       "Union",      SkRegion::kUnion_Op         },
152             { SK_ColorGREEN,    "Rev Diff",   SkRegion::kReverseDifference_Op },
153             { SK_ColorYELLOW,   "Replace",    SkRegion::kReplace_Op       },
154             { SK_ColorBLUE,     "XOR",        SkRegion::kXOR_Op           },
155         };
156 
157         SkPaint textPaint;
158         textPaint.setAntiAlias(true);
159         sk_tool_utils::set_portable_typeface(&textPaint);
160         textPaint.setTextSize(SK_Scalar1*24);
161         int xOff = 0;
162 
163         for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
164             canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
165                              SkIntToScalar(75), SkIntToScalar(50),
166                              textPaint);
167 
168             if (kAAClip_GeomType == fGeomType) {
169                 this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
170             } else {
171                 this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor);
172             }
173 
174             if (xOff >= 400) {
175                 canvas->translate(SkIntToScalar(-400), SkIntToScalar(250));
176                 xOff = 0;
177             } else {
178                 canvas->translate(SkIntToScalar(200), 0);
179                 xOff += 200;
180             }
181         }
182     }
183 private:
184 
185     SkGeomTypes fGeomType;
186 
187     SkRect fBase;
188     SkRect fRect;
189 
190     SkPath fBasePath;       // fBase as a round rect
191     SkPath fRectPath;       // fRect as a round rect
192 
193     typedef GM INHERITED;
194 };
195 
196 //////////////////////////////////////////////////////////////////////////////
197 
198 // rects
199 DEF_GM( return new SimpleClipGM(SimpleClipGM::kRect_GeomType); )
200 DEF_GM( return new SimpleClipGM(SimpleClipGM::kPath_GeomType); )
201 DEF_GM( return new SimpleClipGM(SimpleClipGM::kAAClip_GeomType); )
202 
203 }
204