Home | History | Annotate | Download | only in samplecode
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SampleCode.h"
     10 #include "SkAnimTimer.h"
     11 #include "SkView.h"
     12 #include "SkCanvas.h"
     13 #include "SkGradientShader.h"
     14 #include "SkGraphics.h"
     15 #include "SkImageDecoder.h"
     16 #include "SkPath.h"
     17 #include "SkRegion.h"
     18 #include "SkShader.h"
     19 #include "SkUtils.h"
     20 #include "SkXfermode.h"
     21 #include "SkColorPriv.h"
     22 #include "SkColorFilter.h"
     23 #include "SkParsePath.h"
     24 #include "SkTime.h"
     25 #include "SkTypeface.h"
     26 
     27 #include "SkGeometry.h"
     28 
     29 #include <stdlib.h>
     30 
     31 // http://code.google.com/p/skia/issues/detail?id=32
     32 static void test_cubic() {
     33     SkPoint src[4] = {
     34         { 556.25000f, 523.03003f },
     35         { 556.23999f, 522.96002f },
     36         { 556.21997f, 522.89001f },
     37         { 556.21997f, 522.82001f }
     38     };
     39     SkPoint dst[11];
     40     dst[10].set(42, -42);   // one past the end, that we don't clobber these
     41     SkScalar tval[] = { 0.33333334f, 0.99999994f };
     42 
     43     SkChopCubicAt(src, dst, tval, 2);
     44 
     45 #if 0
     46     for (int i = 0; i < 11; i++) {
     47         SkDebugf("--- %d [%g %g]\n", i, dst[i].fX, dst[i].fY);
     48     }
     49 #endif
     50 }
     51 
     52 static void test_cubic2() {
     53     const char* str = "M2242 -590088L-377758 9.94099e+07L-377758 9.94099e+07L2242 -590088Z";
     54     SkPath path;
     55     SkParsePath::FromSVGString(str, &path);
     56 
     57     {
     58 #ifdef SK_BUILD_FOR_WIN
     59         // windows doesn't have strtof
     60         float x = (float)strtod("9.94099e+07", nullptr);
     61 #else
     62         float x = strtof("9.94099e+07", nullptr);
     63 #endif
     64         int ix = (int)x;
     65         int fx = (int)(x * 65536);
     66         int ffx = SkScalarToFixed(x);
     67         SkDebugf("%g %x %x %x\n", x, ix, fx, ffx);
     68 
     69         SkRect r = path.getBounds();
     70         SkIRect ir;
     71         r.round(&ir);
     72         SkDebugf("[%g %g %g %g] [%x %x %x %x]\n",
     73                 SkScalarToDouble(r.fLeft), SkScalarToDouble(r.fTop),
     74                 SkScalarToDouble(r.fRight), SkScalarToDouble(r.fBottom),
     75                 ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
     76     }
     77 
     78     SkBitmap bitmap;
     79     bitmap.allocN32Pixels(300, 200);
     80 
     81     SkCanvas canvas(bitmap);
     82     SkPaint paint;
     83     paint.setAntiAlias(true);
     84     canvas.drawPath(path, paint);
     85 }
     86 
     87 class PathView : public SampleView {
     88     SkScalar fPrevSecs;
     89 public:
     90     SkScalar fDStroke, fStroke, fMinStroke, fMaxStroke;
     91     SkPath fPath[6];
     92     bool fShowHairline;
     93     bool fOnce;
     94 
     95     PathView() {
     96         fPrevSecs = 0;
     97         fOnce = false;
     98     }
     99 
    100     void init() {
    101         if (fOnce) {
    102             return;
    103         }
    104         fOnce = true;
    105 
    106         test_cubic();
    107         test_cubic2();
    108 
    109         fShowHairline = false;
    110 
    111         fDStroke = 1;
    112         fStroke = 10;
    113         fMinStroke = 10;
    114         fMaxStroke = 180;
    115 
    116         const SkScalar V = 85;
    117 
    118         fPath[0].moveTo(40, 70);
    119         fPath[0].lineTo(70, 70 + SK_ScalarHalf);
    120         fPath[0].lineTo(110, 70);
    121 
    122         fPath[1].moveTo(40, 70);
    123         fPath[1].lineTo(70, 70 - SK_ScalarHalf);
    124         fPath[1].lineTo(110, 70);
    125 
    126         fPath[2].moveTo(V, V);
    127         fPath[2].lineTo(50, V);
    128         fPath[2].lineTo(50, 50);
    129 
    130         fPath[3].moveTo(50, 50);
    131         fPath[3].lineTo(50, V);
    132         fPath[3].lineTo(V, V);
    133 
    134         fPath[4].moveTo(50, 50);
    135         fPath[4].lineTo(50, V);
    136         fPath[4].lineTo(52, 50);
    137 
    138         fPath[5].moveTo(52, 50);
    139         fPath[5].lineTo(50, V);
    140         fPath[5].lineTo(50, 50);
    141 
    142         this->setBGColor(0xFFDDDDDD);
    143     }
    144 
    145 protected:
    146     // overrides from SkEventSink
    147     bool onQuery(SkEvent* evt) override {
    148         if (SampleCode::TitleQ(*evt)) {
    149             SampleCode::TitleR(evt, "Paths");
    150             return true;
    151         }
    152         return this->INHERITED::onQuery(evt);
    153     }
    154 
    155     void drawPath(SkCanvas* canvas, const SkPath& path, SkPaint::Join j) {
    156         SkPaint paint;
    157 
    158         paint.setAntiAlias(true);
    159         paint.setStyle(SkPaint::kStroke_Style);
    160         paint.setStrokeJoin(j);
    161         paint.setStrokeWidth(fStroke);
    162 
    163         if (fShowHairline) {
    164             SkPath  fill;
    165 
    166             paint.getFillPath(path, &fill);
    167             paint.setStrokeWidth(0);
    168             canvas->drawPath(fill, paint);
    169         } else {
    170             canvas->drawPath(path, paint);
    171         }
    172 
    173         paint.setColor(SK_ColorRED);
    174         paint.setStrokeWidth(0);
    175         canvas->drawPath(path, paint);
    176     }
    177 
    178     void onDrawContent(SkCanvas* canvas) override {
    179         this->init();
    180         canvas->translate(50, 50);
    181 
    182         static const SkPaint::Join gJoins[] = {
    183             SkPaint::kBevel_Join,
    184             SkPaint::kMiter_Join,
    185             SkPaint::kRound_Join
    186         };
    187 
    188         for (size_t i = 0; i < SK_ARRAY_COUNT(gJoins); i++) {
    189             canvas->save();
    190             for (size_t j = 0; j < SK_ARRAY_COUNT(fPath); j++) {
    191                 this->drawPath(canvas, fPath[j], gJoins[i]);
    192                 canvas->translate(200, 0);
    193             }
    194             canvas->restore();
    195 
    196             canvas->translate(0, 200);
    197         }
    198     }
    199 
    200     bool onAnimate(const SkAnimTimer& timer) override {
    201         SkScalar currSecs = timer.scaled(100);
    202         SkScalar delta = currSecs - fPrevSecs;
    203         fPrevSecs = currSecs;
    204 
    205         fStroke += fDStroke * delta;
    206         if (fStroke > fMaxStroke || fStroke < fMinStroke) {
    207             fDStroke = -fDStroke;
    208         }
    209         return true;
    210     }
    211 
    212     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
    213         fShowHairline = !fShowHairline;
    214         this->inval(nullptr);
    215         return this->INHERITED::onFindClickHandler(x, y, modi);
    216     }
    217 
    218 private:
    219     typedef SampleView INHERITED;
    220 };
    221 DEF_SAMPLE( return new PathView; )
    222 
    223 //////////////////////////////////////////////////////////////////////////////
    224 
    225 #include "SkArcToPathEffect.h"
    226 #include "SkCornerPathEffect.h"
    227 #include "SkRandom.h"
    228 
    229 class ArcToView : public SampleView {
    230     bool fDoFrame, fDoArcTo, fDoCorner, fDoConic;
    231     SkPaint fPtsPaint, fArcToPaint, fSkeletonPaint, fCornerPaint;
    232 public:
    233     enum {
    234         N = 4
    235     };
    236     SkPoint fPts[N];
    237 
    238     ArcToView()
    239         : fDoFrame(false), fDoArcTo(false), fDoCorner(false), fDoConic(false)
    240     {
    241         SkRandom rand;
    242         for (int i = 0; i < N; ++i) {
    243             fPts[i].fX = 20 + rand.nextUScalar1() * 640;
    244             fPts[i].fY = 20 + rand.nextUScalar1() * 480;
    245         }
    246 
    247         const SkScalar rad = 50;
    248 
    249         fPtsPaint.setAntiAlias(true);
    250         fPtsPaint.setStrokeWidth(15);
    251         fPtsPaint.setStrokeCap(SkPaint::kRound_Cap);
    252 
    253         fArcToPaint.setAntiAlias(true);
    254         fArcToPaint.setStyle(SkPaint::kStroke_Style);
    255         fArcToPaint.setStrokeWidth(9);
    256         fArcToPaint.setColor(0x800000FF);
    257         fArcToPaint.setPathEffect(SkArcToPathEffect::Create(rad))->unref();
    258 
    259         fCornerPaint.setAntiAlias(true);
    260         fCornerPaint.setStyle(SkPaint::kStroke_Style);
    261         fCornerPaint.setStrokeWidth(13);
    262         fCornerPaint.setColor(SK_ColorGREEN);
    263         fCornerPaint.setPathEffect(SkCornerPathEffect::Create(rad*2))->unref();
    264 
    265         fSkeletonPaint.setAntiAlias(true);
    266         fSkeletonPaint.setStyle(SkPaint::kStroke_Style);
    267         fSkeletonPaint.setColor(SK_ColorRED);
    268     }
    269 
    270     void toggle(bool& value) {
    271         value = !value;
    272         this->inval(nullptr);
    273     }
    274 
    275 protected:
    276     // overrides from SkEventSink
    277     bool onQuery(SkEvent* evt) override {
    278         if (SampleCode::TitleQ(*evt)) {
    279             SampleCode::TitleR(evt, "ArcTo");
    280             return true;
    281         }
    282         SkUnichar uni;
    283         if (SampleCode::CharQ(*evt, &uni)) {
    284             switch (uni) {
    285                 case '1': this->toggle(fDoFrame); return true;
    286                 case '2': this->toggle(fDoArcTo); return true;
    287                 case '3': this->toggle(fDoCorner); return true;
    288                 case '4': this->toggle(fDoConic); return true;
    289                 default: break;
    290             }
    291         }
    292         return this->INHERITED::onQuery(evt);
    293     }
    294 
    295     void makePath(SkPath* path) {
    296         path->moveTo(fPts[0]);
    297         for (int i = 1; i < N; ++i) {
    298             path->lineTo(fPts[i]);
    299         }
    300         if (!fDoFrame) {
    301             path->close();
    302         }
    303     }
    304 
    305     void onDrawContent(SkCanvas* canvas) override {
    306         canvas->drawPoints(SkCanvas::kPoints_PointMode, N, fPts, fPtsPaint);
    307 
    308         SkPath path;
    309         this->makePath(&path);
    310 
    311         if (fDoCorner) {
    312             canvas->drawPath(path, fCornerPaint);
    313         }
    314         if (fDoArcTo) {
    315             canvas->drawPath(path, fArcToPaint);
    316         }
    317 
    318         canvas->drawPath(path, fSkeletonPaint);
    319     }
    320 
    321     bool onClick(Click* click) override {
    322         int32_t index;
    323         if (click->fMeta.findS32("index", &index)) {
    324             SkASSERT((unsigned)index < N);
    325             fPts[index] = click->fCurr;
    326             this->inval(nullptr);
    327             return true;
    328         }
    329         return false;
    330     }
    331 
    332     SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
    333         const SkScalar tol = 4;
    334         const SkRect r = SkRect::MakeXYWH(x - tol, y - tol, tol * 2, tol * 2);
    335         for (int i = 0; i < N; ++i) {
    336             if (r.intersects(SkRect::MakeXYWH(fPts[i].fX, fPts[i].fY, 1, 1))) {
    337                 Click* click = new Click(this);
    338                 click->fMeta.setS32("index", i);
    339                 return click;
    340             }
    341         }
    342         return this->INHERITED::onFindClickHandler(x, y, modi);
    343     }
    344 
    345 private:
    346     typedef SampleView INHERITED;
    347 };
    348 DEF_SAMPLE( return new ArcToView; )
    349 
    350