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