Home | History | Annotate | Download | only in samplecode
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #include "SampleCode.h"
      8 #include "SkBlurMask.h"
      9 #include "SkCanvas.h"
     10 #include "SkView.h"
     11 #include "Sk1DPathEffect.h"
     12 #include "Sk2DPathEffect.h"
     13 #include "SkBlurMaskFilter.h"
     14 #include "SkColorMatrixFilter.h"
     15 #include "SkColorPriv.h"
     16 #include "SkCornerPathEffect.h"
     17 #include "SkDashPathEffect.h"
     18 #include "SkDiscretePathEffect.h"
     19 #include "SkEmbossMaskFilter.h"
     20 #include "SkReadBuffer.h"
     21 #include "SkWriteBuffer.h"
     22 #include "SkGradientShader.h"
     23 #include "SkMath.h"
     24 #include "SkPath.h"
     25 #include "SkPictureRecorder.h"
     26 #include "SkRegion.h"
     27 #include "SkShader.h"
     28 #include "SkCornerPathEffect.h"
     29 #include "SkPathMeasure.h"
     30 #include "SkPicture.h"
     31 #include "SkRandom.h"
     32 #include "SkTypeface.h"
     33 #include "SkUtils.h"
     34 
     35 #include <math.h>
     36 #include "DecodeFile.h"
     37 
     38 class Dot2DPathEffect : public Sk2DPathEffect {
     39 public:
     40     Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
     41         : Sk2DPathEffect(matrix), fRadius(radius) {}
     42 
     43     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
     44 
     45 protected:
     46     void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
     47         dst->addCircle(loc.fX, loc.fY, fRadius);
     48     }
     49 
     50     void flatten(SkWriteBuffer& buffer) const override {
     51         this->INHERITED::flatten(buffer);
     52         buffer.writeScalar(fRadius);
     53     }
     54 
     55 private:
     56     SkScalar fRadius;
     57 
     58     typedef Sk2DPathEffect INHERITED;
     59 };
     60 
     61 class DemoView : public SampleView {
     62 public:
     63     DemoView() {}
     64 
     65 protected:
     66     // overrides from SkEventSink
     67     virtual bool onQuery(SkEvent* evt) {
     68         if (SampleCode::TitleQ(*evt)) {
     69             SampleCode::TitleR(evt, "Demo");
     70             return true;
     71         }
     72         return this->INHERITED::onQuery(evt);
     73     }
     74 
     75     virtual bool onClick(Click* click) {
     76         return this->INHERITED::onClick(click);
     77     }
     78 
     79     void makePath(SkPath& path) {
     80         path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
     81             SkPath::kCCW_Direction);
     82         for (int index = 0; index < 10; index++) {
     83             SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f);
     84             SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f);
     85             x *= index & 1 ? 7 : 14;
     86             y *= index & 1 ? 7 : 14;
     87             x += SkIntToScalar(20);
     88             y += SkIntToScalar(20);
     89             if (index == 0)
     90                 path.moveTo(x, y);
     91             else
     92                 path.lineTo(x, y);
     93         }
     94         path.close();
     95     }
     96 
     97     virtual void onDrawContent(SkCanvas* canvas) {
     98         canvas->save();
     99         this->drawPicture(canvas, 0);
    100         canvas->restore();
    101 
    102         {
    103             SkPictureRecorder recorder;
    104             {
    105                 SkCanvas* record = recorder.beginRecording(320, 480, nullptr, 0);
    106                 this->drawPicture(record, 120);
    107             }
    108             sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    109 
    110             canvas->translate(0, SkIntToScalar(120));
    111 
    112             SkRect clip;
    113             clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
    114             do {
    115                 canvas->save();
    116                 canvas->clipRect(clip);
    117                 picture->playback(canvas);
    118                 canvas->restore();
    119                 if (clip.fRight < SkIntToScalar(320))
    120                     clip.offset(SkIntToScalar(160), 0);
    121                 else if (clip.fBottom < SkIntToScalar(480))
    122                     clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
    123                 else
    124                     break;
    125             } while (true);
    126         }
    127     }
    128 
    129     void drawPicture(SkCanvas* canvas, int spriteOffset) {
    130         SkMatrix matrix; matrix.reset();
    131         SkPaint paint;
    132         SkPath path;
    133         SkPoint start = {0, 0};
    134         SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
    135         SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
    136         SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
    137         SkScalar left = 0, top = 0, x = 0, y = 0;
    138         int index;
    139 
    140         char ascii[] = "ascii...";
    141         int asciiLength = sizeof(ascii) - 1;
    142         char utf8[] = "utf8" "\xe2\x80\xa6";
    143         short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
    144         short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
    145 
    146         makePath(path);
    147         SkTDArray<SkPoint> pos;
    148         pos.setCount(asciiLength);
    149         for (index = 0;  index < asciiLength; index++)
    150             pos[index].set(SkIntToScalar((unsigned int)index * 10),
    151                                        SkIntToScalar((unsigned int)index * 2));
    152         SkTDArray<SkPoint> pos2;
    153         pos2.setCount(asciiLength);
    154         for (index = 0;  index < asciiLength; index++)
    155             pos2[index].set(SkIntToScalar((unsigned int)index * 10),
    156                                         SkIntToScalar(20));
    157 
    158         // shaders
    159         SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
    160         SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
    161         SkScalar* linearPos = nullptr;
    162         int linearCount = 2;
    163         SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
    164         auto linear = SkGradientShader::MakeLinear(linearPoints,
    165             linearColors, linearPos, linearCount, linearMode);
    166 
    167         SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
    168         SkScalar radialRadius = SkIntToScalar(25);
    169         SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
    170         SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
    171         int radialCount = 3;
    172         SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
    173         auto radial = SkGradientShader::MakeRadial(radialCenter,
    174             radialRadius, radialColors, radialPos, radialCount,
    175             radialMode);
    176 
    177         SkEmbossMaskFilter::Light light;
    178         light.fDirection[0] = SK_Scalar1/2;
    179         light.fDirection[1] = SK_Scalar1/2;
    180         light.fDirection[2] = SK_Scalar1/3;
    181         light.fAmbient        = 0x48;
    182         light.fSpecular        = 0x80;
    183 
    184         auto lightingFilter = SkColorMatrixFilter::MakeLightingFilter(
    185             0xff89bc45, 0xff112233);
    186 
    187         canvas->save();
    188         canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
    189         paint.setAntiAlias(true);
    190         paint.setFilterQuality(kLow_SkFilterQuality);
    191         // !!! draw through a clip
    192         paint.setColor(SK_ColorLTGRAY);
    193         paint.setStyle(SkPaint::kFill_Style);
    194         SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
    195         canvas->clipRect(clip);
    196         paint.setShader(SkShader::MakeBitmapShader(fTx,
    197             SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode));
    198         canvas->drawPaint(paint);
    199         canvas->save();
    200 
    201         // line (exercises xfermode, colorShader, colorFilter, filterShader)
    202         paint.setColor(SK_ColorGREEN);
    203         paint.setStrokeWidth(SkIntToScalar(10));
    204         paint.setStyle(SkPaint::kStroke_Style);
    205         paint.setBlendMode(SkBlendMode::kXor);
    206         paint.setColorFilter(lightingFilter);
    207         canvas->drawLine(start, stop, paint); // should not be green
    208         paint.setBlendMode(SkBlendMode::kSrcOver);
    209         paint.setColorFilter(nullptr);
    210 
    211         // rectangle
    212         paint.setStyle(SkPaint::kFill_Style);
    213         canvas->translate(SkIntToScalar(50), 0);
    214         paint.setColor(SK_ColorYELLOW);
    215         paint.setShader(linear);
    216         paint.setPathEffect(pathEffectTest());
    217         canvas->drawRect(rect, paint);
    218         paint.setPathEffect(nullptr);
    219 
    220         // circle w/ emboss & transparent (exercises 3dshader)
    221         canvas->translate(SkIntToScalar(50), 0);
    222         paint.setMaskFilter(SkEmbossMaskFilter::Make(
    223                                      SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5), light));
    224         canvas->drawOval(rect, paint);
    225         canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
    226 //        paint.setShader(transparentShader)->unref();
    227         canvas->drawOval(rect, paint);
    228         canvas->translate(0, SkIntToScalar(-10));
    229 
    230         // path
    231         canvas->translate(SkIntToScalar(50), 0);
    232         paint.setColor(SK_ColorRED);
    233         paint.setStyle(SkPaint::kStroke_Style);
    234         paint.setStrokeWidth(SkIntToScalar(5));
    235         paint.setShader(radial);
    236         paint.setMaskFilter(nullptr);
    237         canvas->drawPath(path, paint);
    238 
    239         paint.setShader(nullptr);
    240         // bitmap
    241         canvas->translate(SkIntToScalar(50), 0);
    242         paint.setStyle(SkPaint::kFill_Style);
    243         canvas->drawBitmap(fBug, left, top, &paint);
    244 
    245         canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
    246         paint.setShader(shaderTest()); // test compose shader
    247         canvas->drawRect(rect2, paint);
    248         paint.setShader(nullptr);
    249 
    250         canvas->restore();
    251         // text
    252         canvas->translate(0, SkIntToScalar(60));
    253         canvas->save();
    254         paint.setColor(SK_ColorGRAY);
    255         canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
    256         canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
    257 
    258         canvas->translate(SkIntToScalar(50), 0);
    259         paint.setColor(SK_ColorCYAN);
    260         canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
    261 
    262         canvas->translate(SkIntToScalar(30), 0);
    263         paint.setColor(SK_ColorMAGENTA);
    264         paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    265         matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
    266         canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
    267         canvas->translate(0, SkIntToScalar(20));
    268         canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
    269         canvas->restore();
    270 
    271         canvas->translate(0, SkIntToScalar(60));
    272         paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
    273         canvas->restore();
    274     }
    275 
    276     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
    277         fClickPt.set(x, y);
    278         return this->INHERITED::onFindClickHandler(x, y, modi);
    279     }
    280 
    281     sk_sp<SkPathEffect> pathEffectTest() {
    282         static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
    283         SkScalar gPhase = 0;
    284         SkPath path;
    285         path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    286         for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
    287             path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    288         path.close();
    289         path.offset(SkIntToScalar(-6), 0);
    290         auto outer = SkPath1DPathEffect::Make(path, SkIntToScalar(12),
    291             gPhase, SkPath1DPathEffect::kRotate_Style);
    292         auto inner = SkDiscretePathEffect::Make(SkIntToScalar(2),
    293             SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
    294         return SkPathEffect::MakeCompose(outer, inner);
    295     }
    296 
    297     sk_sp<SkShader> shaderTest() {
    298         SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
    299         SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
    300         auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr,
    301             2, SkShader::kClamp_TileMode);
    302         pts[1].set(0, SkIntToScalar(100));
    303         SkColor colors2[] = {SK_ColorBLACK,  SkColorSetARGB(0x80, 0, 0, 0)};
    304         auto shaderB = SkGradientShader::MakeLinear(pts, colors2, nullptr,
    305             2, SkShader::kClamp_TileMode);
    306         return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB),
    307                                            SkBlendMode::kDstIn);
    308     }
    309 
    310     virtual void startTest() {
    311         decode_file("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
    312         decode_file("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
    313         decode_file("/Users/caryclark/Desktop/05psp04.gif", &fTx);
    314     }
    315 
    316 private:
    317     SkPoint fClickPt;
    318     SkBitmap fBug, fTb, fTx;
    319     typedef SampleView INHERITED;
    320 };
    321 
    322 //////////////////////////////////////////////////////////////////////////////
    323 
    324 static SkView* MyFactory() { return new DemoView; }
    325 static SkViewRegister reg(MyFactory);
    326