1 /* 2 * Copyright (c) 2010, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 33 #if ENABLE(ACCELERATED_2D_CANVAS) 34 35 #include "TilingData.h" 36 37 #include "FloatRect.h" 38 #include "IntRect.h" 39 #include <algorithm> 40 41 using namespace std; 42 43 namespace WebCore { 44 45 static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels) 46 { 47 if (maxTextureSize - 2 * borderTexels <= 0) 48 return totalSize > 0 && maxTextureSize >= totalSize ? 1 : 0; 49 50 int numTiles = max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels)); 51 return totalSize > 0 ? numTiles : 0; 52 } 53 54 TilingData::TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels) 55 : m_maxTextureSize(maxTextureSize) 56 , m_totalSizeX(totalSizeX) 57 , m_totalSizeY(totalSizeY) 58 , m_borderTexels(hasBorderTexels ? 1 : 0) 59 { 60 recomputeNumTiles(); 61 } 62 63 void TilingData::setTotalSize(int totalSizeX, int totalSizeY) 64 { 65 m_totalSizeX = totalSizeX; 66 m_totalSizeY = totalSizeY; 67 recomputeNumTiles(); 68 } 69 70 void TilingData::setMaxTextureSize(int maxTextureSize) 71 { 72 m_maxTextureSize = maxTextureSize; 73 recomputeNumTiles(); 74 } 75 76 int TilingData::tileXIndexFromSrcCoord(int srcPos) const 77 { 78 int x = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); 79 return min(max(x, 0), numTilesX() - 1); 80 } 81 82 int TilingData::tileYIndexFromSrcCoord(int srcPos) const 83 { 84 int y = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels); 85 return min(max(y, 0), numTilesY() - 1); 86 } 87 88 IntRect TilingData::tileBounds(int tile) const 89 { 90 assertTile(tile); 91 int ix = tileXIndex(tile); 92 int iy = tileYIndex(tile); 93 int x = tilePositionX(ix); 94 int y = tilePositionY(iy); 95 int width = tileSizeX(ix); 96 int height = tileSizeY(iy); 97 ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0); 98 ASSERT(x <= totalSizeX() && y <= totalSizeY()); 99 return IntRect(x, y, width, height); 100 } 101 102 IntRect TilingData::tileBoundsWithBorder(int tile) const 103 { 104 IntRect bounds = tileBounds(tile); 105 106 if (m_borderTexels) { 107 int x1 = bounds.x(); 108 int x2 = bounds.maxX(); 109 int y1 = bounds.y(); 110 int y2 = bounds.maxY(); 111 112 if (tileXIndex(tile) > 0) 113 x1--; 114 if (tileXIndex(tile) < (numTilesX() - 1)) 115 x2++; 116 if (tileYIndex(tile) > 0) 117 y1--; 118 if (tileYIndex(tile) < (numTilesY() - 1)) 119 y2++; 120 121 bounds = IntRect(x1, y1, x2 - x1, y2 - y1); 122 } 123 124 return bounds; 125 } 126 127 FloatRect TilingData::tileBoundsNormalized(int tile) const 128 { 129 assertTile(tile); 130 FloatRect bounds(tileBounds(tile)); 131 bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY); 132 return bounds; 133 } 134 135 int TilingData::tilePositionX(int xIndex) const 136 { 137 ASSERT(xIndex >= 0 && xIndex < numTilesX()); 138 139 int pos = 0; 140 for (int i = 0; i < xIndex; i++) 141 pos += tileSizeX(i); 142 143 return pos; 144 } 145 146 int TilingData::tilePositionY(int yIndex) const 147 { 148 ASSERT(yIndex >= 0 && yIndex < numTilesY()); 149 150 int pos = 0; 151 for (int i = 0; i < yIndex; i++) 152 pos += tileSizeY(i); 153 154 return pos; 155 } 156 157 int TilingData::tileSizeX(int xIndex) const 158 { 159 ASSERT(xIndex >= 0 && xIndex < numTilesX()); 160 161 if (!xIndex && m_numTilesX == 1) 162 return m_totalSizeX; 163 if (!xIndex && m_numTilesX > 1) 164 return m_maxTextureSize - m_borderTexels; 165 if (xIndex < numTilesX() - 1) 166 return m_maxTextureSize - 2 * m_borderTexels; 167 if (xIndex == numTilesX() - 1) 168 return m_totalSizeX - tilePositionX(xIndex); 169 170 ASSERT_NOT_REACHED(); 171 return 0; 172 } 173 174 int TilingData::tileSizeY(int yIndex) const 175 { 176 ASSERT(yIndex >= 0 && yIndex < numTilesY()); 177 178 if (!yIndex && m_numTilesY == 1) 179 return m_totalSizeY; 180 if (!yIndex && m_numTilesY > 1) 181 return m_maxTextureSize - m_borderTexels; 182 if (yIndex < numTilesY() - 1) 183 return m_maxTextureSize - 2 * m_borderTexels; 184 if (yIndex == numTilesY() - 1) 185 return m_totalSizeY - tilePositionY(yIndex); 186 187 ASSERT_NOT_REACHED(); 188 return 0; 189 } 190 191 IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const 192 { 193 int x = tileXIndexFromSrcCoord(srcRect.x()); 194 int y = tileYIndexFromSrcCoord(srcRect.y()); 195 int r = tileXIndexFromSrcCoord(srcRect.maxX()); 196 int b = tileYIndexFromSrcCoord(srcRect.maxY()); 197 return IntRect(x, y, r - x, b - y); 198 } 199 200 IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) const 201 { 202 return overlappedTileIndices(enclosingIntRect(srcRect)); 203 } 204 205 void TilingData::intersectDrawQuad(const FloatRect& srcRect, const FloatRect& dstRect, int tile, 206 FloatRect* newSrc, FloatRect* newDst) const 207 { 208 // Intersect with tile 209 FloatRect tileBounds = this->tileBounds(tile); 210 FloatRect srcRectIntersected = srcRect; 211 srcRectIntersected.intersect(tileBounds); 212 213 if (srcRectIntersected.isEmpty()) { 214 *newSrc = *newDst = FloatRect(0, 0, 0, 0); 215 return; 216 } 217 218 float srcRectIntersectedNormX = (srcRectIntersected.x() - srcRect.x()) / srcRect.width(); 219 float srcRectIntersectedNormY = (srcRectIntersected.y() - srcRect.y()) / srcRect.height(); 220 float srcRectIntersectedNormW = srcRectIntersected.width() / srcRect.width(); 221 float srcRectIntersectedNormH = srcRectIntersected.height() / srcRect.height(); 222 223 *newSrc = srcRectIntersected; 224 newSrc->move( 225 -tileBounds.x() + ((tileXIndex(tile) > 0) ? m_borderTexels : 0), 226 -tileBounds.y() + ((tileYIndex(tile) > 0) ? m_borderTexels : 0)); 227 228 *newDst = FloatRect( 229 srcRectIntersectedNormX * dstRect.width() + dstRect.x(), 230 srcRectIntersectedNormY * dstRect.height() + dstRect.y(), 231 srcRectIntersectedNormW * dstRect.width(), 232 srcRectIntersectedNormH * dstRect.height()); 233 } 234 235 IntPoint TilingData::textureOffset(int xIndex, int yIndex) const 236 { 237 int left = (!xIndex || m_numTilesX == 1) ? 0 : m_borderTexels; 238 int top = (!yIndex || m_numTilesY == 1) ? 0 : m_borderTexels; 239 240 return IntPoint(left, top); 241 } 242 243 void TilingData::recomputeNumTiles() 244 { 245 m_numTilesX = computeNumTiles(m_maxTextureSize, m_totalSizeX, m_borderTexels); 246 m_numTilesY = computeNumTiles(m_maxTextureSize, m_totalSizeY, m_borderTexels); 247 } 248 249 } 250 251 #endif 252