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
checkeredPixmap()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
Tile(TiledBackingStore * backingStore,const Coordinate & tileCoordinate)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
~Tile()68 Tile::~Tile()
69 {
70 delete m_buffer;
71 delete m_backBuffer;
72 delete m_dirtyRegion;
73 }
74
isDirty() const75 bool Tile::isDirty() const
76 {
77 return !m_dirtyRegion->isEmpty();
78 }
79
isReadyToPaint() const80 bool Tile::isReadyToPaint() const
81 {
82 return m_buffer;
83 }
84
invalidate(const IntRect & dirtyRect)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
updateBackBuffer()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
swapBackBufferToFront()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
paint(GraphicsContext * context,const IntRect & rect)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
paintCheckerPattern(GraphicsContext * context,const FloatRect & target)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