1#include "EdgeDemo.h" 2#include "EdgeWalker_Test.h" 3#include "ShapeOps.h" 4#import "SkCanvas.h" 5#import "SkPaint.h" 6 7extern 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); 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. 40static 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 84static 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 103static 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) / stars); 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 154static 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 233static 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) * xDiv / 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 269static 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 328static bool (*drawDemos[])(SkCanvas* , int , bool ) = { 329 drawStars, 330 drawCircles, 331 drawLetters, 332}; 333 334static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]); 335 336static bool (*firstTest)(SkCanvas* , int , bool) = drawStars; 337 338 339bool 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} 348