blob: bd79005762d78989692ef501c0da197b75b69df1 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001#include "GrMesh.h"
2#include "SkCanvas.h"
3
4GrMesh::GrMesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {}
5
6GrMesh::~GrMesh() {
7 delete[] fPts;
8 delete[] fIndices;
9}
10
11GrMesh& GrMesh::operator=(const GrMesh& src) {
12 delete[] fPts;
13 delete[] fIndices;
14
15 fBounds = src.fBounds;
16 fRows = src.fRows;
17 fCols = src.fCols;
18
19 fCount = src.fCount;
20 fPts = new SkPoint[fCount * 2];
21 fTex = fPts + fCount;
22 memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint));
23
24 delete[] fIndices;
25 fIndexCount = src.fIndexCount;
26 fIndices = new uint16_t[fIndexCount];
27 memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t));
28
29 return *this;
30}
31
32void GrMesh::init(const SkRect& bounds, int rows, int cols,
33 const SkRect& texture) {
34 SkASSERT(rows > 0 && cols > 0);
35
36 fBounds = bounds;
37 fRows = rows;
38 fCols = cols;
39
40 delete[] fPts;
41 fCount = (rows + 1) * (cols + 1);
42 fPts = new SkPoint[fCount * 2];
43 fTex = fPts + fCount;
44
45 delete[] fIndices;
46 fIndexCount = rows * cols * 6;
47 fIndices = new uint16_t[fIndexCount];
48
49 SkPoint* pts = fPts;
50 const SkScalar dx = bounds.width() / rows;
51 const SkScalar dy = bounds.height() / cols;
52 SkPoint* tex = fTex;
53 const SkScalar dtx = texture.width() / rows;
54 const SkScalar dty = texture.height() / cols;
55 uint16_t* idx = fIndices;
56 int index = 0;
57 for (int y = 0; y <= cols; y++) {
58 for (int x = 0; x <= rows; x++) {
59 pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy);
60 pts += 1;
61 tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty);
62 tex += 1;
63
64 if (y < cols && x < rows) {
65 *idx++ = index;
66 *idx++ = index + rows + 1;
67 *idx++ = index + 1;
68
69 *idx++ = index + 1;
70 *idx++ = index + rows + 1;
71 *idx++ = index + rows + 2;
72
73 index += 1;
74 }
75 }
76 index += 1;
77 }
78}
79
80void GrMesh::draw(SkCanvas* canvas, const SkPaint& paint) {
81 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
82 fPts, fTex, NULL, NULL, fIndices, fIndexCount,
83 paint);
84}
85
86/////////////////////////////////////////////
87
88#include "SkBoundaryPatch.h"
89#include "SkMeshUtils.h"
90
91static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) {
92 return SkPoint::Make(SkScalarInterp(a.fX, b.fX, t),
93 SkScalarInterp(a.fY, b.fY, t));
94}
95
96static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0,
97 SkScalar x3, SkScalar y3, SkScalar scale = 1) {
98 SkPoint tmp, tmp2;
99
100 pts[0].set(x0, y0);
101 pts[3].set(x3, y3);
102
103 tmp = SkPointInterp(pts[0], pts[3], SK_Scalar1/3);
104 tmp2 = pts[0] - tmp;
105 tmp2.rotateCW();
106 tmp2.scale(scale);
107 pts[1] = tmp + tmp2;
108
109 tmp = SkPointInterp(pts[0], pts[3], 2*SK_Scalar1/3);
110 tmp2 = pts[3] - tmp;
111 tmp2.rotateCW();
112 tmp2.scale(scale);
113 pts[2] = tmp + tmp2;
114}
115
116void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) {
117 const float w = bm.width();
118 const float h = bm.height();
119 SkCubicBoundary cubic;
120 set_cubic(cubic.fPts + 0, 0, 0, w, 0, scale);
121 set_cubic(cubic.fPts + 3, w, 0, w, h, scale);
122 set_cubic(cubic.fPts + 6, w, h, 0, h, -scale);
123 set_cubic(cubic.fPts + 9, 0, h, 0, 0, scale);
124
125 SkBoundaryPatch patch;
126 patch.setBoundary(&cubic);
127
128 const int Rows = 16;
129 const int Cols = 16;
130 SkPoint pts[Rows * Cols];
131 patch.evalPatch(pts, Rows, Cols);
132
133 SkPaint paint;
134 paint.setAntiAlias(true);
135 paint.setFilterBitmap(true);
136
137 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
138}
139
140