| OLD | NEW |
| (Empty) |
| 1 #include "EdgeDemo.h" | |
| 2 #include "EdgeWalker_Test.h" | |
| 3 #include "ShapeOps.h" | |
| 4 #import "SkCanvas.h" | |
| 5 #import "SkPaint.h" | |
| 6 | |
| 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 | |
| 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. | |
| 40 static bool drawCircles(SkCanvas* canvas, int step, bool useOld) | |
| 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 } | |
| 58 SkPath path; | |
| 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; | |
| 66 SkScalar temp = (SkScalar) (x * cos(angle) - y * sin(angle)); | |
| 67 y = (SkScalar) (x * sin(angle) + y * cos(angle)); | |
| 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 } | |
| 81 return drawPaths(canvas, path, useOld); | |
| 82 } | |
| 83 | |
| 84 static void createStar(SkPath& path, SkScalar innerRadius, SkScalar outerRadius, | |
| 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; | |
| 89 SkScalar x = (SkScalar) (radius * cos(angle)); | |
| 90 SkScalar y = (SkScalar) (radius * sin(angle)); | |
| 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 | |
| 103 static bool drawStars(SkCanvas* canvas, int step, bool useOld) | |
| 104 { | |
| 105 SkPath path; | |
| 106 const int stars = 25; | |
| 107 int pts[stars]; | |
| 108 // static bool initialize = true; | |
| 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) { | |
| 124 int starW = (int) (width - margin * 2 + (SkScalar) s * (stars - s) / sta
rs); | |
| 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; | |
| 130 int starH = (int) (height - margin * 2 + (SkScalar) s * s / stars); | |
| 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 } | |
| 150 return drawPaths(canvas, path, useOld); | |
| 151 } | |
| 152 | |
| 153 #if 0 | |
| 154 static 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 } | |
| 224 if (show) { | |
| 225 showPath(tiny, NULL); | |
| 226 SkDebugf("simplified:\n"); | |
| 227 } | |
| 228 testSimplifyx(tiny); | |
| 229 } | |
| 230 #endif | |
| 231 | |
| 232 #if 0 | |
| 233 static void tryRonco(const SkPath& path) { | |
| 234 int divMax = 64; | |
| 235 int divMin = 1; | |
| 236 int xDivMin = 0; | |
| 237 int yDivMin = 0; | |
| 238 bool allYs = true; | |
| 239 bool allXs = true; | |
| 240 if (1) { | |
| 241 divMax = divMin = 64; | |
| 242 xDivMin = 11; | |
| 243 yDivMin = 0; | |
| 244 allXs = true; | |
| 245 allYs = true; | |
| 246 } | |
| 247 for (int divs = divMax; divs >= divMin; divs /= 2) { | |
| 248 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); | |
| 259 target.setXYWH(overall.fLeft + (overall.width() - cellWidth) * x
Div / divs, | |
| 260 overall.fTop + (overall.height() - cellHeight) * yDiv /
divs, | |
| 261 cellWidth, cellHeight); | |
| 262 tryRoncoOnce(path, target, divMax == divMin); | |
| 263 } | |
| 264 } | |
| 265 } | |
| 266 } | |
| 267 #endif | |
| 268 | |
| 269 static 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); | |
| 294 #if 0 | |
| 295 bool oneShot = false; | |
| 296 for (int mask = 0; mask < 1 << testStrLen; ++mask) { | |
| 297 char maskStr[testStrLen]; | |
| 298 #if 1 | |
| 299 mask = 12; | |
| 300 oneShot = true; | |
| 301 #endif | |
| 302 SkDebugf("mask=%d\n", mask); | |
| 303 for (int letter = 0; letter < testStrLen; ++letter) { | |
| 304 maskStr[letter] = mask & (1 << letter) ? testStr[letter] : ' '; | |
| 305 } | |
| 306 paint.getPosTextPath(maskStr, testStrLen, textPos, &path); | |
| 307 // showPath(path, NULL); | |
| 308 // SkDebugf("%d simplified:\n", mask); | |
| 309 tryRonco(path); | |
| 310 // testSimplifyx(path); | |
| 311 if (oneShot) { | |
| 312 break; | |
| 313 } | |
| 314 } | |
| 315 #endif | |
| 316 paint.getPosTextPath(testStr, testStrLen, textPos, &path); | |
| 317 #if 0 | |
| 318 tryRonco(path); | |
| 319 SkDebugf("RoncoDone!\n"); | |
| 320 #endif | |
| 321 #if 0 | |
| 322 showPath(path, NULL); | |
| 323 SkDebugf("simplified:\n"); | |
| 324 #endif | |
| 325 return drawPaths(canvas, path, false); | |
| 326 } | |
| 327 | |
| 328 static bool (*drawDemos[])(SkCanvas* , int , bool ) = { | |
| 329 drawStars, | |
| 330 drawCircles, | |
| 331 drawLetters, | |
| 332 }; | |
| 333 | |
| 334 static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]); | |
| 335 | |
| 336 static bool (*firstTest)(SkCanvas* , int , bool) = drawStars; | |
| 337 | |
| 338 | |
| 339 bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) { | |
| 340 size_t index = 0; | |
| 341 if (firstTest) { | |
| 342 while (index < drawDemosCount && drawDemos[index] != firstTest) { | |
| 343 ++index; | |
| 344 } | |
| 345 } | |
| 346 return (*drawDemos[index])(canvas, step, useOld); | |
| 347 } | |
| OLD | NEW |