Home | History | Annotate | Download | only in qt
      1 /*
      2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
      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 "Tile.h"
     22 
     23 #if ENABLE(TILED_BACKING_STORE)
     24 
     25 #include "GraphicsContext.h"
     26 #include "TiledBackingStore.h"
     27 #include "TiledBackingStoreClient.h"
     28 #include <QApplication>
     29 #include <QObject>
     30 #include <QPainter>
     31 #include <QRegion>
     32 
     33 namespace WebCore {
     34 
     35 static const unsigned checkerSize = 16;
     36 static const unsigned checkerColor1 = 0xff555555;
     37 static const unsigned checkerColor2 = 0xffaaaaaa;
     38 
     39 static QPixmap& checkeredPixmap()
     40 {
     41     static QPixmap* pixmap;
     42     if (!pixmap) {
     43         pixmap = new QPixmap(checkerSize, checkerSize);
     44         QPainter painter(pixmap);
     45         QColor color1(checkerColor1);
     46         QColor color2(checkerColor2);
     47         for (unsigned y = 0; y < checkerSize; y += checkerSize / 2) {
     48             bool alternate = y % checkerSize;
     49             for (unsigned x = 0; x < checkerSize; x += checkerSize / 2) {
     50                 painter.fillRect(x, y, checkerSize / 2, checkerSize / 2, alternate ? color1 : color2);
     51                 alternate = !alternate;
     52             }
     53         }
     54     }
     55     return *pixmap;
     56 }
     57 
     58 Tile::Tile(TiledBackingStore* backingStore, const Coordinate& tileCoordinate)
     59     : m_backingStore(backingStore)
     60     , m_coordinate(tileCoordinate)
     61     , m_rect(m_backingStore->tileRectForCoordinate(tileCoordinate))
     62     , m_buffer(0)
     63     , m_backBuffer(0)
     64     , m_dirtyRegion(new QRegion(m_rect))
     65 {
     66 }
     67 
     68 Tile::~Tile()
     69 {
     70     delete m_buffer;
     71     delete m_backBuffer;
     72     delete m_dirtyRegion;
     73 }
     74 
     75 bool Tile::isDirty() const
     76 {
     77     return !m_dirtyRegion->isEmpty();
     78 }
     79 
     80 bool Tile::isReadyToPaint() const
     81 {
     82     return m_buffer;
     83 }
     84 
     85 void Tile::invalidate(const IntRect& dirtyRect)
     86 {
     87     IntRect tileDirtyRect = intersection(dirtyRect, m_rect);
     88     if (tileDirtyRect.isEmpty())
     89         return;
     90 
     91     *m_dirtyRegion += tileDirtyRect;
     92 }
     93 
     94 Vector<IntRect> Tile::updateBackBuffer()
     95 {
     96     if (m_buffer && !isDirty())
     97         return Vector<IntRect>();
     98 
     99     if (!m_backBuffer) {
    100         if (!m_buffer) {
    101             m_backBuffer = new QPixmap(m_backingStore->m_tileSize.width(), m_backingStore->m_tileSize.height());
    102             m_backBuffer->fill(m_backingStore->m_client->tiledBackingStoreBackgroundColor());
    103         } else {
    104             // Currently all buffers are updated synchronously at the same time so there is no real need
    105             // to have separate back and front buffers. Just use the existing buffer.
    106             m_backBuffer = m_buffer;
    107             m_buffer = 0;
    108         }
    109     }
    110 
    111     QVector<QRect> dirtyRects = m_dirtyRegion->rects();
    112     *m_dirtyRegion = QRegion();
    113 
    114     QPainter painter(m_backBuffer);
    115     GraphicsContext context(&painter);
    116     context.translate(-m_rect.x(), -m_rect.y());
    117 
    118     Vector<IntRect> updatedRects;
    119     int size = dirtyRects.size();
    120     for (int n = 0; n < size; ++n)  {
    121         context.save();
    122         IntRect rect = dirtyRects[n];
    123         updatedRects.append(rect);
    124         context.clip(FloatRect(rect));
    125         context.scale(FloatSize(m_backingStore->m_contentsScale, m_backingStore->m_contentsScale));
    126         m_backingStore->m_client->tiledBackingStorePaint(&context, m_backingStore->mapToContents(rect));
    127         context.restore();
    128     }
    129 
    130     return updatedRects;
    131 }
    132 
    133 void Tile::swapBackBufferToFront()
    134 {
    135     if (!m_backBuffer)
    136         return;
    137     delete m_buffer;
    138     m_buffer = m_backBuffer;
    139     m_backBuffer = 0;
    140 }
    141 
    142 void Tile::paint(GraphicsContext* context, const IntRect& rect)
    143 {
    144     if (!m_buffer)
    145         return;
    146 
    147     IntRect target = intersection(rect, m_rect);
    148     IntRect source((target.x() - m_rect.x()),
    149                    (target.y() - m_rect.y()),
    150                    target.width(),
    151                    target.height());
    152 
    153     context->platformContext()->drawPixmap(target, *m_buffer, source);
    154 }
    155 
    156 void Tile::paintCheckerPattern(GraphicsContext* context, const FloatRect& target)
    157 {
    158     QPainter* painter = context->platformContext();
    159     QTransform worldTransform = painter->worldTransform();
    160     qreal scaleX = worldTransform.m11();
    161     qreal scaleY = worldTransform.m22();
    162 
    163     QRect targetViewRect = QRectF(target.x() * scaleX,
    164                                   target.y() * scaleY,
    165                                   target.width() * scaleX,
    166                                   target.height() * scaleY).toAlignedRect();
    167 
    168     QTransform adjustedTransform(1., worldTransform.m12(), worldTransform.m13(),
    169                   worldTransform.m21(), 1., worldTransform.m23(),
    170                   worldTransform.m31(), worldTransform.m32(), worldTransform.m33());
    171     painter->setWorldTransform(adjustedTransform);
    172 
    173     painter->drawTiledPixmap(targetViewRect,
    174                              checkeredPixmap(),
    175                              QPoint(targetViewRect.left() % checkerSize,
    176                                     targetViewRect.top() % checkerSize));
    177 
    178     painter->setWorldTransform(worldTransform);
    179 }
    180 
    181 }
    182 
    183 #endif
    184