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