1
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 */
8#include "SkMeshUtils.h"
9#include "SkCanvas.h"
10#include "SkPaint.h"
11
12SkMeshIndices::SkMeshIndices() {
13    sk_bzero(this, sizeof(*this));
14}
15
16SkMeshIndices::~SkMeshIndices() {
17    sk_free(fStorage);
18}
19
20bool SkMeshIndices::init(SkPoint tex[], uint16_t indices[],
21                         int texW, int texH, int rows, int cols) {
22    if (rows < 2 || cols < 2) {
23        sk_free(fStorage);
24        fStorage = NULL;
25        fTex = NULL;
26        fIndices = NULL;
27        fTexCount = fIndexCount = 0;
28        return false;
29    }
30
31    sk_free(fStorage);
32    fStorage = NULL;
33
34    fTexCount = rows * cols;
35    rows -= 1;
36    cols -= 1;
37    fIndexCount = rows * cols * 6;
38
39    if (tex) {
40        fTex = tex;
41        fIndices = indices;
42    } else {
43        fStorage = sk_malloc_throw(fTexCount * sizeof(SkPoint) +
44                                   fIndexCount * sizeof(uint16_t));
45        fTex = (SkPoint*)fStorage;
46        fIndices = (uint16_t*)(fTex + fTexCount);
47    }
48
49    // compute the indices
50    {
51        uint16_t* idx = fIndices;
52        int index = 0;
53        for (int y = 0; y < cols; y++) {
54            for (int x = 0; x < rows; x++) {
55                *idx++ = index;
56                *idx++ = index + rows + 1;
57                *idx++ = index + 1;
58
59                *idx++ = index + 1;
60                *idx++ = index + rows + 1;
61                *idx++ = index + rows + 2;
62
63                index += 1;
64            }
65            index += 1;
66        }
67    }
68
69    // compute texture coordinates
70    {
71        SkPoint* tex = fTex;
72        const SkScalar dx = SkIntToScalar(texW) / rows;
73        const SkScalar dy = SkIntToScalar(texH) / cols;
74        for (int y = 0; y <= cols; y++) {
75            for (int x = 0; x <= rows; x++) {
76                tex->set(x*dx, y*dy);
77                tex += 1;
78            }
79        }
80    }
81    return true;
82}
83
84///////////////////////////////////////////////////////////////////////////////
85
86#include "SkShader.h"
87
88void SkMeshUtils::Draw(SkCanvas* canvas, const SkBitmap& bitmap,
89                       int rows, int cols, const SkPoint verts[],
90                       const SkColor colors[], const SkPaint& paint) {
91    SkMeshIndices idx;
92
93    if (idx.init(bitmap.width(), bitmap.height(), rows, cols)) {
94        SkPaint p(paint);
95        p.setShader(SkShader::CreateBitmapShader(bitmap,
96                                         SkShader::kClamp_TileMode,
97                                         SkShader::kClamp_TileMode))->unref();
98        canvas->drawVertices(SkCanvas::kTriangles_VertexMode,
99                             rows * cols, verts, idx.tex(), colors, NULL,
100                             idx.indices(), idx.indexCount(), p);
101    }
102}
103