blob: 684dfd99b745d9bde3062368c3e522a67777825e [file] [log] [blame]
caryclark@google.coma5764232012-03-28 16:20:21 +00001#include "EdgeDemo.h"
2#include "EdgeWalker_Test.h"
3#include "ShapeOps.h"
4#import "SkCanvas.h"
5#import "SkPaint.h"
6
caryclark@google.com6aea33f2012-10-09 14:11:58 +00007extern void showPath(const SkPath& path, const char* str);
8
9static bool drawPaths(SkCanvas* canvas, const SkPath& path, bool useOld)
10{
11 SkPath out;
12#define SHOW_PATH 0
13#if SHOW_PATH
14 showPath(path, "original:");
15#endif
16 if (useOld) {
17 simplify(path, true, out);
18 } else {
19 simplifyx(path, out);
20 }
21#if SHOW_PATH
22 showPath(out, "simplified:");
23#endif
24 SkPaint paint;
25 paint.setAntiAlias(true);
26 paint.setStyle(SkPaint::kStroke_Style);
caryclark@google.com31143cf2012-11-09 22:14:19 +000027// paint.setStrokeWidth(6);
28 // paint.setColor(0x1F003f7f);
29 // canvas->drawPath(path, paint);
caryclark@google.com6aea33f2012-10-09 14:11:58 +000030 paint.setColor(0xFF305F00);
31 paint.setStrokeWidth(1);
32 canvas->drawPath(out, paint);
33 return true;
34}
35
caryclark@google.coma5764232012-03-28 16:20:21 +000036// Three circles bounce inside a rectangle. The circles describe three, four
37// or five points which in turn describe a polygon. The polygon points
38// bounce inside the circles. The circles rotate and scale over time. The
39// polygons are combined into a single path, simplified, and stroked.
caryclark@google.com03f97062012-08-21 13:13:52 +000040static bool drawCircles(SkCanvas* canvas, int step, bool useOld)
caryclark@google.coma5764232012-03-28 16:20:21 +000041{
42 const int circles = 3;
43 int scales[circles];
44 int angles[circles];
45 int locs[circles * 2];
46 int pts[circles * 2 * 4];
47 int c, p;
48 for (c = 0; c < circles; ++c) {
49 scales[c] = abs(10 - (step + c * 4) % 21);
50 angles[c] = (step + c * 6) % 600;
51 locs[c * 2] = abs(130 - (step + c * 9) % 261);
52 locs[c * 2 + 1] = abs(170 - (step + c * 11) % 341);
53 for (p = 0; p < 4; ++p) {
54 pts[c * 8 + p * 2] = abs(90 - ((step + c * 121 + p * 13) % 190));
55 pts[c * 8 + p * 2 + 1] = abs(110 - ((step + c * 223 + p * 17) % 230));
56 }
57 }
caryclark@google.com6aea33f2012-10-09 14:11:58 +000058 SkPath path;
caryclark@google.coma5764232012-03-28 16:20:21 +000059 for (c = 0; c < circles; ++c) {
60 for (p = 0; p < 4; ++p) {
61 SkScalar x = pts[c * 8 + p * 2];
62 SkScalar y = pts[c * 8 + p * 2 + 1];
63 x *= 3 + scales[c] / 10.0f;
64 y *= 3 + scales[c] / 10.0f;
65 SkScalar angle = angles[c] * 3.1415f * 2 / 600;
caryclark@google.com03f97062012-08-21 13:13:52 +000066 SkScalar temp = (SkScalar) (x * cos(angle) - y * sin(angle));
67 y = (SkScalar) (x * sin(angle) + y * cos(angle));
caryclark@google.coma5764232012-03-28 16:20:21 +000068 x = temp;
69 x += locs[c * 2] * 200 / 130.0f;
70 y += locs[c * 2 + 1] * 200 / 170.0f;
71 x += 50;
72 // y += 200;
73 if (p == 0) {
74 path.moveTo(x, y);
75 } else {
76 path.lineTo(x, y);
77 }
78 }
79 path.close();
80 }
caryclark@google.com6aea33f2012-10-09 14:11:58 +000081 return drawPaths(canvas, path, useOld);
caryclark@google.coma5764232012-03-28 16:20:21 +000082}
83
rmistry@google.comd6176b02012-08-23 18:14:13 +000084static void createStar(SkPath& path, SkScalar innerRadius, SkScalar outerRadius,
caryclark@google.coma5764232012-03-28 16:20:21 +000085 SkScalar startAngle, int points, SkPoint center) {
86 SkScalar angle = startAngle;
87 for (int index = 0; index < points * 2; ++index) {
88 SkScalar radius = index & 1 ? outerRadius : innerRadius;
caryclark@google.com03f97062012-08-21 13:13:52 +000089 SkScalar x = (SkScalar) (radius * cos(angle));
90 SkScalar y = (SkScalar) (radius * sin(angle));
caryclark@google.coma5764232012-03-28 16:20:21 +000091 x += center.fX;
92 y += center.fY;
93 if (index == 0) {
94 path.moveTo(x, y);
95 } else {
96 path.lineTo(x, y);
97 }
98 angle += 3.1415f / points;
99 }
100 path.close();
101}
102
caryclark@google.com03f97062012-08-21 13:13:52 +0000103static bool drawStars(SkCanvas* canvas, int step, bool useOld)
caryclark@google.coma5764232012-03-28 16:20:21 +0000104{
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000105 SkPath path;
caryclark@google.coma5764232012-03-28 16:20:21 +0000106 const int stars = 25;
107 int pts[stars];
caryclark@google.com03f97062012-08-21 13:13:52 +0000108 // static bool initialize = true;
caryclark@google.coma5764232012-03-28 16:20:21 +0000109 int s;
110 for (s = 0; s < stars; ++s) {
111 pts[s] = 4 + (s % 7);
112 }
113 SkPoint locs[stars];
114 SkScalar angles[stars];
115 SkScalar innerRadius[stars];
116 SkScalar outerRadius[stars];
117 const int width = 640;
118 const int height = 480;
119 const int margin = 30;
120 const int minRadius = 120;
121 const int maxInner = 800;
122 const int maxOuter = 1153;
123 for (s = 0; s < stars; ++s) {
caryclark@google.com03f97062012-08-21 13:13:52 +0000124 int starW = (int) (width - margin * 2 + (SkScalar) s * (stars - s) / stars);
caryclark@google.coma5764232012-03-28 16:20:21 +0000125 locs[s].fX = (int) (step * (1.3f * (s + 1) / stars) + s * 121) % (starW * 2);
126 if (locs[s].fX > starW) {
127 locs[s].fX = starW * 2 - locs[s].fX;
128 }
129 locs[s].fX += margin;
caryclark@google.com03f97062012-08-21 13:13:52 +0000130 int starH = (int) (height - margin * 2 + (SkScalar) s * s / stars);
caryclark@google.coma5764232012-03-28 16:20:21 +0000131 locs[s].fY = (int) (step * (1.7f * (s + 1) / stars) + s * 183) % (starH * 2);
132 if (locs[s].fY > starH) {
133 locs[s].fY = starH * 2 - locs[s].fY;
134 }
135 locs[s].fY += margin;
136 angles[s] = ((step + s * 47) % (360 * 4)) * 3.1415f / 180 / 4;
137 innerRadius[s] = (step + s * 30) % (maxInner * 2);
138 if (innerRadius[s] > maxInner) {
139 innerRadius[s] = (maxInner * 2) - innerRadius[s];
140 }
141 innerRadius[s] = innerRadius[s] / 4 + minRadius;
142 outerRadius[s] = (step + s * 70) % (maxOuter * 2);
143 if (outerRadius[s] > maxOuter) {
144 outerRadius[s] = (maxOuter * 2) - outerRadius[s];
145 }
146 outerRadius[s] = outerRadius[s] / 4 + minRadius;
147 createStar(path, innerRadius[s] / 4.0f, outerRadius[s] / 4.0f,
148 angles[s], pts[s], locs[s]);
149 }
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000150 return drawPaths(canvas, path, useOld);
151}
152
caryclark@google.comaa358312013-01-29 20:28:49 +0000153#if 0
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000154static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) {
155 // capture everything in a desired rectangle
156 SkPath tiny;
157 bool closed = true;
158 SkPath::Iter iter(path, false);
159 SkPoint pts[4];
160 SkPath::Verb verb;
161 int count = 0;
162 SkPoint lastPt;
163 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
164 switch (verb) {
165 case SkPath::kMove_Verb:
166 count = 0;
167 break;
168 case SkPath::kLine_Verb:
169 count = 1;
170 break;
171 case SkPath::kQuad_Verb:
172 count = 2;
173 break;
174 case SkPath::kCubic_Verb:
175 count = 3;
176 break;
177 case SkPath::kClose_Verb:
178 if (!closed) {
179 tiny.close();
180 closed = true;
181 }
182 count = 0;
183 break;
184 default:
185 SkDEBUGFAIL("bad verb");
186 }
187 if (!count) {
188 continue;
189 }
190 SkRect bounds;
191 bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
192 for (int i = 1; i <= count; ++i) {
193 bounds.growToInclude(pts[i].fX + 0.1f, pts[i].fY + 0.1f);
194 }
195 if (!SkRect::Intersects(target, bounds)) {
196 continue;
197 }
198 if (closed) {
199 tiny.moveTo(pts[0].fX, pts[0].fY);
200 closed = false;
201 } else if (pts[0] != lastPt) {
202 tiny.lineTo(pts[0].fX, pts[0].fY);
203 }
204 switch (verb) {
205 case SkPath::kLine_Verb:
206 tiny.lineTo(pts[1].fX, pts[1].fY);
207 lastPt = pts[1];
208 break;
209 case SkPath::kQuad_Verb:
210 tiny.quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
211 lastPt = pts[2];
212 break;
213 case SkPath::kCubic_Verb:
214 tiny.cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
215 lastPt = pts[3];
216 break;
217 default:
218 SkDEBUGFAIL("bad verb");
219 }
220 }
221 if (!closed) {
222 tiny.close();
223 }
caryclark@google.comc91dfe42012-10-16 12:06:27 +0000224 if (show) {
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000225 showPath(tiny, NULL);
226 SkDebugf("simplified:\n");
227 }
caryclark@google.coma461ff02012-10-11 12:54:23 +0000228 testSimplifyx(tiny);
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000229}
caryclark@google.comaa358312013-01-29 20:28:49 +0000230#endif
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000231
caryclark@google.comaa358312013-01-29 20:28:49 +0000232#if 0
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000233static void tryRonco(const SkPath& path) {
caryclark@google.com0b7da432012-10-31 19:00:20 +0000234 int divMax = 64;
caryclark@google.comf839c032012-10-26 21:03:50 +0000235 int divMin = 1;
236 int xDivMin = 0;
237 int yDivMin = 0;
238 bool allYs = true;
239 bool allXs = true;
caryclark@google.comfb51afb2012-10-19 15:54:16 +0000240 if (1) {
caryclark@google.com0b7da432012-10-31 19:00:20 +0000241 divMax = divMin = 64;
242 xDivMin = 11;
caryclark@google.comf839c032012-10-26 21:03:50 +0000243 yDivMin = 0;
244 allXs = true;
245 allYs = true;
246 }
caryclark@google.com0b7da432012-10-31 19:00:20 +0000247 for (int divs = divMax; divs >= divMin; divs /= 2) {
caryclark@google.comf839c032012-10-26 21:03:50 +0000248 SkDebugf("divs=%d\n",divs);
249 const SkRect& overall = path.getBounds();
250 SkScalar cellWidth = overall.width() / divs * 2;
251 SkScalar cellHeight = overall.height() / divs * 2;
252 SkRect target;
253 int xDivMax = divMax == divMin && !allXs ? xDivMin + 1 : divs;
254 int yDivMax = divMax == divMin && !allYs ? yDivMin + 1 : divs;
255 for (int xDiv = xDivMin; xDiv < xDivMax; ++xDiv) {
256 SkDebugf("xDiv=%d\n",xDiv);
257 for (int yDiv = yDivMin; yDiv < yDivMax; ++yDiv) {
258 SkDebugf("yDiv=%d\n",yDiv);
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000259 target.setXYWH(overall.fLeft + (overall.width() - cellWidth) * xDiv / divs,
260 overall.fTop + (overall.height() - cellHeight) * yDiv / divs,
261 cellWidth, cellHeight);
caryclark@google.comf839c032012-10-26 21:03:50 +0000262 tryRoncoOnce(path, target, divMax == divMin);
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000263 }
264 }
265 }
266}
caryclark@google.comaa358312013-01-29 20:28:49 +0000267#endif
skia.committer@gmail.com439cb512012-10-10 02:01:30 +0000268
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000269static bool drawLetters(SkCanvas* canvas, int step, bool useOld)
270{
271 SkPath path;
272 const int width = 640;
273 const int height = 480;
274 const char testStr[] = "Merge";
275 const int testStrLen = sizeof(testStr) - 1;
276 SkPoint textPos[testStrLen];
277 SkScalar widths[testStrLen];
278 SkPaint paint;
279 paint.setTextSize(40);
280 paint.setAntiAlias(true);
281 paint.getTextWidths(testStr, testStrLen, widths, NULL);
282 SkScalar running = 0;
283 for (int x = 0; x < testStrLen; ++x) {
284 SkScalar width = widths[x];
285 widths[x] = running;
286 running += width;
287 }
288 SkScalar bias = (width - widths[testStrLen - 1]) / 2;
289 for (int x = 0; x < testStrLen; ++x) {
290 textPos[x].fX = bias + widths[x];
291 textPos[x].fY = height / 2;
292 }
293 paint.setTextSize(40 + step / 100.0f);
caryclark@google.com31143cf2012-11-09 22:14:19 +0000294#if 0
caryclark@google.comf839c032012-10-26 21:03:50 +0000295 bool oneShot = false;
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000296 for (int mask = 0; mask < 1 << testStrLen; ++mask) {
297 char maskStr[testStrLen];
caryclark@google.comf839c032012-10-26 21:03:50 +0000298#if 1
caryclark@google.com0b7da432012-10-31 19:00:20 +0000299 mask = 12;
caryclark@google.comf839c032012-10-26 21:03:50 +0000300 oneShot = true;
301#endif
302 SkDebugf("mask=%d\n", mask);
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000303 for (int letter = 0; letter < testStrLen; ++letter) {
304 maskStr[letter] = mask & (1 << letter) ? testStr[letter] : ' ';
305 }
306 paint.getPosTextPath(maskStr, testStrLen, textPos, &path);
caryclark@google.coma461ff02012-10-11 12:54:23 +0000307 // showPath(path, NULL);
308 // SkDebugf("%d simplified:\n", mask);
caryclark@google.comc91dfe42012-10-16 12:06:27 +0000309 tryRonco(path);
caryclark@google.comf839c032012-10-26 21:03:50 +0000310 // testSimplifyx(path);
311 if (oneShot) {
312 break;
313 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000314 }
315#endif
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000316 paint.getPosTextPath(testStr, testStrLen, textPos, &path);
caryclark@google.com0b7da432012-10-31 19:00:20 +0000317#if 0
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000318 tryRonco(path);
caryclark@google.comf839c032012-10-26 21:03:50 +0000319 SkDebugf("RoncoDone!\n");
caryclark@google.coma5764232012-03-28 16:20:21 +0000320#endif
caryclark@google.coma461ff02012-10-11 12:54:23 +0000321#if 0
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000322 showPath(path, NULL);
323 SkDebugf("simplified:\n");
caryclark@google.coma5764232012-03-28 16:20:21 +0000324#endif
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000325 return drawPaths(canvas, path, false);
caryclark@google.coma5764232012-03-28 16:20:21 +0000326}
327
caryclark@google.com03f97062012-08-21 13:13:52 +0000328static bool (*drawDemos[])(SkCanvas* , int , bool ) = {
caryclark@google.coma5764232012-03-28 16:20:21 +0000329 drawStars,
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000330 drawCircles,
331 drawLetters,
caryclark@google.coma5764232012-03-28 16:20:21 +0000332};
333
334static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]);
335
caryclark@google.comaa358312013-01-29 20:28:49 +0000336static bool (*firstTest)(SkCanvas* , int , bool) = drawStars;
caryclark@google.coma5764232012-03-28 16:20:21 +0000337
338
caryclark@google.com03f97062012-08-21 13:13:52 +0000339bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) {
caryclark@google.coma5764232012-03-28 16:20:21 +0000340 size_t index = 0;
341 if (firstTest) {
342 while (index < drawDemosCount && drawDemos[index] != firstTest) {
343 ++index;
344 }
345 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000346 return (*drawDemos[index])(canvas, step, useOld);
caryclark@google.coma5764232012-03-28 16:20:21 +0000347}