Home | History | Annotate | Download | only in Intersection
      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) / 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
    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) * 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 
    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 }
    348