• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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