Home | History | Annotate | Download | only in samplecode
      1 /*
      2  * Copyright 2015 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 
      8 #include "SampleCode.h"
      9 #include "Resources.h"
     10 #include "SkAnimTimer.h"
     11 #include "SkView.h"
     12 #include "SkCanvas.h"
     13 #include "SkRSXform.h"
     14 #include "SkSurface.h"
     15 #include "Timer.h"
     16 
     17 #include <stdio.h>
     18 
     19 static const int kGrid = 100;
     20 static const int kWidth = 960;
     21 static const int kHeight = 640;
     22 
     23 typedef void (*DrawAtlasProc)(SkCanvas*, SkImage*, const SkRSXform[], const SkRect[],
     24 const SkColor[], int, const SkRect*, const SkPaint*);
     25 
     26 static void draw_atlas(SkCanvas* canvas, SkImage* atlas, const SkRSXform xform[],
     27                        const SkRect tex[], const SkColor colors[], int count, const SkRect* cull,
     28                        const SkPaint* paint) {
     29     canvas->drawAtlas(atlas, xform, tex, colors, count, SkBlendMode::kModulate, cull, paint);
     30 }
     31 
     32 static void draw_atlas_sim(SkCanvas* canvas, SkImage* atlas, const SkRSXform xform[],
     33                            const SkRect tex[], const SkColor colors[], int count, const SkRect* cull,
     34                            const SkPaint* paint) {
     35     for (int i = 0; i < count; ++i) {
     36         SkMatrix matrix;
     37         matrix.setRSXform(xform[i]);
     38 
     39         canvas->save();
     40         canvas->concat(matrix);
     41         canvas->drawImageRect(atlas, tex[i], tex[i].makeOffset(-tex[i].x(), -tex[i].y()), paint,
     42                               SkCanvas::kFast_SrcRectConstraint);
     43         canvas->restore();
     44     }
     45 }
     46 
     47 
     48 class DrawShipView : public SampleView {
     49 public:
     50     DrawShipView(const char name[], DrawAtlasProc proc) : fName(name), fProc(proc) {
     51         fAtlas = GetResourceAsImage("images/ship.png");
     52         if (!fAtlas) {
     53             SkDebugf("\nCould not decode file ship.png. Falling back to penguin mode.\n");
     54             fAtlas = GetResourceAsImage("images/baby_tux.png");
     55             if (!fAtlas) {
     56                 SkDebugf("\nCould not decode file baby_tux.png. Did you forget"
     57                          " to set the resourcePath?\n");
     58                 return;
     59             }
     60         }
     61 
     62         SkScalar anchorX = fAtlas->width()*0.5f;
     63         SkScalar anchorY = fAtlas->height()*0.5f;
     64         int currIndex = 0;
     65         for (int x = 0; x < kGrid; x++) {
     66             for (int y = 0; y < kGrid; y++) {
     67                 float xPos = (x / (kGrid - 1.0f)) * kWidth;
     68                 float yPos = (y / (kGrid - 1.0f)) * kWidth;
     69 
     70                 fTex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f,
     71                                                    SkIntToScalar(fAtlas->width()),
     72                                                    SkIntToScalar(fAtlas->height()));
     73                 fXform[currIndex] = SkRSXform::MakeFromRadians(0.1f, SK_ScalarPI*0.5f,
     74                                                                xPos, yPos, anchorX, anchorY);
     75                 currIndex++;
     76             }
     77         }
     78         fTex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f,
     79                                            SkIntToScalar(fAtlas->width()),
     80                                            SkIntToScalar(fAtlas->height()));
     81         fXform[currIndex] = SkRSXform::MakeFromRadians(0.5f, SK_ScalarPI*0.5f,
     82                                                        kWidth*0.5f, kHeight*0.5f, anchorX, anchorY);
     83 
     84         fCurrentTime = 0;
     85         fTimer.start();
     86     }
     87 
     88     ~DrawShipView() override {}
     89 
     90 protected:
     91     // overrides from SkEventSink
     92     bool onQuery(SkEvent* evt) override {
     93         if (SampleCode::TitleQ(*evt)) {
     94             SampleCode::TitleR(evt, fName);
     95             return true;
     96         }
     97         return this->INHERITED::onQuery(evt);
     98     }
     99 
    100     void onDrawContent(SkCanvas* canvas) override {
    101         const float kCosDiff = 0.99984769515f;
    102         const float kSinDiff = 0.01745240643f;
    103 
    104         if (!fAtlas) {
    105             return;
    106         }
    107 
    108         SkPaint paint;
    109         paint.setFilterQuality(kLow_SkFilterQuality);
    110         paint.setColor(SK_ColorWHITE);
    111         paint.setTextSize(15.0f);
    112 
    113         fTimer.end();
    114 
    115         fTimes[fCurrentTime] = (float)(fTimer.fWall);
    116         fCurrentTime = (fCurrentTime + 1) & 0x1f;
    117 
    118         float meanTime = 0.0f;
    119         for (int i = 0; i < 32; ++i) {
    120             meanTime += fTimes[i];
    121         }
    122         meanTime /= 32.f;
    123         SkString outString("fps: ");
    124         SkScalar fps = 1000.f/meanTime;
    125         outString.appendScalar(fps);
    126         outString.append(" ms: ");
    127         outString.appendScalar(meanTime);
    128 
    129         fTimer.start();
    130 
    131         SkScalar anchorX = fAtlas->width()*0.5f;
    132         SkScalar anchorY = fAtlas->height()*0.5f;
    133         for (int i = 0; i < kGrid*kGrid+1; ++i) {
    134             SkScalar c = fXform[i].fSCos;
    135             SkScalar s = fXform[i].fSSin;
    136 
    137             SkScalar dx = c*anchorX - s*anchorY;
    138             SkScalar dy = s*anchorX + c*anchorY;
    139 
    140             fXform[i].fSCos = kCosDiff*c - kSinDiff*s;
    141             fXform[i].fSSin = kSinDiff*c + kCosDiff*s;
    142 
    143             dx -= fXform[i].fSCos*anchorX - fXform[i].fSSin*anchorY;
    144             dy -= fXform[i].fSSin*anchorX + fXform[i].fSCos*anchorY;
    145             fXform[i].fTx += dx;
    146             fXform[i].fTy += dy;
    147         }
    148 
    149         fProc(canvas, fAtlas.get(), fXform, fTex, nullptr, kGrid*kGrid+1, nullptr, &paint);
    150         paint.setColor(SK_ColorBLACK);
    151         canvas->drawRect(SkRect::MakeXYWH(0, 0, 200, 24), paint);
    152         paint.setColor(SK_ColorWHITE);
    153         canvas->drawString(outString, 5, 15, paint);
    154     }
    155 
    156 #if 0
    157     // TODO: switch over to use this for our animation
    158     bool onAnimate(const SkAnimTimer& timer) override {
    159         SkScalar angle = SkDoubleToScalar(fmod(timer.secs() * 360 / 24, 360));
    160         fAnimatingDrawable->setSweep(angle);
    161         return true;
    162     }
    163 #endif
    164 
    165 private:
    166     const char*         fName;
    167     DrawAtlasProc       fProc;
    168 
    169     sk_sp<SkImage> fAtlas;
    170     SkRSXform   fXform[kGrid*kGrid+1];
    171     SkRect      fTex[kGrid*kGrid+1];
    172     WallTimer   fTimer;
    173     float       fTimes[32];
    174     int         fCurrentTime;
    175 
    176 
    177     typedef SampleView INHERITED;
    178 };
    179 
    180 //////////////////////////////////////////////////////////////////////////////
    181 
    182 DEF_SAMPLE( return new DrawShipView("DrawShip", draw_atlas); )
    183 DEF_SAMPLE( return new DrawShipView("DrawShipSim", draw_atlas_sim); )
    184