| /* |
| * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "TiledDrawingAreaTile.h" |
| |
| #if ENABLE(TILED_BACKING_STORE) |
| |
| #include "GraphicsContext.h" |
| #include "TiledDrawingAreaProxy.h" |
| #include "WebPageProxy.h" |
| #include "WebProcessProxy.h" |
| #include "UpdateChunk.h" |
| #include <QApplication> |
| #include <QObject> |
| #include <QPainter> |
| |
| using namespace WebCore; |
| |
| namespace WebKit { |
| |
| TiledDrawingAreaTile::TiledDrawingAreaTile(TiledDrawingAreaProxy* proxy, const Coordinate& tileCoordinate) |
| : m_proxy(proxy) |
| , m_coordinate(tileCoordinate) |
| , m_rect(proxy->tileRectForCoordinate(tileCoordinate)) |
| , m_hasUpdatePending(false) |
| , m_dirtyRegion(m_rect) |
| { |
| static int id = 0; |
| m_ID = ++id; |
| #ifdef TILE_DEBUG_LOG |
| qDebug() << "deleting tile id=" << m_ID; |
| #endif |
| } |
| |
| TiledDrawingAreaTile::~TiledDrawingAreaTile() |
| { |
| #ifdef TILE_DEBUG_LOG |
| qDebug() << "deleting tile id=" << m_ID; |
| #endif |
| } |
| |
| bool TiledDrawingAreaTile::isDirty() const |
| { |
| return !m_dirtyRegion.isEmpty(); |
| } |
| |
| bool TiledDrawingAreaTile::isReadyToPaint() const |
| { |
| return !m_buffer.isNull(); |
| } |
| |
| bool TiledDrawingAreaTile::hasReadyBackBuffer() const |
| { |
| return !m_backBuffer.isNull() && !m_hasUpdatePending; |
| } |
| |
| void TiledDrawingAreaTile::invalidate(const IntRect& dirtyRect) |
| { |
| IntRect tileDirtyRect = intersection(dirtyRect, m_rect); |
| if (tileDirtyRect.isEmpty()) |
| return; |
| |
| m_dirtyRegion += tileDirtyRect; |
| } |
| |
| void TiledDrawingAreaTile::resize(const IntSize& newSize) |
| { |
| IntRect oldRect = m_rect; |
| m_rect = IntRect(m_rect.location(), newSize); |
| if (m_rect.maxX() > oldRect.maxX()) |
| invalidate(IntRect(oldRect.maxX(), oldRect.y(), m_rect.maxX() - oldRect.maxX(), m_rect.height())); |
| if (m_rect.maxY() > oldRect.maxY()) |
| invalidate(IntRect(oldRect.x(), oldRect.maxY(), m_rect.width(), m_rect.maxY() - oldRect.maxY())); |
| } |
| |
| void TiledDrawingAreaTile::swapBackBufferToFront() |
| { |
| ASSERT(!m_backBuffer.isNull()); |
| |
| m_buffer = m_backBuffer; |
| m_backBuffer = QPixmap(); |
| } |
| |
| void TiledDrawingAreaTile::paint(GraphicsContext* context, const IntRect& rect) |
| { |
| ASSERT(!m_buffer.isNull()); |
| |
| IntRect target = intersection(rect, m_rect); |
| IntRect source((target.x() - m_rect.x()), |
| (target.y() - m_rect.y()), |
| target.width(), |
| target.height()); |
| |
| context->platformContext()->drawPixmap(target, m_buffer, source); |
| } |
| |
| void TiledDrawingAreaTile::updateFromChunk(UpdateChunk* updateChunk, float) |
| { |
| QImage image(updateChunk->createImage()); |
| const IntRect& updateChunkRect = updateChunk->rect(); |
| |
| #ifdef TILE_DEBUG_LOG |
| qDebug() << "tile updated id=" << ID() << " rect=" << QRect(updateChunkRect); |
| #endif |
| if (updateChunkRect.size() == m_proxy->tileSize()) { |
| // Make a deep copy of the image since it's in shared memory. |
| m_backBuffer = QPixmap::fromImage(image.copy()); |
| } else { |
| if (m_backBuffer.isNull()) |
| m_backBuffer = m_buffer.isNull() ? QPixmap(m_proxy->tileSize()) : m_buffer; |
| QPainter painter(&m_backBuffer); |
| IntSize drawPoint = updateChunkRect.location() - m_rect.location(); |
| painter.drawImage(QPoint(drawPoint.width(), drawPoint.height()), image); |
| } |
| m_hasUpdatePending = false; |
| } |
| |
| void TiledDrawingAreaTile::updateBackBuffer() |
| { |
| if (isReadyToPaint() && !isDirty()) |
| return; |
| |
| // FIXME: individual rects |
| IntRect dirtyRect = m_dirtyRegion.boundingRect(); |
| m_dirtyRegion = QRegion(); |
| |
| #ifdef TILE_DEBUG_LOG |
| qDebug() << "requesting tile update id=" << m_ID << " rect=" << QRect(dirtyRect) << " scale=" << m_proxy->contentsScale(); |
| #endif |
| if (!m_proxy->page()->process()->isValid()) |
| return; |
| m_proxy->requestTileUpdate(m_ID, dirtyRect); |
| |
| m_hasUpdatePending = true; |
| } |
| |
| } |
| #endif |