void TiledDrawingAreaProxy::paint(const IntRect& rect, PlatformDrawingContext context)
{
    if (m_isWaitingForDidSetFrameNotification) {
        WebPageProxy* page = this->page();
        if (!page->isValid())
            return;

        if (page->process()->isLaunching())
            return;
    }

    adjustVisibleRect();

    GraphicsContext gc(context);
    gc.save();

    // Assumes the backing store is painted with the scale transform applied.
    // Since tile content is already scaled, first revert the scaling from the painter.
    gc.scale(FloatSize(1 / m_contentsScale, 1 / m_contentsScale));

    IntRect dirtyRect = mapFromContents(rect);

    TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
    TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());

    for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
        for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
            TiledDrawingAreaTile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
            RefPtr<TiledDrawingAreaTile> currentTile = tileAt(currentCoordinate);
            if (currentTile && currentTile->isReadyToPaint())
                currentTile->paint(&gc, dirtyRect);
            else {
                IntRect tileRect = tileRectForCoordinate(currentCoordinate);
                IntRect target = intersection(tileRect, dirtyRect);
                if (target.isEmpty())
                    continue;
                TiledDrawingAreaTile::paintCheckerPattern(&gc, FloatRect(target));
            }
        }
    }
    gc.restore();
}
예제 #2
0
double TiledDrawingAreaProxy::tileDistance(const IntRect& viewport, const TiledDrawingAreaTile::Coordinate& tileCoordinate)
{
    if (viewport.intersects(tileRectForCoordinate(tileCoordinate)))
        return 0;

    IntPoint viewCenter = viewport.location() + IntSize(viewport.width() / 2, viewport.height() / 2);
    TiledDrawingAreaTile::Coordinate centerCoordinate = tileCoordinateForPoint(viewCenter);

    // Manhattan distance, biased so that vertical distances are shorter.
    const double horizontalBias = 1.3;
    return abs(centerCoordinate.y() - tileCoordinate.y()) + horizontalBias * abs(centerCoordinate.x() - tileCoordinate.x());
}
예제 #3
0
void TiledDrawingAreaProxy::createTiles()
{
    IntRect visibleRect = mapFromContents(webViewVisibleRect());
    m_previousVisibleRect = visibleRect;

    if (visibleRect.isEmpty())
        return;

    // Resize tiles on edges in case the contents size has changed.
    bool didResizeTiles = resizeEdgeTiles();

    // Remove tiles outside out current maximum keep rect.
    dropTilesOutsideRect(calculateKeepRect(visibleRect));

    // Cover the cover rect with tiles.
    IntRect coverRect = calculateCoverRect(visibleRect);

    // Search for the tile position closest to the viewport center that does not yet contain a tile.
    // Which position is considered the closest depends on the tileDistance function.
    double shortestDistance = std::numeric_limits<double>::infinity();
    Vector<TiledDrawingAreaTile::Coordinate> tilesToCreate;
    unsigned requiredTileCount = 0;
    bool hasVisibleCheckers = false;
    TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(coverRect.topLeft());
    TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(coverRect.bottomRight());
    for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
        for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
            TiledDrawingAreaTile::Coordinate currentCoordinate(xCoordinate, yCoordinate);
            // Distance is 0 for all currently visible tiles.
            double distance = tileDistance(visibleRect, currentCoordinate);

            RefPtr<TiledDrawingAreaTile> tile = tileAt(currentCoordinate);
            if (!distance && (!tile || !tile->isReadyToPaint()))
                hasVisibleCheckers = true;
            if (tile)
                continue;

            ++requiredTileCount;

            if (distance > shortestDistance)
                continue;
            if (distance < shortestDistance) {
                tilesToCreate.clear();
                shortestDistance = distance;
            }
            tilesToCreate.append(currentCoordinate);
        }
    }

    if (hasVisibleCheckers && shortestDistance > 0)
        return;

    // Now construct the tile(s).
    unsigned tilesToCreateCount = tilesToCreate.size();
    for (unsigned n = 0; n < tilesToCreateCount; ++n)
        createTile(tilesToCreate[n]);

    requiredTileCount -= tilesToCreateCount;

    // Paint the content of the newly created tiles.
    if (tilesToCreateCount || didResizeTiles)
        updateTileBuffers();

    // Keep creating tiles until the whole coverRect is covered.
    if (requiredTileCount)
        m_tileCreationTimer.startOneShot(m_tileCreationDelay);
}