1 #include "GrMesh.h" 2 #include "SkCanvas.h" 3 4 GrMesh::GrMesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {} 5 6 GrMesh::~GrMesh() { 7 delete[] fPts; 8 delete[] fIndices; 9 } 10 11 GrMesh& 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 32 void 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 80 void 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 91 static 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 96 static 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 116 void 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 141