#include "config.h"
#if USE(ACCELERATED_COMPOSITING) || ENABLE(ACCELERATED_2D_CANVAS)
#include "TilingData.h"
#include "FloatRect.h"
#include "IntRect.h"
#include <algorithm>
using namespace std;
namespace WebCore {
static int computeNumTiles(int maxTextureSize, int totalSize, int borderTexels)
{
if (maxTextureSize - 2 * borderTexels <= 0)
return totalSize > 0 && maxTextureSize >= totalSize ? 1 : 0;
int numTiles = max(1, 1 + (totalSize - 1 - 2 * borderTexels) / (maxTextureSize - 2 * borderTexels));
return totalSize > 0 ? numTiles : 0;
}
TilingData::TilingData(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels)
: m_maxTextureSize(maxTextureSize)
, m_totalSizeX(totalSizeX)
, m_totalSizeY(totalSizeY)
, m_borderTexels(hasBorderTexels ? 1 : 0)
{
recomputeNumTiles();
}
void TilingData::setTotalSize(int totalSizeX, int totalSizeY)
{
m_totalSizeX = totalSizeX;
m_totalSizeY = totalSizeY;
recomputeNumTiles();
}
void TilingData::setMaxTextureSize(int maxTextureSize)
{
m_maxTextureSize = maxTextureSize;
recomputeNumTiles();
}
void TilingData::setHasBorderTexels(bool hasBorderTexels)
{
m_borderTexels = hasBorderTexels ? 1 : 0;
recomputeNumTiles();
}
int TilingData::tileXIndexFromSrcCoord(int srcPos) const
{
if (numTilesX() <= 1)
return 0;
ASSERT(m_maxTextureSize - 2 * m_borderTexels);
int x = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels);
return min(max(x, 0), numTilesX() - 1);
}
int TilingData::tileYIndexFromSrcCoord(int srcPos) const
{
if (numTilesY() <= 1)
return 0;
ASSERT(m_maxTextureSize - 2 * m_borderTexels);
int y = (srcPos - m_borderTexels) / (m_maxTextureSize - 2 * m_borderTexels);
return min(max(y, 0), numTilesY() - 1);
}
IntRect TilingData::tileBounds(int i, int j) const
{
assertTile(i, j);
int x = tilePositionX(i);
int y = tilePositionY(j);
int width = tileSizeX(i);
int height = tileSizeY(j);
ASSERT(x >= 0 && y >= 0 && width >= 0 && height >= 0);
ASSERT(x <= totalSizeX() && y <= totalSizeY());
return IntRect(x, y, width, height);
}
IntRect TilingData::tileBoundsWithBorder(int i, int j) const
{
IntRect bounds = tileBounds(i, j);
if (m_borderTexels) {
int x1 = bounds.x();
int x2 = bounds.maxX();
int y1 = bounds.y();
int y2 = bounds.maxY();
if (i > 0)
x1--;
if (i < (numTilesX() - 1))
x2++;
if (j > 0)
y1--;
if (j < (numTilesY() - 1))
y2++;
bounds = IntRect(x1, y1, x2 - x1, y2 - y1);
}
return bounds;
}
FloatRect TilingData::tileBoundsNormalized(int i, int j) const
{
assertTile(i, j);
FloatRect bounds(tileBounds(i, j));
bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY);
return bounds;
}
int TilingData::tilePositionX(int xIndex) const
{
ASSERT(xIndex >= 0 && xIndex < numTilesX());
int pos = 0;
for (int i = 0; i < xIndex; i++)
pos += tileSizeX(i);
return pos;
}
int TilingData::tilePositionY(int yIndex) const
{
ASSERT(yIndex >= 0 && yIndex < numTilesY());
int pos = 0;
for (int i = 0; i < yIndex; i++)
pos += tileSizeY(i);
return pos;
}
int TilingData::tileSizeX(int xIndex) const
{
ASSERT(xIndex >= 0 && xIndex < numTilesX());
if (!xIndex && m_numTilesX == 1)
return m_totalSizeX;
if (!xIndex && m_numTilesX > 1)
return m_maxTextureSize - m_borderTexels;
if (xIndex < numTilesX() - 1)
return m_maxTextureSize - 2 * m_borderTexels;
if (xIndex == numTilesX() - 1)
return m_totalSizeX - tilePositionX(xIndex);
ASSERT_NOT_REACHED();
return 0;
}
int TilingData::tileSizeY(int yIndex) const
{
ASSERT(yIndex >= 0 && yIndex < numTilesY());
if (!yIndex && m_numTilesY == 1)
return m_totalSizeY;
if (!yIndex && m_numTilesY > 1)
return m_maxTextureSize - m_borderTexels;
if (yIndex < numTilesY() - 1)
return m_maxTextureSize - 2 * m_borderTexels;
if (yIndex == numTilesY() - 1)
return m_totalSizeY - tilePositionY(yIndex);
ASSERT_NOT_REACHED();
return 0;
}
IntRect TilingData::overlappedTileIndices(const WebCore::IntRect &srcRect) const
{
int x = tileXIndexFromSrcCoord(srcRect.x());
int y = tileYIndexFromSrcCoord(srcRect.y());
int r = tileXIndexFromSrcCoord(srcRect.maxX());
int b = tileYIndexFromSrcCoord(srcRect.maxY());
return IntRect(x, y, r - x, b - y);
}
IntRect TilingData::overlappedTileIndices(const WebCore::FloatRect &srcRect) const
{
return overlappedTileIndices(enclosingIntRect(srcRect));
}
IntPoint TilingData::textureOffset(int xIndex, int yIndex) const
{
int left = (!xIndex || m_numTilesX == 1) ? 0 : m_borderTexels;
int top = (!yIndex || m_numTilesY == 1) ? 0 : m_borderTexels;
return IntPoint(left, top);
}
void TilingData::recomputeNumTiles()
{
m_numTilesX = computeNumTiles(m_maxTextureSize, m_totalSizeX, m_borderTexels);
m_numTilesY = computeNumTiles(m_maxTextureSize, m_totalSizeY, m_borderTexels);
}
}
#endif