/* * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "config.h" #include "TiledImageOpenVG.h" #include "FloatRect.h" #include "IntRect.h" #include "VGUtils.h" namespace WebCore { TiledImageOpenVG::TiledImageOpenVG(const IntSize& size, const IntSize& tileSize) : SharedResourceOpenVG() , m_size(size) , m_maxTileSize(tileSize) , m_numColumns((m_size.width() - 1) / m_maxTileSize.width() + 1) , m_tiles(((m_size.height() - 1) / m_maxTileSize.height() + 1) * m_numColumns, VG_INVALID_HANDLE) { } TiledImageOpenVG::TiledImageOpenVG(const TiledImageOpenVG& other) : SharedResourceOpenVG() , m_size(other.m_size) , m_maxTileSize(other.m_maxTileSize) , m_numColumns(other.m_numColumns) , m_tiles(other.m_tiles) { detachTiles(); } TiledImageOpenVG& TiledImageOpenVG::operator=(const TiledImageOpenVG& other) { if (&other != this) { destroyTiles(); m_size = other.m_size; m_maxTileSize = other.m_maxTileSize; m_numColumns = other.m_numColumns; m_tiles = other.m_tiles; detachTiles(); } return *this; } TiledImageOpenVG::~TiledImageOpenVG() { destroyTiles(); } int TiledImageOpenVG::numTiles() const { return m_tiles.size(); } int TiledImageOpenVG::numColumns() const { return m_numColumns; } int TiledImageOpenVG::numRows() const { return m_tiles.size() / m_numColumns; } void TiledImageOpenVG::setTile(int xIndex, int yIndex, VGImage image) { ASSERT(xIndex < m_numColumns); int i = (yIndex * m_numColumns) + xIndex; ASSERT(i < m_tiles.size()); m_tiles.at(i) = image; } IntRect TiledImageOpenVG::tilesInRect(const FloatRect& rect) const { int leftIndex = static_cast(rect.x()) / m_maxTileSize.width(); int topIndex = static_cast(rect.y()) / m_maxTileSize.height(); if (leftIndex < 0) leftIndex = 0; if (topIndex < 0) topIndex = 0; // Round rect edges up to get the outer pixel boundaries. int rightIndex = (static_cast(ceil(rect.right())) - 1) / m_maxTileSize.width(); int bottomIndex = (static_cast(ceil(rect.bottom())) - 1) / m_maxTileSize.height(); int columns = (rightIndex - leftIndex) + 1; int rows = (bottomIndex - topIndex) + 1; return IntRect(leftIndex, topIndex, (columns <= m_numColumns) ? columns : m_numColumns, (rows <= (m_tiles.size() / m_numColumns)) ? rows : (m_tiles.size() / m_numColumns)); } VGImage TiledImageOpenVG::tile(int xIndex, int yIndex) const { ASSERT(xIndex < m_numColumns); int i = (yIndex * m_numColumns) + xIndex; ASSERT(i < m_tiles.size()); return m_tiles.at(i); } IntRect TiledImageOpenVG::tileRect(int xIndex, int yIndex) const { ASSERT(xIndex < m_numColumns); ASSERT((yIndex * m_numColumns) + xIndex < m_tiles.size()); int x = xIndex * m_maxTileSize.width(); int y = yIndex * m_maxTileSize.height(); return IntRect(x, y, ((m_maxTileSize.width() < m_size.width() - x) ? m_maxTileSize.width() : (m_size.width() - x)), ((m_maxTileSize.height() < m_size.height() - y) ? m_maxTileSize.height() : (m_size.height() - y))); } void TiledImageOpenVG::detachTiles() { makeSharedContextCurrent(); // because we create new images int numTiles = m_tiles.size(); VGImage newTile, originalTile; for (int i = 0; i < numTiles; ++i) { originalTile = m_tiles.at(i); if (originalTile == VG_INVALID_HANDLE) continue; VGImageFormat format = (VGImageFormat) vgGetParameteri(originalTile, VG_IMAGE_FORMAT); VGint width = vgGetParameteri(originalTile, VG_IMAGE_WIDTH); VGint height = vgGetParameteri(originalTile, VG_IMAGE_HEIGHT); ASSERT_VG_NO_ERROR(); newTile = vgCreateImage(format, width, height, VG_IMAGE_QUALITY_FASTER); ASSERT_VG_NO_ERROR(); vgCopyImage(newTile, 0, 0, originalTile, 0, 0, width, height, VG_FALSE /* dither */); ASSERT_VG_NO_ERROR(); m_tiles.at(i) = newTile; } } void TiledImageOpenVG::destroyTiles() { makeCompatibleContextCurrent(); Vector::const_iterator it = m_tiles.begin(); Vector::const_iterator end = m_tiles.end(); for (; it != end; ++it) { if (*it != VG_INVALID_HANDLE) vgDestroyImage(*it); } ASSERT_VG_NO_ERROR(); m_tiles.fill(VG_INVALID_HANDLE); } }