aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/thinconcavepaths.cpp
blob: bc28d6b0a037f2bed3bc1381747f0ffdc42eb683 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkPath.h"

namespace {
// Test thin stroked rect (stroked "by hand", not by stroking).
void draw_thin_stroked_rect(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(10 + width, 10 + width);
    path.lineTo(40,         10 + width);
    path.lineTo(40,         20);
    path.lineTo(10 + width, 20);
    path.moveTo(10,         10);
    path.lineTo(10,         20 + width);
    path.lineTo(40 + width, 20 + width);
    path.lineTo(40 + width, 10);
    canvas->drawPath(path, paint);
}

void draw_thin_right_angle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(10 + width, 10 + width);
    path.lineTo(40,         10 + width);
    path.lineTo(40,         20);
    path.lineTo(40 + width, 20 + width);
    path.lineTo(40 + width, 10);
    path.lineTo(10,         10);
    canvas->drawPath(path, paint);
}

// Test thin horizontal line (<1 pixel) which should give lower alpha.
void draw_golf_club(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(20, 10);
    path.lineTo(80, 10);
    path.lineTo(80, 10 + width);
    path.lineTo(30, 10 + width);
    path.lineTo(30, 20);
    path.lineTo(20, 20);
    canvas->drawPath(path, paint);
}

// Test thin lines between two filled regions. The outer edges overlap, but
// there are no inverted edges to fix.
void draw_barbell(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkScalar offset = width * 0.5f;
    SkPath path;
    path.moveTo(30,  5);
    path.lineTo(40 - offset, 15 - offset);
    path.lineTo(60 + offset, 15 - offset);
    path.lineTo(70,  5);
    path.lineTo(70, 25);
    path.lineTo(60 + offset, 15 + offset);
    path.lineTo(40 - offset, 15 + offset);
    path.lineTo(30, 25);
    canvas->drawPath(path, paint);
}

// Test a thin rectangle and triangle. The top and bottom inner edges of the
// rectangle and all inner edges of the triangle invert on stroking.
void draw_thin_rect_and_triangle(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(30,  5);
    path.lineTo(30 + width,  5);
    path.lineTo(30 + width,  25);
    path.lineTo(30,  25);
    path.moveTo(40,  5);
    path.lineTo(40 + width,  5);
    path.lineTo(40,  25);
    canvas->drawPath(path, paint);
}

// Two triangles joined by a very thin bridge. The tiny triangle formed
// by the inner edges at the bridge is inverted.
// (These are actually now more phat pants than hipster pants.)
void draw_hipster_pants(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(10, 10);
    path.lineTo(10, 20);
    path.lineTo(50, 10 + width);
    path.lineTo(90, 20);
    path.lineTo(90, 10);
    canvas->drawPath(path, paint);
}

// A thin z-shape whose interior inverts on stroking. The top and bottom inner edges invert, and
// the connector edges at the "elbows" intersect the inner edges.
void draw_skinny_snake(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(20 + width, 10);
    path.lineTo(20 + width, 20);
    path.lineTo(10 + width, 30);
    path.lineTo(10 + width, 40);
    path.lineTo(10 - width, 40);
    path.lineTo(10 - width, 30);
    path.lineTo(20 - width, 20);
    path.lineTo(20 - width, 10);
    canvas->drawPath(path, paint);
}

// Test pointy features whose outer edges extend far to the right on stroking.
void draw_pointy_golf_club(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
    SkPath path;
    path.moveTo(20, 10);
    path.lineTo(80, 10 + width * 0.5);
    path.lineTo(30, 10 + width);
    path.lineTo(30, 20);
    path.lineTo(20, 20);
    canvas->drawPath(path, paint);
}

};

DEF_SIMPLE_GM(thinconcavepaths, canvas, 550, 400) {
    SkPaint paint;

    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kFill_Style);

    canvas->save();
    for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) {
        draw_thin_stroked_rect(canvas, paint, width);
        canvas->translate(0, 25);
    }
    canvas->restore();
    canvas->translate(50, 0);
    canvas->save();
    for (SkScalar width = 0.5f; width < 2.05f; width += 0.25f) {
        draw_thin_right_angle(canvas, paint, width);
        canvas->translate(0, 25);
    }
    canvas->restore();
    canvas->translate(40, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_golf_club(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(70, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_thin_rect_and_triangle(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(30, 0);
    canvas->save();

    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_barbell(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(80, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_hipster_pants(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(100, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_skinny_snake(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(30, 0);
    canvas->save();
    for (SkScalar width = 0.2f; width < 2.1f; width += 0.2f) {
        draw_pointy_golf_club(canvas, paint, width);
        canvas->translate(0, 30);
    }
    canvas->restore();
    canvas->translate(100, 0);
}