caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 1 | #include "EdgeDemo.h" |
| 2 | #include "EdgeWalker_Test.h" |
| 3 | #include "ShapeOps.h" |
| 4 | #import "SkCanvas.h" |
| 5 | #import "SkPaint.h" |
| 6 | |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 7 | extern void showPath(const SkPath& path, const char* str); |
| 8 | |
| 9 | static 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); |
| 27 | // paint.setStrokeWidth(6); |
| 28 | // paint.setColor(0x1F003f7f); |
| 29 | // canvas->drawPath(path, paint); |
| 30 | paint.setColor(0xFF305F00); |
| 31 | paint.setStrokeWidth(1); |
| 32 | canvas->drawPath(out, paint); |
| 33 | return true; |
| 34 | } |
| 35 | |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 36 | // 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.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 40 | static bool drawCircles(SkCanvas* canvas, int step, bool useOld) |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 41 | { |
| 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.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 58 | SkPath path; |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 59 | 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.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 66 | SkScalar temp = (SkScalar) (x * cos(angle) - y * sin(angle)); |
| 67 | y = (SkScalar) (x * sin(angle) + y * cos(angle)); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 68 | 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.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 81 | return drawPaths(canvas, path, useOld); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 82 | } |
| 83 | |
rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 84 | static void createStar(SkPath& path, SkScalar innerRadius, SkScalar outerRadius, |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 85 | 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.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 89 | SkScalar x = (SkScalar) (radius * cos(angle)); |
| 90 | SkScalar y = (SkScalar) (radius * sin(angle)); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 91 | 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.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 103 | static bool drawStars(SkCanvas* canvas, int step, bool useOld) |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 104 | { |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 105 | SkPath path; |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 106 | const int stars = 25; |
| 107 | int pts[stars]; |
caryclark@google.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 108 | // static bool initialize = true; |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 109 | 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.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 124 | int starW = (int) (width - margin * 2 + (SkScalar) s * (stars - s) / stars); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 125 | 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.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 130 | int starH = (int) (height - margin * 2 + (SkScalar) s * s / stars); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 131 | 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.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 150 | return drawPaths(canvas, path, useOld); |
| 151 | } |
| 152 | |
| 153 | static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) { |
| 154 | // capture everything in a desired rectangle |
| 155 | SkPath tiny; |
| 156 | bool closed = true; |
| 157 | SkPath::Iter iter(path, false); |
| 158 | SkPoint pts[4]; |
| 159 | SkPath::Verb verb; |
| 160 | int count = 0; |
| 161 | SkPoint lastPt; |
| 162 | while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| 163 | switch (verb) { |
| 164 | case SkPath::kMove_Verb: |
| 165 | count = 0; |
| 166 | break; |
| 167 | case SkPath::kLine_Verb: |
| 168 | count = 1; |
| 169 | break; |
| 170 | case SkPath::kQuad_Verb: |
| 171 | count = 2; |
| 172 | break; |
| 173 | case SkPath::kCubic_Verb: |
| 174 | count = 3; |
| 175 | break; |
| 176 | case SkPath::kClose_Verb: |
| 177 | if (!closed) { |
| 178 | tiny.close(); |
| 179 | closed = true; |
| 180 | } |
| 181 | count = 0; |
| 182 | break; |
| 183 | default: |
| 184 | SkDEBUGFAIL("bad verb"); |
| 185 | } |
| 186 | if (!count) { |
| 187 | continue; |
| 188 | } |
| 189 | SkRect bounds; |
| 190 | bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY); |
| 191 | for (int i = 1; i <= count; ++i) { |
| 192 | bounds.growToInclude(pts[i].fX + 0.1f, pts[i].fY + 0.1f); |
| 193 | } |
| 194 | if (!SkRect::Intersects(target, bounds)) { |
| 195 | continue; |
| 196 | } |
| 197 | if (closed) { |
| 198 | tiny.moveTo(pts[0].fX, pts[0].fY); |
| 199 | closed = false; |
| 200 | } else if (pts[0] != lastPt) { |
| 201 | tiny.lineTo(pts[0].fX, pts[0].fY); |
| 202 | } |
| 203 | switch (verb) { |
| 204 | case SkPath::kLine_Verb: |
| 205 | tiny.lineTo(pts[1].fX, pts[1].fY); |
| 206 | lastPt = pts[1]; |
| 207 | break; |
| 208 | case SkPath::kQuad_Verb: |
| 209 | tiny.quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); |
| 210 | lastPt = pts[2]; |
| 211 | break; |
| 212 | case SkPath::kCubic_Verb: |
| 213 | tiny.cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY); |
| 214 | lastPt = pts[3]; |
| 215 | break; |
| 216 | default: |
| 217 | SkDEBUGFAIL("bad verb"); |
| 218 | } |
| 219 | } |
| 220 | if (!closed) { |
| 221 | tiny.close(); |
| 222 | } |
caryclark@google.com | c91dfe4 | 2012-10-16 12:06:27 +0000 | [diff] [blame] | 223 | if (show) { |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 224 | showPath(tiny, NULL); |
| 225 | SkDebugf("simplified:\n"); |
| 226 | } |
caryclark@google.com | a461ff0 | 2012-10-11 12:54:23 +0000 | [diff] [blame] | 227 | testSimplifyx(tiny); |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 228 | } |
| 229 | |
| 230 | static void tryRonco(const SkPath& path) { |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 231 | int divMax = 17; |
| 232 | int divMin = 1; |
| 233 | int xDivMin = 0; |
| 234 | int yDivMin = 0; |
| 235 | bool allYs = true; |
| 236 | bool allXs = true; |
caryclark@google.com | fb51afb | 2012-10-19 15:54:16 +0000 | [diff] [blame] | 237 | if (1) { |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 238 | divMax = divMin = 3; |
| 239 | xDivMin = 0; |
| 240 | yDivMin = 0; |
| 241 | allXs = true; |
| 242 | allYs = true; |
| 243 | } |
| 244 | for (int divs = divMax; divs >= divMin; divs -= 2) { |
| 245 | SkDebugf("divs=%d\n",divs); |
| 246 | const SkRect& overall = path.getBounds(); |
| 247 | SkScalar cellWidth = overall.width() / divs * 2; |
| 248 | SkScalar cellHeight = overall.height() / divs * 2; |
| 249 | SkRect target; |
| 250 | int xDivMax = divMax == divMin && !allXs ? xDivMin + 1 : divs; |
| 251 | int yDivMax = divMax == divMin && !allYs ? yDivMin + 1 : divs; |
| 252 | for (int xDiv = xDivMin; xDiv < xDivMax; ++xDiv) { |
| 253 | SkDebugf("xDiv=%d\n",xDiv); |
| 254 | for (int yDiv = yDivMin; yDiv < yDivMax; ++yDiv) { |
| 255 | SkDebugf("yDiv=%d\n",yDiv); |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 256 | target.setXYWH(overall.fLeft + (overall.width() - cellWidth) * xDiv / divs, |
| 257 | overall.fTop + (overall.height() - cellHeight) * yDiv / divs, |
| 258 | cellWidth, cellHeight); |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 259 | tryRoncoOnce(path, target, divMax == divMin); |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 260 | } |
| 261 | } |
| 262 | } |
| 263 | } |
skia.committer@gmail.com | 439cb51 | 2012-10-10 02:01:30 +0000 | [diff] [blame] | 264 | |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 265 | static bool drawLetters(SkCanvas* canvas, int step, bool useOld) |
| 266 | { |
| 267 | SkPath path; |
| 268 | const int width = 640; |
| 269 | const int height = 480; |
| 270 | const char testStr[] = "Merge"; |
| 271 | const int testStrLen = sizeof(testStr) - 1; |
| 272 | SkPoint textPos[testStrLen]; |
| 273 | SkScalar widths[testStrLen]; |
| 274 | SkPaint paint; |
| 275 | paint.setTextSize(40); |
| 276 | paint.setAntiAlias(true); |
| 277 | paint.getTextWidths(testStr, testStrLen, widths, NULL); |
| 278 | SkScalar running = 0; |
| 279 | for (int x = 0; x < testStrLen; ++x) { |
| 280 | SkScalar width = widths[x]; |
| 281 | widths[x] = running; |
| 282 | running += width; |
| 283 | } |
| 284 | SkScalar bias = (width - widths[testStrLen - 1]) / 2; |
| 285 | for (int x = 0; x < testStrLen; ++x) { |
| 286 | textPos[x].fX = bias + widths[x]; |
| 287 | textPos[x].fY = height / 2; |
| 288 | } |
| 289 | paint.setTextSize(40 + step / 100.0f); |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 290 | #if 1 |
| 291 | bool oneShot = false; |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 292 | for (int mask = 0; mask < 1 << testStrLen; ++mask) { |
| 293 | char maskStr[testStrLen]; |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 294 | #if 1 |
| 295 | mask = 3; |
| 296 | oneShot = true; |
| 297 | #endif |
| 298 | SkDebugf("mask=%d\n", mask); |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 299 | for (int letter = 0; letter < testStrLen; ++letter) { |
| 300 | maskStr[letter] = mask & (1 << letter) ? testStr[letter] : ' '; |
| 301 | } |
| 302 | paint.getPosTextPath(maskStr, testStrLen, textPos, &path); |
caryclark@google.com | a461ff0 | 2012-10-11 12:54:23 +0000 | [diff] [blame] | 303 | // showPath(path, NULL); |
| 304 | // SkDebugf("%d simplified:\n", mask); |
caryclark@google.com | c91dfe4 | 2012-10-16 12:06:27 +0000 | [diff] [blame] | 305 | tryRonco(path); |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 306 | // testSimplifyx(path); |
| 307 | if (oneShot) { |
| 308 | break; |
| 309 | } |
caryclark@google.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 310 | } |
| 311 | #endif |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 312 | paint.getPosTextPath(testStr, testStrLen, textPos, &path); |
caryclark@google.com | 185c7c4 | 2012-10-19 18:26:24 +0000 | [diff] [blame] | 313 | #if 1 |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 314 | tryRonco(path); |
caryclark@google.com | f839c03 | 2012-10-26 21:03:50 +0000 | [diff] [blame^] | 315 | SkDebugf("RoncoDone!\n"); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 316 | #endif |
caryclark@google.com | a461ff0 | 2012-10-11 12:54:23 +0000 | [diff] [blame] | 317 | #if 0 |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 318 | showPath(path, NULL); |
| 319 | SkDebugf("simplified:\n"); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 320 | #endif |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 321 | return drawPaths(canvas, path, false); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 322 | } |
| 323 | |
caryclark@google.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 324 | static bool (*drawDemos[])(SkCanvas* , int , bool ) = { |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 325 | drawStars, |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 326 | drawCircles, |
| 327 | drawLetters, |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 328 | }; |
| 329 | |
| 330 | static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]); |
| 331 | |
caryclark@google.com | 6aea33f | 2012-10-09 14:11:58 +0000 | [diff] [blame] | 332 | static bool (*firstTest)(SkCanvas* , int , bool) = drawLetters; |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 333 | |
| 334 | |
caryclark@google.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 335 | bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) { |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 336 | size_t index = 0; |
| 337 | if (firstTest) { |
| 338 | while (index < drawDemosCount && drawDemos[index] != firstTest) { |
| 339 | ++index; |
| 340 | } |
| 341 | } |
caryclark@google.com | 03f9706 | 2012-08-21 13:13:52 +0000 | [diff] [blame] | 342 | return (*drawDemos[index])(canvas, step, useOld); |
caryclark@google.com | a576423 | 2012-03-28 16:20:21 +0000 | [diff] [blame] | 343 | } |