| |
| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #include "GrMesh.h" |
| #include "SkCanvas.h" |
| |
| GrMesh::GrMesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {} |
| |
| GrMesh::~GrMesh() { |
| delete[] fPts; |
| delete[] fIndices; |
| } |
| |
| GrMesh& GrMesh::operator=(const GrMesh& src) { |
| delete[] fPts; |
| delete[] fIndices; |
| |
| fBounds = src.fBounds; |
| fRows = src.fRows; |
| fCols = src.fCols; |
| |
| fCount = src.fCount; |
| fPts = new SkPoint[fCount * 2]; |
| fTex = fPts + fCount; |
| memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint)); |
| |
| delete[] fIndices; |
| fIndexCount = src.fIndexCount; |
| fIndices = new uint16_t[fIndexCount]; |
| memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t)); |
| |
| return *this; |
| } |
| |
| void GrMesh::init(const SkRect& bounds, int rows, int cols, |
| const SkRect& texture) { |
| SkASSERT(rows > 0 && cols > 0); |
| |
| fBounds = bounds; |
| fRows = rows; |
| fCols = cols; |
| |
| delete[] fPts; |
| fCount = (rows + 1) * (cols + 1); |
| fPts = new SkPoint[fCount * 2]; |
| fTex = fPts + fCount; |
| |
| delete[] fIndices; |
| fIndexCount = rows * cols * 6; |
| fIndices = new uint16_t[fIndexCount]; |
| |
| SkPoint* pts = fPts; |
| const SkScalar dx = bounds.width() / rows; |
| const SkScalar dy = bounds.height() / cols; |
| SkPoint* tex = fTex; |
| const SkScalar dtx = texture.width() / rows; |
| const SkScalar dty = texture.height() / cols; |
| uint16_t* idx = fIndices; |
| int index = 0; |
| for (int y = 0; y <= cols; y++) { |
| for (int x = 0; x <= rows; x++) { |
| pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy); |
| pts += 1; |
| tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty); |
| tex += 1; |
| |
| if (y < cols && x < rows) { |
| *idx++ = index; |
| *idx++ = index + rows + 1; |
| *idx++ = index + 1; |
| |
| *idx++ = index + 1; |
| *idx++ = index + rows + 1; |
| *idx++ = index + rows + 2; |
| |
| index += 1; |
| } |
| } |
| index += 1; |
| } |
| } |
| |
| void GrMesh::draw(SkCanvas* canvas, const SkPaint& paint) { |
| canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount, |
| fPts, fTex, NULL, NULL, fIndices, fIndexCount, |
| paint); |
| } |
| |
| ///////////////////////////////////////////// |
| |
| #include "SkBoundaryPatch.h" |
| #include "SkMeshUtils.h" |
| |
| static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) { |
| return SkPoint::Make(SkScalarInterp(a.fX, b.fX, t), |
| SkScalarInterp(a.fY, b.fY, t)); |
| } |
| |
| static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0, |
| SkScalar x3, SkScalar y3, SkScalar scale = 1) { |
| SkPoint tmp, tmp2; |
| |
| pts[0].set(x0, y0); |
| pts[3].set(x3, y3); |
| |
| tmp = SkPointInterp(pts[0], pts[3], SK_Scalar1/3); |
| tmp2 = pts[0] - tmp; |
| tmp2.rotateCW(); |
| tmp2.scale(scale); |
| pts[1] = tmp + tmp2; |
| |
| tmp = SkPointInterp(pts[0], pts[3], 2*SK_Scalar1/3); |
| tmp2 = pts[3] - tmp; |
| tmp2.rotateCW(); |
| tmp2.scale(scale); |
| pts[2] = tmp + tmp2; |
| } |
| |
| void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) { |
| const float w = bm.width(); |
| const float h = bm.height(); |
| SkCubicBoundary cubic; |
| set_cubic(cubic.fPts + 0, 0, 0, w, 0, scale); |
| set_cubic(cubic.fPts + 3, w, 0, w, h, scale); |
| set_cubic(cubic.fPts + 6, w, h, 0, h, -scale); |
| set_cubic(cubic.fPts + 9, 0, h, 0, 0, scale); |
| |
| SkBoundaryPatch patch; |
| patch.setBoundary(&cubic); |
| |
| const int Rows = 16; |
| const int Cols = 16; |
| SkPoint pts[Rows * Cols]; |
| patch.evalPatch(pts, Rows, Cols); |
| |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setFilterBitmap(true); |
| |
| SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint); |
| } |
| |
| |