• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "TiledDrawingAreaProxy.h"
28 
29 #if ENABLE(TILED_BACKING_STORE)
30 #include "DrawingAreaMessageKinds.h"
31 #include "DrawingAreaProxyMessageKinds.h"
32 #include "MessageID.h"
33 #include "UpdateChunk.h"
34 #include "WebCoreArgumentCoders.h"
35 #include "WebPageProxy.h"
36 #include "WebProcessProxy.h"
37 
38 using namespace WebCore;
39 
40 namespace WebKit {
41 
42 static const int defaultTileWidth = 1024;
43 static const int defaultTileHeight = 1024;
44 
create(PlatformWebView * webView,WebPageProxy * webPageProxy)45 PassOwnPtr<TiledDrawingAreaProxy> TiledDrawingAreaProxy::create(PlatformWebView* webView, WebPageProxy* webPageProxy)
46 {
47     return adoptPtr(new TiledDrawingAreaProxy(webView, webPageProxy));
48 }
49 
TiledDrawingAreaProxy(PlatformWebView * webView,WebPageProxy * webPageProxy)50 TiledDrawingAreaProxy::TiledDrawingAreaProxy(PlatformWebView* webView, WebPageProxy* webPageProxy)
51     : DrawingAreaProxy(DrawingAreaTypeTiled, webPageProxy)
52     , m_isWaitingForDidSetFrameNotification(false)
53     , m_isVisible(true)
54     , m_webView(webView)
55     , m_tileBufferUpdateTimer(RunLoop::main(), this, &TiledDrawingAreaProxy::tileBufferUpdateTimerFired)
56     , m_tileCreationTimer(RunLoop::main(), this, &TiledDrawingAreaProxy::tileCreationTimerFired)
57     , m_tileSize(defaultTileWidth, defaultTileHeight)
58     , m_tileCreationDelay(0.01)
59     , m_keepAreaMultiplier(2.5, 4.5)
60     , m_coverAreaMultiplier(2, 3)
61     , m_contentsScale(1)
62 {
63 }
64 
~TiledDrawingAreaProxy()65 TiledDrawingAreaProxy::~TiledDrawingAreaProxy()
66 {
67 }
68 
sizeDidChange()69 void TiledDrawingAreaProxy::sizeDidChange()
70 {
71     WebPageProxy* page = this->page();
72     if (!page || !page->isValid())
73         return;
74 
75     if (m_size.isEmpty())
76         return;
77 
78     m_viewSize = m_size;
79     m_lastSetViewSize = m_size;
80 
81     if (m_isWaitingForDidSetFrameNotification)
82         return;
83     m_isWaitingForDidSetFrameNotification = true;
84 
85     page->process()->responsivenessTimer()->start();
86     page->process()->deprecatedSend(DrawingAreaLegacyMessage::SetSize, page->pageID(), CoreIPC::In(m_size));
87 }
88 
setPageIsVisible(bool isVisible)89 void TiledDrawingAreaProxy::setPageIsVisible(bool isVisible)
90 {
91     WebPageProxy* page = this->page();
92 
93     if (isVisible == m_isVisible)
94         return;
95 
96     m_isVisible = isVisible;
97     if (!page || !page->isValid())
98         return;
99 
100     if (!m_isVisible) {
101         // Tell the web process that it doesn't need to paint anything for now.
102         page->process()->deprecatedSend(DrawingAreaLegacyMessage::SuspendPainting, page->pageID(), CoreIPC::In());
103         return;
104     }
105 
106     // The page is now visible.
107     page->process()->deprecatedSend(DrawingAreaLegacyMessage::ResumePainting, page->pageID(), CoreIPC::In());
108 
109     // FIXME: We should request a full repaint here if needed.
110 }
111 
didSetSize(const IntSize & viewSize)112 void TiledDrawingAreaProxy::didSetSize(const IntSize& viewSize)
113 {
114     ASSERT(m_isWaitingForDidSetFrameNotification);
115     m_isWaitingForDidSetFrameNotification = false;
116 
117     if (viewSize != m_lastSetViewSize)
118         setSize(m_lastSetViewSize, IntSize());
119 
120     WebPageProxy* page = this->page();
121     page->process()->responsivenessTimer()->stop();
122 }
123 
didReceiveMessage(CoreIPC::Connection *,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments)124 void TiledDrawingAreaProxy::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
125 {
126     switch (messageID.get<DrawingAreaProxyLegacyMessage::Kind>()) {
127     case DrawingAreaProxyLegacyMessage::TileUpdated: {
128         int tileID;
129         UpdateChunk updateChunk;
130         float scale;
131         unsigned pendingUpdateCount;
132         if (!arguments->decode(CoreIPC::Out(tileID, updateChunk, scale, pendingUpdateCount)))
133             return;
134 
135         TiledDrawingAreaTile* tile = m_tilesByID.get(tileID);
136         ASSERT(!tile || tile->ID() == tileID);
137         if (tile)
138             tile->updateFromChunk(&updateChunk, scale);
139         tileBufferUpdateComplete();
140         break;
141     }
142     case DrawingAreaProxyLegacyMessage::DidSetSize: {
143         IntSize size;
144         if (!arguments->decode(CoreIPC::Out(size)))
145             return;
146 
147         didSetSize(size);
148         break;
149     }
150     case DrawingAreaProxyLegacyMessage::Invalidate: {
151         IntRect rect;
152         if (!arguments->decode(CoreIPC::Out(rect)))
153             return;
154 
155         invalidate(rect);
156         break;
157     }
158     case DrawingAreaProxyLegacyMessage::AllTileUpdatesProcessed: {
159         tileBufferUpdateComplete();
160         break;
161     }
162     case DrawingAreaProxyLegacyMessage::SnapshotTaken: {
163         UpdateChunk chunk;
164         if (!arguments->decode(CoreIPC::Out(chunk)))
165             return;
166         snapshotTaken(chunk);
167         break;
168     }
169     default:
170         ASSERT_NOT_REACHED();
171     }
172 }
173 
requestTileUpdate(int tileID,const IntRect & dirtyRect)174 void TiledDrawingAreaProxy::requestTileUpdate(int tileID, const IntRect& dirtyRect)
175 {
176     page()->process()->connection()->deprecatedSend(DrawingAreaLegacyMessage::RequestTileUpdate, page()->pageID(), CoreIPC::In(tileID, dirtyRect, contentsScale()));
177 }
178 
waitUntilUpdatesComplete()179 void TiledDrawingAreaProxy::waitUntilUpdatesComplete()
180 {
181     while (hasPendingUpdates()) {
182         int tileID;
183         UpdateChunk updateChunk;
184         float scale;
185         unsigned pendingUpdateCount;
186         static const double tileUpdateTimeout = 10.0;
187         OwnPtr<CoreIPC::ArgumentDecoder> arguments = page()->process()->connection()->deprecatedWaitFor(DrawingAreaProxyLegacyMessage::TileUpdated, page()->pageID(), tileUpdateTimeout);
188         if (!arguments)
189             break;
190         if (!arguments->decode(CoreIPC::Out(tileID, updateChunk, scale, pendingUpdateCount)))
191             break;
192         TiledDrawingAreaTile* tile = m_tilesByID.get(tileID);
193         ASSERT(!tile || tile->ID() == tileID);
194         if (tile)
195             tile->updateFromChunk(&updateChunk, scale);
196     }
197     tileBufferUpdateComplete();
198 }
199 
createTile(const TiledDrawingAreaTile::Coordinate & coordinate)200 PassRefPtr<TiledDrawingAreaTile> TiledDrawingAreaProxy::createTile(const TiledDrawingAreaTile::Coordinate& coordinate)
201 {
202     RefPtr<TiledDrawingAreaTile> tile = TiledDrawingAreaTile::create(this, coordinate);
203     setTile(coordinate, tile);
204     return tile;
205 }
206 
setTileSize(const IntSize & size)207 void TiledDrawingAreaProxy::setTileSize(const IntSize& size)
208 {
209     if (m_tileSize == size)
210         return;
211     m_tileSize = size;
212     removeAllTiles();
213     startTileCreationTimer();
214 }
215 
setTileCreationDelay(double delay)216 void TiledDrawingAreaProxy::setTileCreationDelay(double delay)
217 {
218     m_tileCreationDelay = delay;
219 }
220 
setKeepAndCoverAreaMultipliers(const FloatSize & keepMultiplier,const FloatSize & coverMultiplier)221 void TiledDrawingAreaProxy::setKeepAndCoverAreaMultipliers(const FloatSize& keepMultiplier, const FloatSize& coverMultiplier)
222 {
223     m_keepAreaMultiplier = keepMultiplier;
224     m_coverAreaMultiplier = coverMultiplier;
225     startTileCreationTimer();
226 }
227 
takeSnapshot(const IntSize & size,const IntRect & contentsRect)228 void TiledDrawingAreaProxy::takeSnapshot(const IntSize& size, const IntRect& contentsRect)
229 {
230     WebPageProxy* page = this->page();
231     page->process()->deprecatedSend(DrawingAreaLegacyMessage::TakeSnapshot, page->pageID(), CoreIPC::Out(size, contentsRect));
232 }
233 
invalidate(const IntRect & contentsDirtyRect)234 void TiledDrawingAreaProxy::invalidate(const IntRect& contentsDirtyRect)
235 {
236     IntRect dirtyRect(mapFromContents(contentsDirtyRect));
237 
238     TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.location());
239     TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(dirtyRect.maxX(), dirtyRect.maxY()));
240 
241     IntRect coverRect = calculateCoverRect(m_previousVisibleRect);
242 
243     Vector<TiledDrawingAreaTile::Coordinate> tilesToRemove;
244 
245     for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
246         for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
247             RefPtr<TiledDrawingAreaTile> currentTile = tileAt(TiledDrawingAreaTile::Coordinate(xCoordinate, yCoordinate));
248             if (!currentTile)
249                 continue;
250             if (!currentTile->rect().intersects(dirtyRect))
251                 continue;
252             // If a tile outside out current cover rect gets invalidated, just drop it instead of updating.
253             if (!currentTile->rect().intersects(coverRect)) {
254                 tilesToRemove.append(currentTile->coordinate());
255                 continue;
256             }
257             currentTile->invalidate(dirtyRect);
258         }
259     }
260 
261     unsigned removeCount = tilesToRemove.size();
262     for (unsigned n = 0; n < removeCount; ++n)
263         removeTile(tilesToRemove[n]);
264 
265     startTileBufferUpdateTimer();
266 }
267 
updateTileBuffers()268 void TiledDrawingAreaProxy::updateTileBuffers()
269 {
270     Vector<RefPtr<TiledDrawingAreaTile> > newDirtyTiles;
271     TileMap::iterator end = m_tiles.end();
272     for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
273         RefPtr<TiledDrawingAreaTile>& current = it->second;
274         if (!current->isDirty())
275             continue;
276         newDirtyTiles.append(it->second);
277     }
278 
279     if (newDirtyTiles.isEmpty())
280         return;
281 
282     unsigned size = newDirtyTiles.size();
283     for (unsigned n = 0; n < size; ++n)
284         newDirtyTiles[n]->updateBackBuffer();
285 }
286 
tileBufferUpdateComplete()287 void TiledDrawingAreaProxy::tileBufferUpdateComplete()
288 {
289     // Bail out if all tile back buffers have not been updated.
290     Vector<TiledDrawingAreaTile*> tilesToFlip;
291     TileMap::iterator end = m_tiles.end();
292     for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
293         RefPtr<TiledDrawingAreaTile>& current = it->second;
294         if (current->isReadyToPaint() && (current->isDirty() || current->hasBackBufferUpdatePending()))
295             return;
296         if (current->hasReadyBackBuffer())
297             tilesToFlip.append(current.get());
298     }
299     // Everything done, move back buffers to front.
300     Vector<IntRect> paintedArea;
301     unsigned size = tilesToFlip.size();
302     for (unsigned n = 0; n < size; ++n) {
303         TiledDrawingAreaTile* tile = tilesToFlip[n];
304         tile->swapBackBufferToFront();
305         // FIXME: should not request system repaint for the full tile.
306         paintedArea.append(mapToContents(tile->rect()));
307     }
308     if (size)
309         updateWebView(paintedArea);
310 
311     m_tileCreationTimer.startOneShot(0);
312 }
313 
paint(const IntRect & rect,PlatformDrawingContext context)314 bool TiledDrawingAreaProxy::paint(const IntRect& rect, PlatformDrawingContext context)
315 {
316     if (m_isWaitingForDidSetFrameNotification) {
317         WebPageProxy* page = this->page();
318         if (!page->isValid())
319             return false;
320 
321         if (page->process()->isLaunching())
322             return false;
323     }
324 
325     adjustVisibleRect();
326 
327     GraphicsContext gc(context);
328     gc.save();
329 
330     // Assumes the backing store is painted with the scale transform applied.
331     // Since tile content is already scaled, first revert the scaling from the painter.
332     gc.scale(FloatSize(1 / m_contentsScale, 1 / m_contentsScale));
333 
334     IntRect dirtyRect = mapFromContents(rect);
335 
336     TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.location());
337     TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(dirtyRect.maxX(), dirtyRect.maxY()));
338 
339     for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
340         for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
341             TiledDrawingAreaTile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
342             RefPtr<TiledDrawingAreaTile> currentTile = tileAt(currentCoordinate);
343             if (currentTile && currentTile->isReadyToPaint())
344                 currentTile->paint(&gc, dirtyRect);
345         }
346     }
347 
348     gc.restore();
349     return true;
350 }
351 
adjustVisibleRect()352 void TiledDrawingAreaProxy::adjustVisibleRect()
353 {
354     IntRect visibleRect = mapFromContents(webViewVisibleRect());
355     if (m_previousVisibleRect == visibleRect)
356         return;
357     m_previousVisibleRect = visibleRect;
358 
359     startTileCreationTimer();
360 }
361 
setContentsScale(float scale)362 void TiledDrawingAreaProxy::setContentsScale(float scale)
363 {
364     if (m_contentsScale == scale)
365         return;
366     m_contentsScale = scale;
367     removeAllTiles();
368     createTiles();
369 }
370 
removeAllTiles()371 void TiledDrawingAreaProxy::removeAllTiles()
372 {
373     Vector<RefPtr<TiledDrawingAreaTile> > tilesToRemove;
374     copyValuesToVector(m_tiles, tilesToRemove);
375     unsigned removeCount = tilesToRemove.size();
376     for (unsigned n = 0; n < removeCount; ++n)
377         removeTile(tilesToRemove[n]->coordinate());
378 }
379 
tileDistance(const IntRect & viewport,const TiledDrawingAreaTile::Coordinate & tileCoordinate)380 double TiledDrawingAreaProxy::tileDistance(const IntRect& viewport, const TiledDrawingAreaTile::Coordinate& tileCoordinate)
381 {
382     if (viewport.intersects(tileRectForCoordinate(tileCoordinate)))
383         return 0;
384 
385     IntPoint viewCenter = viewport.location() + IntSize(viewport.width() / 2, viewport.height() / 2);
386     TiledDrawingAreaTile::Coordinate centerCoordinate = tileCoordinateForPoint(viewCenter);
387 
388     // Manhattan distance, biased so that vertical distances are shorter.
389     const double horizontalBias = 1.3;
390     return abs(centerCoordinate.y() - tileCoordinate.y()) + horizontalBias * abs(centerCoordinate.x() - tileCoordinate.x());
391 }
392 
calculateKeepRect(const IntRect & visibleRect) const393 IntRect TiledDrawingAreaProxy::calculateKeepRect(const IntRect& visibleRect) const
394 {
395     IntRect result = visibleRect;
396     // Inflates to both sides, so divide inflate delta by 2
397     result.inflateX(visibleRect.width() * (m_keepAreaMultiplier.width() - 1) / 2);
398     result.inflateY(visibleRect.height() * (m_keepAreaMultiplier.height() - 1) / 2);
399     result.intersect(contentsRect());
400     return result;
401 }
402 
calculateCoverRect(const IntRect & visibleRect) const403 IntRect TiledDrawingAreaProxy::calculateCoverRect(const IntRect& visibleRect) const
404 {
405     IntRect result = visibleRect;
406     // Inflates to both sides, so divide inflate delta by 2
407     result.inflateX(visibleRect.width() * (m_coverAreaMultiplier.width() - 1) / 2);
408     result.inflateY(visibleRect.height() * (m_coverAreaMultiplier.height() - 1) / 2);
409     result.intersect(contentsRect());
410     return result;
411 }
412 
createTiles()413 void TiledDrawingAreaProxy::createTiles()
414 {
415     IntRect visibleRect = mapFromContents(webViewVisibleRect());
416     m_previousVisibleRect = visibleRect;
417 
418     if (visibleRect.isEmpty())
419         return;
420 
421     // Resize tiles on edges in case the contents size has changed.
422     bool didResizeTiles = resizeEdgeTiles();
423 
424     // Remove tiles outside out current maximum keep rect.
425     dropTilesOutsideRect(calculateKeepRect(visibleRect));
426 
427     // Cover the cover rect with tiles.
428     IntRect coverRect = calculateCoverRect(visibleRect);
429 
430     // Search for the tile position closest to the viewport center that does not yet contain a tile.
431     // Which position is considered the closest depends on the tileDistance function.
432     double shortestDistance = std::numeric_limits<double>::infinity();
433     Vector<TiledDrawingAreaTile::Coordinate> tilesToCreate;
434     unsigned requiredTileCount = 0;
435     bool hasVisibleCheckers = false;
436     TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(visibleRect.location());
437     TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(IntPoint(visibleRect.maxX(), visibleRect.maxY()));
438     for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
439         for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
440             TiledDrawingAreaTile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
441             // Distance is 0 for all currently visible tiles.
442             double distance = tileDistance(visibleRect, currentCoordinate);
443 
444             RefPtr<TiledDrawingAreaTile> tile = tileAt(currentCoordinate);
445             if (!distance && (!tile || !tile->isReadyToPaint()))
446                 hasVisibleCheckers = true;
447             if (tile)
448                 continue;
449 
450             ++requiredTileCount;
451 
452             if (distance > shortestDistance)
453                 continue;
454             if (distance < shortestDistance) {
455                 tilesToCreate.clear();
456                 shortestDistance = distance;
457             }
458             tilesToCreate.append(currentCoordinate);
459         }
460     }
461 
462     if (hasVisibleCheckers && shortestDistance > 0)
463         return;
464 
465     // Now construct the tile(s).
466     unsigned tilesToCreateCount = tilesToCreate.size();
467     for (unsigned n = 0; n < tilesToCreateCount; ++n)
468         createTile(tilesToCreate[n]);
469 
470     requiredTileCount -= tilesToCreateCount;
471 
472     // Paint the content of the newly created tiles.
473     if (tilesToCreateCount || didResizeTiles)
474         updateTileBuffers();
475 
476     // Keep creating tiles until the whole coverRect is covered.
477     if (requiredTileCount)
478         m_tileCreationTimer.startOneShot(m_tileCreationDelay);
479 }
480 
resizeEdgeTiles()481 bool TiledDrawingAreaProxy::resizeEdgeTiles()
482 {
483     IntRect contentsRect = this->contentsRect();
484     bool wasResized = false;
485 
486     Vector<TiledDrawingAreaTile::Coordinate> tilesToRemove;
487     TileMap::iterator end = m_tiles.end();
488     for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
489         TiledDrawingAreaTile::Coordinate tileCoordinate = it->second->coordinate();
490         IntRect tileRect = it->second->rect();
491         IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate);
492         if (!contentsRect.contains(tileRect))
493             tilesToRemove.append(tileCoordinate);
494         else if (expectedTileRect != tileRect) {
495             it->second->resize(expectedTileRect.size());
496             wasResized = true;
497         }
498     }
499     unsigned removeCount = tilesToRemove.size();
500     for (unsigned n = 0; n < removeCount; ++n)
501         removeTile(tilesToRemove[n]);
502     return wasResized;
503 }
504 
dropTilesOutsideRect(const IntRect & keepRect)505 void TiledDrawingAreaProxy::dropTilesOutsideRect(const IntRect& keepRect)
506 {
507     FloatRect keepRectF = keepRect;
508 
509     Vector<TiledDrawingAreaTile::Coordinate> toRemove;
510     TileMap::iterator end = m_tiles.end();
511     for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
512         TiledDrawingAreaTile::Coordinate coordinate = it->second->coordinate();
513         FloatRect tileRect = it->second->rect();
514         if (!tileRect.intersects(keepRectF))
515             toRemove.append(coordinate);
516     }
517     unsigned removeCount = toRemove.size();
518     for (unsigned n = 0; n < removeCount; ++n)
519         removeTile(toRemove[n]);
520 }
521 
tileAt(const TiledDrawingAreaTile::Coordinate & coordinate) const522 PassRefPtr<TiledDrawingAreaTile> TiledDrawingAreaProxy::tileAt(const TiledDrawingAreaTile::Coordinate& coordinate) const
523 {
524     return m_tiles.get(coordinate);
525 }
526 
setTile(const TiledDrawingAreaTile::Coordinate & coordinate,RefPtr<TiledDrawingAreaTile> tile)527 void TiledDrawingAreaProxy::setTile(const TiledDrawingAreaTile::Coordinate& coordinate, RefPtr<TiledDrawingAreaTile> tile)
528 {
529     m_tiles.set(coordinate, tile);
530     m_tilesByID.set(tile->ID(), tile.get());
531 }
532 
removeTile(const TiledDrawingAreaTile::Coordinate & coordinate)533 void TiledDrawingAreaProxy::removeTile(const TiledDrawingAreaTile::Coordinate& coordinate)
534 {
535     RefPtr<TiledDrawingAreaTile> tile = m_tiles.take(coordinate);
536 
537     m_tilesByID.remove(tile->ID());
538 
539     if (!tile->hasBackBufferUpdatePending())
540         return;
541     WebPageProxy* page = this->page();
542     page->process()->deprecatedSend(DrawingAreaLegacyMessage::CancelTileUpdate, page->pageID(), CoreIPC::In(tile->ID()));
543 }
544 
mapToContents(const IntRect & rect) const545 IntRect TiledDrawingAreaProxy::mapToContents(const IntRect& rect) const
546 {
547     return enclosingIntRect(FloatRect(rect.x() / m_contentsScale,
548                                       rect.y() / m_contentsScale,
549                                       rect.width() / m_contentsScale,
550                                       rect.height() / m_contentsScale));
551 }
552 
mapFromContents(const IntRect & rect) const553 IntRect TiledDrawingAreaProxy::mapFromContents(const IntRect& rect) const
554 {
555     return enclosingIntRect(FloatRect(rect.x() * m_contentsScale,
556                                       rect.y() * m_contentsScale,
557                                       rect.width() * m_contentsScale,
558                                       rect.height() * m_contentsScale));
559 }
560 
contentsRect() const561 IntRect TiledDrawingAreaProxy::contentsRect() const
562 {
563     return mapFromContents(IntRect(IntPoint(0, 0), m_viewSize));
564 }
565 
tileRectForCoordinate(const TiledDrawingAreaTile::Coordinate & coordinate) const566 IntRect TiledDrawingAreaProxy::tileRectForCoordinate(const TiledDrawingAreaTile::Coordinate& coordinate) const
567 {
568     IntRect rect(coordinate.x() * m_tileSize.width(),
569                  coordinate.y() * m_tileSize.height(),
570                  m_tileSize.width(),
571                  m_tileSize.height());
572 
573     rect.intersect(contentsRect());
574     return rect;
575 }
576 
tileCoordinateForPoint(const IntPoint & point) const577 TiledDrawingAreaTile::Coordinate TiledDrawingAreaProxy::tileCoordinateForPoint(const IntPoint& point) const
578 {
579     int x = point.x() / m_tileSize.width();
580     int y = point.y() / m_tileSize.height();
581     return TiledDrawingAreaTile::Coordinate(std::max(x, 0), std::max(y, 0));
582 }
583 
584 
startTileBufferUpdateTimer()585 void TiledDrawingAreaProxy::startTileBufferUpdateTimer()
586 {
587     if (m_tileBufferUpdateTimer.isActive())
588         return;
589     m_tileBufferUpdateTimer.startOneShot(0);
590 }
591 
tileBufferUpdateTimerFired()592 void TiledDrawingAreaProxy::tileBufferUpdateTimerFired()
593 {
594     updateTileBuffers();
595 }
596 
startTileCreationTimer()597 void TiledDrawingAreaProxy::startTileCreationTimer()
598 {
599     if (m_tileCreationTimer.isActive())
600         return;
601     m_tileCreationTimer.startOneShot(0);
602 }
603 
tileCreationTimerFired()604 void TiledDrawingAreaProxy::tileCreationTimerFired()
605 {
606     createTiles();
607 }
608 
hasPendingUpdates() const609 bool TiledDrawingAreaProxy::hasPendingUpdates() const
610 {
611     TileMap::const_iterator end = m_tiles.end();
612     for (TileMap::const_iterator it = m_tiles.begin(); it != end; ++it) {
613         const RefPtr<TiledDrawingAreaTile>& current = it->second;
614         if (current->hasBackBufferUpdatePending())
615             return true;
616     }
617     return false;
618 }
619 
620 } // namespace WebKit
621 
622 #endif
623