Home | History | Annotate | Download | only in openvg
      1 /*
      2  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  */
     19 
     20 #include "config.h"
     21 #include "TiledImageOpenVG.h"
     22 
     23 #include "FloatRect.h"
     24 #include "IntRect.h"
     25 #include "VGUtils.h"
     26 
     27 namespace WebCore {
     28 
     29 TiledImageOpenVG::TiledImageOpenVG(const IntSize& size, const IntSize& tileSize)
     30     : SharedResourceOpenVG()
     31     , m_size(size)
     32     , m_maxTileSize(tileSize)
     33     , m_numColumns((m_size.width() - 1) / m_maxTileSize.width() + 1)
     34     , m_tiles(((m_size.height() - 1) / m_maxTileSize.height() + 1) * m_numColumns, VG_INVALID_HANDLE)
     35 {
     36 }
     37 
     38 TiledImageOpenVG::TiledImageOpenVG(const TiledImageOpenVG& other)
     39     : SharedResourceOpenVG()
     40     , m_size(other.m_size)
     41     , m_maxTileSize(other.m_maxTileSize)
     42     , m_numColumns(other.m_numColumns)
     43     , m_tiles(other.m_tiles)
     44 {
     45     detachTiles();
     46 }
     47 
     48 TiledImageOpenVG& TiledImageOpenVG::operator=(const TiledImageOpenVG& other)
     49 {
     50     if (&other != this) {
     51         destroyTiles();
     52 
     53         m_size = other.m_size;
     54         m_maxTileSize = other.m_maxTileSize;
     55         m_numColumns = other.m_numColumns;
     56         m_tiles = other.m_tiles;
     57 
     58         detachTiles();
     59     }
     60     return *this;
     61 }
     62 
     63 TiledImageOpenVG::~TiledImageOpenVG()
     64 {
     65     destroyTiles();
     66 }
     67 
     68 int TiledImageOpenVG::numTiles() const
     69 {
     70     return m_tiles.size();
     71 }
     72 
     73 int TiledImageOpenVG::numColumns() const
     74 {
     75     return m_numColumns;
     76 }
     77 
     78 int TiledImageOpenVG::numRows() const
     79 {
     80     return m_tiles.size() / m_numColumns;
     81 }
     82 
     83 void TiledImageOpenVG::setTile(int xIndex, int yIndex, VGImage image)
     84 {
     85     ASSERT(xIndex < m_numColumns);
     86     int i = (yIndex * m_numColumns) + xIndex;
     87     ASSERT(i < m_tiles.size());
     88     m_tiles.at(i) = image;
     89 }
     90 
     91 IntRect TiledImageOpenVG::tilesInRect(const FloatRect& rect) const
     92 {
     93     int leftIndex = static_cast<int>(rect.x()) / m_maxTileSize.width();
     94     int topIndex = static_cast<int>(rect.y()) / m_maxTileSize.height();
     95 
     96     if (leftIndex < 0)
     97         leftIndex = 0;
     98     if (topIndex < 0)
     99         topIndex = 0;
    100 
    101     // Round rect edges up to get the outer pixel boundaries.
    102     int rightIndex = (static_cast<int>(ceil(rect.right())) - 1) / m_maxTileSize.width();
    103     int bottomIndex = (static_cast<int>(ceil(rect.bottom())) - 1) / m_maxTileSize.height();
    104     int columns = (rightIndex - leftIndex) + 1;
    105     int rows = (bottomIndex - topIndex) + 1;
    106 
    107     return IntRect(leftIndex, topIndex,
    108         (columns <= m_numColumns) ? columns : m_numColumns,
    109         (rows <= (m_tiles.size() / m_numColumns)) ? rows : (m_tiles.size() / m_numColumns));
    110 }
    111 
    112 VGImage TiledImageOpenVG::tile(int xIndex, int yIndex) const
    113 {
    114     ASSERT(xIndex < m_numColumns);
    115     int i = (yIndex * m_numColumns) + xIndex;
    116     ASSERT(i < m_tiles.size());
    117     return m_tiles.at(i);
    118 }
    119 
    120 IntRect TiledImageOpenVG::tileRect(int xIndex, int yIndex) const
    121 {
    122     ASSERT(xIndex < m_numColumns);
    123     ASSERT((yIndex * m_numColumns) + xIndex < m_tiles.size());
    124 
    125     int x = xIndex * m_maxTileSize.width();
    126     int y = yIndex * m_maxTileSize.height();
    127 
    128     return IntRect(x, y,
    129         ((m_maxTileSize.width() < m_size.width() - x) ? m_maxTileSize.width() : (m_size.width() - x)),
    130         ((m_maxTileSize.height() < m_size.height() - y) ? m_maxTileSize.height() : (m_size.height() - y)));
    131 }
    132 
    133 void TiledImageOpenVG::detachTiles()
    134 {
    135     makeSharedContextCurrent(); // because we create new images
    136 
    137     int numTiles = m_tiles.size();
    138     VGImage newTile, originalTile;
    139 
    140     for (int i = 0; i < numTiles; ++i) {
    141         originalTile = m_tiles.at(i);
    142 
    143         if (originalTile == VG_INVALID_HANDLE)
    144             continue;
    145 
    146         VGImageFormat format = (VGImageFormat) vgGetParameteri(originalTile, VG_IMAGE_FORMAT);
    147         VGint width = vgGetParameteri(originalTile, VG_IMAGE_WIDTH);
    148         VGint height = vgGetParameteri(originalTile, VG_IMAGE_HEIGHT);
    149         ASSERT_VG_NO_ERROR();
    150 
    151         newTile = vgCreateImage(format, width, height, VG_IMAGE_QUALITY_FASTER);
    152         ASSERT_VG_NO_ERROR();
    153 
    154         vgCopyImage(newTile, 0, 0, originalTile, 0, 0, width, height, VG_FALSE /* dither */);
    155         ASSERT_VG_NO_ERROR();
    156 
    157         m_tiles.at(i) = newTile;
    158     }
    159 }
    160 
    161 void TiledImageOpenVG::destroyTiles()
    162 {
    163     makeCompatibleContextCurrent();
    164 
    165     Vector<VGImage>::const_iterator it = m_tiles.begin();
    166     Vector<VGImage>::const_iterator end = m_tiles.end();
    167 
    168     for (; it != end; ++it) {
    169         if (*it != VG_INVALID_HANDLE)
    170             vgDestroyImage(*it);
    171     }
    172     ASSERT_VG_NO_ERROR();
    173 
    174     m_tiles.fill(VG_INVALID_HANDLE);
    175 }
    176 
    177 }
    178