Home | History | Annotate | Download | only in UIProcess
      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 
     45 PassOwnPtr<TiledDrawingAreaProxy> TiledDrawingAreaProxy::create(PlatformWebView* webView, WebPageProxy* webPageProxy)
     46 {
     47     return adoptPtr(new TiledDrawingAreaProxy(webView, webPageProxy));
     48 }
     49 
     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 
     65 TiledDrawingAreaProxy::~TiledDrawingAreaProxy()
     66 {
     67 }
     68 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    216 void TiledDrawingAreaProxy::setTileCreationDelay(double delay)
    217 {
    218     m_tileCreationDelay = delay;
    219 }
    220 
    221 void TiledDrawingAreaProxy::setKeepAndCoverAreaMultipliers(const FloatSize& keepMultiplier, const FloatSize& coverMultiplier)
    222 {
    223     m_keepAreaMultiplier = keepMultiplier;
    224     m_coverAreaMultiplier = coverMultiplier;
    225     startTileCreationTimer();
    226 }
    227 
    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 
    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 
    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 
    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 
    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 
    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 
    362 void TiledDrawingAreaProxy::setContentsScale(float scale)
    363 {
    364     if (m_contentsScale == scale)
    365         return;
    366     m_contentsScale = scale;
    367     removeAllTiles();
    368     createTiles();
    369 }
    370 
    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 
    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 
    393 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 
    403 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 
    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 
    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 
    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 
    522 PassRefPtr<TiledDrawingAreaTile> TiledDrawingAreaProxy::tileAt(const TiledDrawingAreaTile::Coordinate& coordinate) const
    523 {
    524     return m_tiles.get(coordinate);
    525 }
    526 
    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 
    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 
    545 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 
    553 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 
    561 IntRect TiledDrawingAreaProxy::contentsRect() const
    562 {
    563     return mapFromContents(IntRect(IntPoint(0, 0), m_viewSize));
    564 }
    565 
    566 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 
    577 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 
    585 void TiledDrawingAreaProxy::startTileBufferUpdateTimer()
    586 {
    587     if (m_tileBufferUpdateTimer.isActive())
    588         return;
    589     m_tileBufferUpdateTimer.startOneShot(0);
    590 }
    591 
    592 void TiledDrawingAreaProxy::tileBufferUpdateTimerFired()
    593 {
    594     updateTileBuffers();
    595 }
    596 
    597 void TiledDrawingAreaProxy::startTileCreationTimer()
    598 {
    599     if (m_tileCreationTimer.isActive())
    600         return;
    601     m_tileCreationTimer.startOneShot(0);
    602 }
    603 
    604 void TiledDrawingAreaProxy::tileCreationTimerFired()
    605 {
    606     createTiles();
    607 }
    608 
    609 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