Patch.cpp revision fb5e23c327cd5f8f93d1eaa7c10f34d6fd3efb6c
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
19#include <cstring>
20
21#include <utils/Log.h>
22
23#include "Patch.h"
24
25namespace android {
26namespace uirenderer {
27
28///////////////////////////////////////////////////////////////////////////////
29// Constructors/destructor
30///////////////////////////////////////////////////////////////////////////////
31
32Patch::Patch(const uint32_t xCount, const uint32_t yCount):
33        xCount(xCount + 2), yCount(yCount + 2) {
34    verticesCount = (xCount + 2) * (yCount + 2);
35    vertices = new TextureVertex[verticesCount];
36
37    // 2 triangles per patch, 3 vertices per triangle
38    indicesCount = (xCount + 1) * (yCount + 1) * 2 * 3;
39    indices = new uint16_t[indicesCount];
40
41    const uint32_t xNum = xCount + 1;
42    const uint32_t yNum = yCount + 1;
43
44    uint16_t* startIndices = indices;
45    uint32_t n = 0;
46    for (uint32_t y = 0; y < yNum; y++) {
47        for (uint32_t x = 0; x < xNum; x++) {
48            *startIndices++ = n;
49            *startIndices++ = n + 1;
50            *startIndices++ = n + xNum + 2;
51
52            *startIndices++ = n;
53            *startIndices++ = n + xNum + 2;
54            *startIndices++ = n + xNum + 1;
55
56            n += 1;
57        }
58        n += 1;
59    }
60}
61
62Patch::~Patch() {
63    delete indices;
64    delete vertices;
65}
66
67///////////////////////////////////////////////////////////////////////////////
68// Vertices management
69///////////////////////////////////////////////////////////////////////////////
70
71void Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float right,
72        float bottom, const int32_t* xDivs,  const int32_t* yDivs, const uint32_t width,
73        const uint32_t height) {
74    const uint32_t xStretchCount = (width + 1) >> 1;
75    const uint32_t yStretchCount = (height + 1) >> 1;
76
77    float xStretch = 0;
78    float yStretch = 0;
79    float xStretchTex = 0;
80    float yStretchTex = 0;
81
82    const float meshWidth = right - left;
83
84    const float bitmapWidth = float(bitmap->width());
85    const float bitmapHeight = float(bitmap->height());
86
87    if (xStretchCount > 0) {
88        uint32_t stretchSize = 0;
89        for (uint32_t i = 1; i < width; i += 2) {
90            stretchSize += xDivs[i] - xDivs[i - 1];
91        }
92        xStretchTex = (stretchSize / bitmapWidth) / xStretchCount;
93        const float fixed = bitmapWidth - stretchSize;
94        xStretch = (right - left - fixed) / xStretchCount;
95    }
96
97    if (yStretchCount > 0) {
98        uint32_t stretchSize = 0;
99        for (uint32_t i = 1; i < height; i += 2) {
100            stretchSize += yDivs[i] - yDivs[i - 1];
101        }
102        yStretchTex = (stretchSize / bitmapHeight) / yStretchCount;
103        const float fixed = bitmapHeight - stretchSize;
104        yStretch = (bottom - top - fixed) / yStretchCount;
105    }
106
107    float vy = 0.0f;
108    float ty = 0.0f;
109    TextureVertex* vertex = vertices;
110
111    generateVertices(vertex, 0.0f, 0.0f, xDivs, width, xStretch, xStretchTex,
112            meshWidth, bitmapWidth);
113    vertex += width + 2;
114
115    for (uint32_t y = 0; y < height; y++) {
116        if (y & 1) {
117            vy += yStretch;
118            ty += yStretchTex;
119        } else {
120            const float step = float(yDivs[y]);
121            vy += step;
122            ty += step / bitmapHeight;
123        }
124        generateVertices(vertex, vy, ty, xDivs, width, xStretch, xStretchTex,
125                meshWidth, bitmapWidth);
126        vertex += width + 2;
127    }
128
129    generateVertices(vertex, bottom - top, 1.0f, xDivs, width, xStretch, xStretchTex,
130            meshWidth, bitmapWidth);
131}
132
133inline void Patch::generateVertices(TextureVertex* vertex, float y, float v,
134        const int32_t xDivs[], uint32_t xCount, float xStretch, float xStretchTex,
135        float width, float widthTex) {
136    float vx = 0.0f;
137    float tx = 0.0f;
138
139    TextureVertex::set(vertex, vx, y, tx, v);
140    vertex++;
141
142    for (uint32_t x = 0; x < xCount; x++) {
143        if (x & 1) {
144            vx += xStretch;
145            tx += xStretchTex;
146        } else {
147            const float step = float(xDivs[x]);
148            vx += step;
149            tx += step / widthTex;
150        }
151
152        TextureVertex::set(vertex, vx, y, tx, v);
153        vertex++;
154    }
155
156    TextureVertex::set(vertex, width, y, 1.0f, v);
157    vertex++;
158}
159
160///////////////////////////////////////////////////////////////////////////////
161// Debug tools
162///////////////////////////////////////////////////////////////////////////////
163
164void Patch::dump() {
165    LOGD("Vertices [");
166    for (uint32_t y = 0; y < yCount; y++) {
167        char buffer[512];
168        buffer[0] = '\0';
169        uint32_t offset = 0;
170        for (uint32_t x = 0; x < xCount; x++) {
171            TextureVertex* v = &vertices[y * xCount + x];
172            offset += sprintf(&buffer[offset], " (%.4f,%.4f)-(%.4f,%.4f)",
173                    v->position[0], v->position[1], v->texture[0], v->texture[1]);
174        }
175        LOGD("  [%s ]", buffer);
176    }
177    LOGD("]\nIndices [ ");
178    char buffer[4096];
179    buffer[0] = '\0';
180    uint32_t offset = 0;
181    for (uint32_t i = 0; i < indicesCount; i++) {
182        offset += sprintf(&buffer[offset], "%d ", indices[i]);
183    }
184    LOGD("  %s\n]", buffer);
185}
186
187}; // namespace uirenderer
188}; // namespace android
189