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