blob: 6fdd7df586b137efd03e97aefc7c8dfb944d631a [file] [log] [blame]
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "TextureMapperQt.h"
#include <QtCore/qdebug.h>
#include <QtGui/qpaintengine.h>
#include <QtGui/qpixmap.h>
#ifdef QT_OPENGL_LIB
# include "opengl/TextureMapperGL.h"
#endif
namespace WebCore {
void BitmapTextureQt::destroy()
{
if (m_pixmap.paintingActive())
qFatal("Destroying an active pixmap");
m_pixmap = QPixmap();
}
void BitmapTextureQt::reset(const IntSize& size, bool isOpaque)
{
BitmapTexture::reset(size, isOpaque);
if (size.width() > m_pixmap.size().width() || size.height() > m_pixmap.size().height() || m_pixmap.isNull())
m_pixmap = QPixmap(size.width(), size.height());
if (!isOpaque)
m_pixmap.fill(Qt::transparent);
}
PlatformGraphicsContext* BitmapTextureQt::beginPaint(const IntRect& dirtyRect)
{
m_painter.begin(&m_pixmap);
TextureMapperQt::initialize(&m_painter);
m_painter.setCompositionMode(QPainter::CompositionMode_Clear);
m_painter.fillRect(QRect(dirtyRect), Qt::transparent);
m_painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
return &m_painter;
}
void BitmapTextureQt::endPaint()
{
m_painter.end();
}
bool BitmapTextureQt::save(const String& path)
{
return m_pixmap.save(path, "PNG");
}
void BitmapTextureQt::setContentsToImage(Image* image)
{
if (!image)
return;
const QPixmap* pixmap = image->nativeImageForCurrentFrame();
if (!pixmap)
return;
BitmapTexture::reset(pixmap->size(), !pixmap->hasAlphaChannel());
m_pixmap = *pixmap;
}
void BitmapTextureQt::pack()
{
if (m_pixmap.isNull())
return;
m_image = m_pixmap.toImage();
m_pixmap = QPixmap();
m_isPacked = true;
}
void BitmapTextureQt::unpack()
{
m_isPacked = false;
if (m_image.isNull())
return;
m_pixmap = QPixmap::fromImage(m_image);
m_image = QImage();
}
void TextureMapperQt::setClip(const IntRect& rect)
{
QPainter* painter = m_currentSurface ? &m_currentSurface->m_painter : m_painter;
painter->setClipRect(rect);
}
TextureMapperQt::TextureMapperQt()
: m_currentSurface(0)
{
}
void TextureMapperQt::setGraphicsContext(GraphicsContext* context)
{
m_painter = context->platformContext();
initialize(m_painter);
}
void TextureMapperQt::bindSurface(BitmapTexture* surface)
{
if (m_currentSurface == surface)
return;
if (m_currentSurface)
m_currentSurface->m_painter.end();
if (!surface) {
m_currentSurface = 0;
return;
}
BitmapTextureQt* surfaceQt = static_cast<BitmapTextureQt*>(surface);
if (!surfaceQt->m_painter.isActive())
surfaceQt->m_painter.begin(&surfaceQt->m_pixmap);
m_currentSurface = surfaceQt;
}
void TextureMapperQt::drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture)
{
const BitmapTextureQt& textureQt = static_cast<const BitmapTextureQt&>(texture);
QPainter* painter = m_painter;
QPixmap pixmap = textureQt.m_pixmap;
if (m_currentSurface)
painter = &m_currentSurface->m_painter;
if (maskTexture && maskTexture->isValid()) {
const BitmapTextureQt* mask = static_cast<const BitmapTextureQt*>(maskTexture);
QPixmap intermediatePixmap(pixmap.size());
intermediatePixmap.fill(Qt::transparent);
QPainter maskPainter(&intermediatePixmap);
maskPainter.setCompositionMode(QPainter::CompositionMode_Source);
maskPainter.drawPixmap(0, 0, pixmap);
maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
maskPainter.drawPixmap(QRect(0, 0, pixmap.width(), pixmap.height()), mask->m_pixmap, mask->sourceRect());
maskPainter.end();
pixmap = intermediatePixmap;
}
const qreal prevOpacity = painter->opacity();
const QTransform prevTransform = painter->transform();
painter->setOpacity(opacity);
painter->setTransform(matrix, true);
painter->drawPixmap(targetRect, pixmap, textureQt.sourceRect());
painter->setTransform(prevTransform);
painter->setOpacity(prevOpacity);
}
PassOwnPtr<TextureMapper> TextureMapper::create(GraphicsContext* context)
{
#ifdef QT_OPENGL_LIB
if (context && context->platformContext()->paintEngine()->type() == QPaintEngine::OpenGL2)
return new TextureMapperGL;
#endif
return new TextureMapperQt;
}
PassRefPtr<BitmapTexture> TextureMapperQt::createTexture()
{
return adoptRef(new BitmapTextureQt());
}
BitmapTextureQt::BitmapTextureQt()
: m_isPacked(false)
{
}
#ifdef QT_OPENGL_LIB
class RGBA32PremultimpliedBufferQt : public RGBA32PremultimpliedBuffer {
public:
virtual PlatformGraphicsContext* beginPaint(const IntRect& rect, bool opaque)
{
// m_image is only using during paint, it's safe to override it.
m_image = QImage(rect.size().width(), rect.size().height(), QImage::Format_ARGB32_Premultiplied);
if (!opaque)
m_image.fill(0);
m_painter.begin(&m_image);
TextureMapperQt::initialize(&m_painter);
m_painter.translate(-rect.x(), -rect.y());
return &m_painter;
}
virtual void endPaint() { m_painter.end(); }
virtual const void* data() const { return m_image.constBits(); }
private:
QPainter m_painter;
QImage m_image;
};
PassRefPtr<RGBA32PremultimpliedBuffer> RGBA32PremultimpliedBuffer::create()
{
return adoptRef(new RGBA32PremultimpliedBufferQt());
}
#endif
};