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 "include/core/SkCanvas.h"
9 #include "include/core/SkFont.h"
10 #include "include/core/SkRSXform.h"
11 #include "include/core/SkSurface.h"
12 #include "samplecode/Sample.h"
13 #include "src/core/SkPaintPriv.h"
14 #include "tools/Resources.h"
15 #include "tools/timer/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 SkSamplingOptions&, const SkPaint*);
25
draw_atlas(SkCanvas * canvas,SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,const SkRect * cull,const SkSamplingOptions & sampling,const SkPaint * paint)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 SkSamplingOptions& sampling, const SkPaint* paint) {
29 canvas->drawAtlas(atlas, xform, tex, colors, count, SkBlendMode::kModulate, sampling,
30 cull, paint);
31 }
32
draw_atlas_sim(SkCanvas * canvas,SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,const SkRect * cull,const SkSamplingOptions & sampling,const SkPaint * paint)33 static void draw_atlas_sim(SkCanvas* canvas, SkImage* atlas, const SkRSXform xform[],
34 const SkRect tex[], const SkColor colors[], int count, const SkRect* cull,
35 const SkSamplingOptions& sampling, const SkPaint* paint) {
36 for (int i = 0; i < count; ++i) {
37 SkMatrix matrix;
38 matrix.setRSXform(xform[i]);
39
40 canvas->save();
41 canvas->concat(matrix);
42 canvas->drawImageRect(atlas, tex[i], tex[i].makeOffset(-tex[i].x(), -tex[i].y()),
43 sampling, paint, SkCanvas::kFast_SrcRectConstraint);
44 canvas->restore();
45 }
46 }
47
48
49 class DrawShipView : public Sample {
50 public:
DrawShipView(const char name[],DrawAtlasProc proc)51 DrawShipView(const char name[], DrawAtlasProc proc) : fName(name), fProc(proc) {
52 fAtlas = GetResourceAsImage("images/ship.png");
53 if (!fAtlas) {
54 SkDebugf("\nCould not decode file ship.png. Falling back to penguin mode.\n");
55 fAtlas = GetResourceAsImage("images/baby_tux.png");
56 if (!fAtlas) {
57 SkDebugf("\nCould not decode file baby_tux.png. Did you forget"
58 " to set the resourcePath?\n");
59 return;
60 }
61 }
62
63 SkScalar anchorX = fAtlas->width()*0.5f;
64 SkScalar anchorY = fAtlas->height()*0.5f;
65 int currIndex = 0;
66 for (int x = 0; x < kGrid; x++) {
67 for (int y = 0; y < kGrid; y++) {
68 float xPos = (x / (kGrid - 1.0f)) * kWidth;
69 float yPos = (y / (kGrid - 1.0f)) * kWidth;
70
71 fTex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f,
72 SkIntToScalar(fAtlas->width()),
73 SkIntToScalar(fAtlas->height()));
74 fXform[currIndex] = SkRSXform::MakeFromRadians(0.1f, SK_ScalarPI*0.5f,
75 xPos, yPos, anchorX, anchorY);
76 currIndex++;
77 }
78 }
79 fTex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f,
80 SkIntToScalar(fAtlas->width()),
81 SkIntToScalar(fAtlas->height()));
82 fXform[currIndex] = SkRSXform::MakeFromRadians(0.5f, SK_ScalarPI*0.5f,
83 kWidth*0.5f, kHeight*0.5f, anchorX, anchorY);
84
85 }
86
~DrawShipView()87 ~DrawShipView() override {}
88
89 protected:
name()90 SkString name() override { return SkString(fName); }
91
onDrawContent(SkCanvas * canvas)92 void onDrawContent(SkCanvas* canvas) override {
93 const float kCosDiff = 0.99984769515f;
94 const float kSinDiff = 0.01745240643f;
95
96 if (!fAtlas) {
97 return;
98 }
99
100 SkPaint paint;
101 paint.setColor(SK_ColorWHITE);
102
103 SkScalar anchorX = fAtlas->width()*0.5f;
104 SkScalar anchorY = fAtlas->height()*0.5f;
105 for (int i = 0; i < kGrid*kGrid+1; ++i) {
106 SkScalar c = fXform[i].fSCos;
107 SkScalar s = fXform[i].fSSin;
108
109 SkScalar dx = c*anchorX - s*anchorY;
110 SkScalar dy = s*anchorX + c*anchorY;
111
112 fXform[i].fSCos = kCosDiff*c - kSinDiff*s;
113 fXform[i].fSSin = kSinDiff*c + kCosDiff*s;
114
115 dx -= fXform[i].fSCos*anchorX - fXform[i].fSSin*anchorY;
116 dy -= fXform[i].fSSin*anchorX + fXform[i].fSCos*anchorY;
117 fXform[i].fTx += dx;
118 fXform[i].fTy += dy;
119 }
120
121 fProc(canvas, fAtlas.get(), fXform, fTex, nullptr, kGrid*kGrid+1, nullptr,
122 SkSamplingOptions(SkFilterMode::kLinear), &paint);
123 }
124
onAnimate(double nanos)125 bool onAnimate(double nanos) override {
126 //TODO: use nanos
127 //SkScalar angle = SkDoubleToScalar(fmod(1e-9 * nanos * 360 / 24, 360));
128 //fAnimatingDrawable->setSweep(angle);
129 return true;
130 }
131
132 private:
133 const char* fName;
134 DrawAtlasProc fProc;
135
136 sk_sp<SkImage> fAtlas;
137 SkRSXform fXform[kGrid*kGrid+1];
138 SkRect fTex[kGrid*kGrid+1];
139
140 using INHERITED = Sample;
141 };
142
143 //////////////////////////////////////////////////////////////////////////////
144
145 DEF_SAMPLE( return new DrawShipView("DrawShip", draw_atlas); )
146 DEF_SAMPLE( return new DrawShipView("DrawShipSim", draw_atlas_sim); )
147