223383e198531d65e35919434d7a51db3e66cac2
[WebKit-https.git] / Source / WebCore / platform / graphics / qt / TileQt.cpp
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 "TileQt.h"
22
23 #if USE(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 TileQt::TileQt(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 TileQt::~TileQt()
69 {
70     delete m_buffer;
71     delete m_backBuffer;
72     delete m_dirtyRegion;
73 }
74
75 bool TileQt::isDirty() const
76
77     return !m_dirtyRegion->isEmpty(); 
78 }
79
80 bool TileQt::isReadyToPaint() const
81
82     return m_buffer; 
83 }
84
85 void TileQt::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> TileQt::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->tileSize().width(), m_backingStore->tileSize().height());
102             m_backBuffer->fill(m_backingStore->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->contentsScale(), m_backingStore->contentsScale()));
126         m_backingStore->client()->tiledBackingStorePaint(&context, m_backingStore->mapToContents(rect));
127         context.restore();
128     }
129
130     return updatedRects;
131 }
132
133 void TileQt::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 TileQt::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 TileQt::resize(const IntSize& newSize)
157 {
158     IntRect oldRect = m_rect;
159     m_rect = IntRect(m_rect.location(), newSize);
160     if (m_rect.maxX() > oldRect.maxX())
161         invalidate(IntRect(oldRect.maxX(), oldRect.y(), m_rect.maxX() - oldRect.maxX(), m_rect.height()));
162     if (m_rect.maxY() > oldRect.maxY())
163         invalidate(IntRect(oldRect.x(), oldRect.maxY(), m_rect.width(), m_rect.maxY() - oldRect.maxY()));
164 }
165
166 void TiledBackingStoreBackend::paintCheckerPattern(GraphicsContext* context, const FloatRect& target)
167 {
168     QPainter* painter = context->platformContext();
169     QTransform worldTransform = painter->worldTransform();
170     qreal scaleX = worldTransform.m11();
171     qreal scaleY = worldTransform.m22();
172     
173     QRect targetViewRect = QRectF(target.x() * scaleX,
174                                   target.y() * scaleY,
175                                   target.width() * scaleX,
176                                   target.height() * scaleY).toAlignedRect();
177     
178     QTransform adjustedTransform(1., worldTransform.m12(), worldTransform.m13(),
179                   worldTransform.m21(), 1., worldTransform.m23(),
180                   worldTransform.m31(), worldTransform.m32(), worldTransform.m33());
181     painter->setWorldTransform(adjustedTransform);
182     
183     painter->drawTiledPixmap(targetViewRect,
184                              checkeredPixmap(),
185                              QPoint(targetViewRect.left() % checkerSize,
186                                     targetViewRect.top() % checkerSize));
187     
188     painter->setWorldTransform(worldTransform);
189 }
190
191 PassRefPtr<Tile> TiledBackingStoreBackend::createTile(TiledBackingStore* backingStore, const Tile::Coordinate& tileCoordinate)
192 {
193     return TileQt::create(backingStore, tileCoordinate);
194 }
195
196 }
197
198 #endif