blob: 5e189099be402553b3839a0f8d38f2694c3d156c [file] [log] [blame]
reed@android.comd2abab62009-10-20 21:27:15 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGradientShader.h"
5#include "SkPath.h"
6#include "SkRegion.h"
7#include "SkShader.h"
8#include "SkUtils.h"
9#include "SkImageDecoder.h"
10
11class Mesh {
12public:
13 Mesh();
14 ~Mesh();
15
16 Mesh& operator=(const Mesh& src);
17
18 void init(const SkRect& bounds, int rows, int cols,
19 const SkRect& texture);
20
21 int rows() const { return fRows; }
22 int cols() const { return fCols; }
23 SkPoint& pt(int row, int col) {
24 return fPts[row * (fRows + 1) + col];
25 }
26
27 void draw(SkCanvas*, const SkPaint&);
28 void drawWireframe(SkCanvas* canvas, const SkPaint& paint);
29
30private:
31 int fRows, fCols;
32 SkPoint* fPts;
33 SkPoint* fTex; // just points into fPts, not separately allocated
34 int fCount;
35 uint16_t* fIndices;
36 int fIndexCount;
37};
38
39Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {}
40
41Mesh::~Mesh() {
42 delete[] fPts;
43 delete[] fIndices;
44}
45
46Mesh& Mesh::operator=(const Mesh& src) {
47 delete[] fPts;
48 delete[] fIndices;
49
50 fRows = src.fRows;
51 fCols = src.fCols;
52
53 fCount = src.fCount;
54 fPts = new SkPoint[fCount * 2];
55 fTex = fPts + fCount;
56 memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint));
57
58 delete[] fIndices;
59 fIndexCount = src.fIndexCount;
60 fIndices = new uint16_t[fIndexCount];
61 memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t));
62
63 return *this;
64}
65
66void Mesh::init(const SkRect& bounds, int rows, int cols,
67 const SkRect& texture) {
68 SkASSERT(rows > 0 && cols > 0);
69
70 fRows = rows;
71 fCols = cols;
72
73 delete[] fPts;
74 fCount = (rows + 1) * (cols + 1);
75 fPts = new SkPoint[fCount * 2];
76 fTex = fPts + fCount;
77
78 delete[] fIndices;
79 fIndexCount = rows * cols * 6;
80 fIndices = new uint16_t[fIndexCount];
81
82 SkPoint* pts = fPts;
83 const SkScalar dx = bounds.width() / rows;
84 const SkScalar dy = bounds.height() / cols;
85 SkPoint* tex = fTex;
86 const SkScalar dtx = texture.width() / rows;
87 const SkScalar dty = texture.height() / cols;
88 uint16_t* idx = fIndices;
89 int index = 0;
90 for (int y = 0; y <= cols; y++) {
91 for (int x = 0; x <= rows; x++) {
92 pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy);
93 pts += 1;
94 tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty);
95 tex += 1;
96
97 if (y < cols && x < rows) {
98 *idx++ = index;
99 *idx++ = index + rows + 1;
100 *idx++ = index + 1;
101
102 *idx++ = index + 1;
103 *idx++ = index + rows + 1;
104 *idx++ = index + rows + 2;
105
106 index += 1;
107 }
108 }
109 index += 1;
110 }
111}
112
113void Mesh::draw(SkCanvas* canvas, const SkPaint& paint) {
114 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
115 fPts, fTex, NULL, NULL, fIndices, fIndexCount,
116 paint);
117}
118
119void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) {
120 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
121 fPts, NULL, NULL, NULL, fIndices, fIndexCount,
122 paint);
123}
124
125///////////////////////////////////////////////////////////////////////////////
126
127class WarpView : public SkView {
128 Mesh fMesh, fOrig;
129 SkBitmap fBitmap;
130public:
131 WarpView() {
132 SkBitmap bm;
133 SkImageDecoder::DecodeFile("/skimages/nytimes.png", &bm);
134 SkIRect subset = { 0, 0, 420, 420 };
135 bm.extractSubset(&fBitmap, subset);
136
137 SkRect bounds, texture;
138 texture.set(0, 0, SkIntToScalar(fBitmap.width()),
139 SkIntToScalar(fBitmap.height()));
140 bounds = texture;
141
142// fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, texture);
143 fMesh.init(bounds, 10, 10, texture);
144 fOrig = fMesh;
145 }
146
147protected:
148 // overrides from SkEventSink
149 virtual bool onQuery(SkEvent* evt) {
150 if (SampleCode::TitleQ(*evt)) {
151 SampleCode::TitleR(evt, "Warp");
152 return true;
153 }
154 return this->INHERITED::onQuery(evt);
155 }
156
157 void warp(const SkPoint& p0, const SkPoint& p1) {
158 int rows = fMesh.rows();
159 int cols = fMesh.cols();
160
161 const SkVector delta = p1 - p0;
162 for (int y = 1; y < cols; y++) {
163 for (int x = 1; x < rows; x++) {
164 const SkPoint& orig = fOrig.pt(x, y);
165 SkScalar dist = SkPoint::Distance(p0, orig);
166 dist += SkIntToScalar(1);
167 // dist = SkScalarSqrt(dist);
168 SkScalar dx = SkScalarDiv(delta.fX, dist);
169 SkScalar dy = SkScalarDiv(delta.fY, dist);
170 fMesh.pt(x, y).set(orig.fX + dx, orig.fY + dy);
171// SkDebugf("[%g %g] -> [%d %d %g] <%g %g>\n", delta.fX, delta.fY, x, y, dist, dx, dy);
172 }
173 }
174 }
175
176 virtual void onDraw(SkCanvas* canvas) {
177 canvas->drawColor(SK_ColorGRAY);
178
179 SkPaint paint;
180 paint.setFilterBitmap(true);
181 paint.setShader(SkShader::CreateBitmapShader(fBitmap,
182 SkShader::kClamp_TileMode,
183 SkShader::kClamp_TileMode))->unref();
184 fMesh.draw(canvas, paint);
185
186 paint.setShader(NULL);
187 paint.setColor(SK_ColorRED);
188 fMesh.draw(canvas, paint);
189 }
190
191 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
192 return new Click(this);
193 }
194
195 virtual bool onClick(Click* click) {
196 this->warp(click->fOrig, click->fCurr);
197 this->inval(NULL);
198 return true;
199 }
200
201private:
202 SkIRect fBase, fRect;
203
204 typedef SkView INHERITED;
205};
206
207//////////////////////////////////////////////////////////////////////////////
208
209static SkView* MyFactory() { return new WarpView; }
210static SkViewRegister reg(MyFactory);
211