1/*
2 * Copyright 2011 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#include "SampleCode.h"
9#include "SkAAClip.h"
10#include "SkView.h"
11#include "SkCanvas.h"
12#include "SkColorPriv.h"
13#include "SkPaint.h"
14#include "SkPath.h"
15#include "SkRandom.h"
16#include "SkClipOpPriv.h"
17
18constexpr int W = 150;
19constexpr int H = 200;
20
21static void show_text(SkCanvas* canvas, bool doAA) {
22    SkRandom rand;
23    SkPaint paint;
24    paint.setAntiAlias(doAA);
25    paint.setLCDRenderText(true);
26    paint.setTextSize(SkIntToScalar(20));
27
28    for (int i = 0; i < 200; ++i) {
29        paint.setColor((SK_A32_MASK << SK_A32_SHIFT) | rand.nextU());
30        canvas->drawString("Hamburgefons",
31                         rand.nextSScalar1() * W, rand.nextSScalar1() * H + 20,
32                         paint);
33    }
34}
35
36static void show_fill(SkCanvas* canvas, bool doAA) {
37    SkRandom rand;
38    SkPaint paint;
39    paint.setAntiAlias(doAA);
40
41    for (int i = 0; i < 50; ++i) {
42        SkRect r;
43        SkPath p;
44
45        r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H,
46                  rand.nextUScalar1() * W, rand.nextUScalar1() * H);
47        paint.setColor(rand.nextU());
48        canvas->drawRect(r, paint);
49
50        r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H,
51                  rand.nextUScalar1() * W, rand.nextUScalar1() * H);
52        paint.setColor(rand.nextU());
53        p.addOval(r);
54        canvas->drawPath(p, paint);
55    }
56}
57
58static SkScalar randRange(SkRandom& rand, SkScalar min, SkScalar max) {
59    SkASSERT(min <= max);
60    return min + rand.nextUScalar1() * (max - min);
61}
62
63static void show_stroke(SkCanvas* canvas, bool doAA, SkScalar strokeWidth, int n) {
64    SkRandom rand;
65    SkPaint paint;
66    paint.setAntiAlias(doAA);
67    paint.setStyle(SkPaint::kStroke_Style);
68    paint.setStrokeWidth(strokeWidth);
69
70    for (int i = 0; i < n; ++i) {
71        SkRect r;
72        SkPath p;
73
74        r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H,
75                  rand.nextUScalar1() * W, rand.nextUScalar1() * H);
76        paint.setColor(rand.nextU());
77        canvas->drawRect(r, paint);
78
79        r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H,
80                  rand.nextUScalar1() * W, rand.nextUScalar1() * H);
81        paint.setColor(rand.nextU());
82        p.addOval(r);
83        canvas->drawPath(p, paint);
84
85        const SkScalar minx = -SkIntToScalar(W)/4;
86        const SkScalar maxx = 5*SkIntToScalar(W)/4;
87        const SkScalar miny = -SkIntToScalar(H)/4;
88        const SkScalar maxy = 5*SkIntToScalar(H)/4;
89        paint.setColor(rand.nextU());
90        canvas->drawLine(randRange(rand, minx, maxx), randRange(rand, miny, maxy),
91                         randRange(rand, minx, maxx), randRange(rand, miny, maxy),
92                         paint);
93    }
94}
95
96static void show_hair(SkCanvas* canvas, bool doAA) {
97    show_stroke(canvas, doAA, 0, 150);
98}
99
100static void show_thick(SkCanvas* canvas, bool doAA) {
101    show_stroke(canvas, doAA, SkIntToScalar(5), 50);
102}
103
104typedef void (*CanvasProc)(SkCanvas*, bool);
105
106class ClipView : public SampleView {
107public:
108    ClipView() {
109        SkAAClip clip;
110        SkIRect r = { -2, -3, 842, 18 };
111        clip.setRect(r);
112    }
113
114    virtual ~ClipView() {
115    }
116
117protected:
118    // overrides from SkEventSink
119    virtual bool onQuery(SkEvent* evt) {
120        if (SampleCode::TitleQ(*evt)) {
121            SampleCode::TitleR(evt, "Clip");
122            return true;
123        }
124        return this->INHERITED::onQuery(evt);
125    }
126
127    virtual void onDrawContent(SkCanvas* canvas) {
128        canvas->drawColor(SK_ColorWHITE);
129        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
130
131        static const CanvasProc gProc[] = {
132            show_text, show_thick, show_hair, show_fill
133        };
134
135        SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
136        SkPath clipPath;
137        r.inset(SK_Scalar1 / 4, SK_Scalar1 / 4);
138        clipPath.addRoundRect(r, SkIntToScalar(20), SkIntToScalar(20));
139
140//        clipPath.toggleInverseFillType();
141
142        for (int aa = 0; aa <= 1; ++aa) {
143            canvas->save();
144            for (size_t i = 0; i < SK_ARRAY_COUNT(gProc); ++i) {
145                canvas->save();
146                canvas->clipPath(clipPath, kIntersect_SkClipOp, SkToBool(aa));
147//                canvas->drawColor(SK_ColorWHITE);
148                gProc[i](canvas, SkToBool(aa));
149                canvas->restore();
150                canvas->translate(W * SK_Scalar1 * 8 / 7, 0);
151            }
152            canvas->restore();
153            canvas->translate(0, H * SK_Scalar1 * 8 / 7);
154        }
155    }
156
157private:
158    typedef SampleView INHERITED;
159};
160
161//////////////////////////////////////////////////////////////////////////////
162
163static SkView* MyFactory() { return new ClipView; }
164static SkViewRegister reg(MyFactory);
165