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