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