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 "include/core/SkCanvas.h"
9#include "include/core/SkFont.h"
10#include "include/core/SkPath.h"
11#include "samplecode/Sample.h"
12
13class ComplexClipView : public Sample {
14    void onOnceBeforeDraw() override {
15        this->setBGColor(0xFFA0DDA0);
16    }
17
18    SkString name() override { return SkString("ComplexClip"); }
19
20    void onDrawContent(SkCanvas* canvas) override {
21        SkPath path;
22        path.moveTo(SkIntToScalar(0),   SkIntToScalar(50));
23        path.quadTo(SkIntToScalar(0),   SkIntToScalar(0),   SkIntToScalar(50),  SkIntToScalar(0));
24        path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
25        path.quadTo(SkIntToScalar(200), SkIntToScalar(0),   SkIntToScalar(200), SkIntToScalar(25));
26        path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
27        path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
28        path.lineTo(SkIntToScalar(0),   SkIntToScalar(200));
29        path.close();
30        path.moveTo(SkIntToScalar(50),  SkIntToScalar(50));
31        path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
32        path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
33        path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
34        path.lineTo(SkIntToScalar(50),  SkIntToScalar(150));
35        path.close();
36        path.setFillType(SkPathFillType::kEvenOdd);
37        SkColor pathColor = SK_ColorBLACK;
38        SkPaint pathPaint;
39        pathPaint.setAntiAlias(true);
40        pathPaint.setColor(pathColor);
41
42        SkPath clipA;
43        clipA.moveTo(SkIntToScalar(10),  SkIntToScalar(20));
44        clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
45        clipA.lineTo(SkIntToScalar(70),  SkIntToScalar(105));
46        clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
47        clipA.lineTo(SkIntToScalar(-5),  SkIntToScalar(180));
48        clipA.close();
49        SkColor colorA = SK_ColorCYAN;
50
51        SkPath clipB;
52        clipB.moveTo(SkIntToScalar(40),  SkIntToScalar(10));
53        clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
54        clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
55        clipB.lineTo(SkIntToScalar(40),  SkIntToScalar(185));
56        clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
57        clipB.close();
58        SkColor colorB = SK_ColorRED;
59
60        SkFont font;
61        font.setSize(20);
62
63        SkPaint paint;
64        paint.setAntiAlias(true);
65
66        paint.setStyle(SkPaint::kStroke_Style);
67        paint.setStrokeWidth(0);
68
69        canvas->translate(SkIntToScalar(10),SkIntToScalar(10));
70        canvas->drawPath(path, pathPaint);
71        paint.setColor(colorA);
72        canvas->drawPath(clipA, paint);
73        paint.setColor(colorB);
74        canvas->drawPath(clipB, paint);
75
76        static const struct {
77            SkClipOp    fOp;
78            const char* fName;
79        } gOps[] = { //extra spaces in names for measureText
80            {SkClipOp::kIntersect,         "Isect "},
81            {SkClipOp::kDifference,        "Diff " },
82        };
83
84        canvas->translate(0, SkIntToScalar(40));
85        canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
86        canvas->save();
87
88        for (int invA = 0; invA < 2; ++invA) {
89            for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
90                size_t idx = invA * SK_ARRAY_COUNT(gOps) + op;
91                if (!(idx % 3)) {
92                    canvas->restore();
93                    canvas->translate(0, SkIntToScalar(250));
94                    canvas->save();
95                }
96                canvas->save();
97                    // set clip
98                    clipA.setFillType(invA ? SkPathFillType::kInverseEvenOdd :
99                                             SkPathFillType::kEvenOdd);
100                    canvas->clipPath(clipA);
101                    canvas->clipPath(clipB, gOps[op].fOp);
102
103                    // draw path clipped
104                    canvas->drawPath(path, pathPaint);
105                canvas->restore();
106
107                // draw path in hairline
108                paint.setColor(pathColor);
109                canvas->drawPath(path, paint);
110
111                // draw clips in hair line
112                paint.setColor(colorA);
113                canvas->drawPath(clipA, paint);
114                paint.setColor(colorB);
115                canvas->drawPath(clipB, paint);
116
117                SkScalar txtX = SkIntToScalar(55);
118                paint.setColor(colorA);
119                const char* aTxt = invA ? "InverseA " : "A ";
120                canvas->drawSimpleText(aTxt, strlen(aTxt), SkTextEncoding::kUTF8, txtX, SkIntToScalar(220), font, paint);
121                txtX += font.measureText(aTxt, strlen(aTxt), SkTextEncoding::kUTF8);
122                paint.setColor(SK_ColorBLACK);
123                canvas->drawSimpleText(gOps[op].fName, strlen(gOps[op].fName), SkTextEncoding::kUTF8,
124                                    txtX, 220, font, paint);
125                txtX += font.measureText(gOps[op].fName, strlen(gOps[op].fName), SkTextEncoding::kUTF8);
126                paint.setColor(colorB);
127                canvas->drawSimpleText("B", 1, SkTextEncoding::kUTF8, txtX, 220, font, paint);
128
129                canvas->translate(SkIntToScalar(250),0);
130            }
131        }
132        canvas->restore();
133    }
134};
135
136DEF_SAMPLE( return new ComplexClipView(); )
137