1 /* 2 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18 */ 19 20 #include "config.h" 21 #include "TextureMapperQt.h" 22 23 #include <QtCore/qdebug.h> 24 #include <QtGui/qpaintengine.h> 25 #include <QtGui/qpixmap.h> 26 27 #ifdef QT_OPENGL_LIB 28 # include "opengl/TextureMapperGL.h" 29 #endif 30 31 namespace WebCore { 32 33 void BitmapTextureQt::destroy() 34 { 35 if (m_pixmap.paintingActive()) 36 qFatal("Destroying an active pixmap"); 37 m_pixmap = QPixmap(); 38 } 39 40 void BitmapTextureQt::reset(const IntSize& size, bool isOpaque) 41 { 42 BitmapTexture::reset(size, isOpaque); 43 44 if (size.width() > m_pixmap.size().width() || size.height() > m_pixmap.size().height() || m_pixmap.isNull()) 45 m_pixmap = QPixmap(size.width(), size.height()); 46 if (!isOpaque) 47 m_pixmap.fill(Qt::transparent); 48 } 49 50 PlatformGraphicsContext* BitmapTextureQt::beginPaint(const IntRect& dirtyRect) 51 { 52 m_painter.begin(&m_pixmap); 53 TextureMapperQt::initialize(&m_painter); 54 m_painter.setCompositionMode(QPainter::CompositionMode_Clear); 55 m_painter.fillRect(QRect(dirtyRect), Qt::transparent); 56 m_painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 57 return &m_painter; 58 } 59 60 void BitmapTextureQt::endPaint() 61 { 62 m_painter.end(); 63 } 64 65 bool BitmapTextureQt::save(const String& path) 66 { 67 return m_pixmap.save(path, "PNG"); 68 } 69 70 void BitmapTextureQt::setContentsToImage(Image* image) 71 { 72 if (!image) 73 return; 74 const QPixmap* pixmap = image->nativeImageForCurrentFrame(); 75 if (!pixmap) 76 return; 77 BitmapTexture::reset(pixmap->size(), !pixmap->hasAlphaChannel()); 78 m_pixmap = *pixmap; 79 } 80 81 void BitmapTextureQt::pack() 82 { 83 if (m_pixmap.isNull()) 84 return; 85 86 m_image = m_pixmap.toImage(); 87 m_pixmap = QPixmap(); 88 m_isPacked = true; 89 } 90 91 void BitmapTextureQt::unpack() 92 { 93 m_isPacked = false; 94 if (m_image.isNull()) 95 return; 96 97 m_pixmap = QPixmap::fromImage(m_image); 98 m_image = QImage(); 99 } 100 101 void TextureMapperQt::setClip(const IntRect& rect) 102 { 103 QPainter* painter = m_currentSurface ? &m_currentSurface->m_painter : m_painter; 104 painter->setClipRect(rect); 105 } 106 107 TextureMapperQt::TextureMapperQt() 108 : m_currentSurface(0) 109 { 110 } 111 112 void TextureMapperQt::setGraphicsContext(GraphicsContext* context) 113 { 114 m_painter = context->platformContext(); 115 initialize(m_painter); 116 } 117 118 void TextureMapperQt::bindSurface(BitmapTexture* surface) 119 { 120 if (m_currentSurface == surface) 121 return; 122 if (m_currentSurface) 123 m_currentSurface->m_painter.end(); 124 if (!surface) { 125 m_currentSurface = 0; 126 return; 127 } 128 BitmapTextureQt* surfaceQt = static_cast<BitmapTextureQt*>(surface); 129 if (!surfaceQt->m_painter.isActive()) 130 surfaceQt->m_painter.begin(&surfaceQt->m_pixmap); 131 m_currentSurface = surfaceQt; 132 } 133 134 135 void TextureMapperQt::drawTexture(const BitmapTexture& texture, const IntRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture) 136 { 137 const BitmapTextureQt& textureQt = static_cast<const BitmapTextureQt&>(texture); 138 QPainter* painter = m_painter; 139 QPixmap pixmap = textureQt.m_pixmap; 140 if (m_currentSurface) 141 painter = &m_currentSurface->m_painter; 142 143 if (maskTexture && maskTexture->isValid()) { 144 const BitmapTextureQt* mask = static_cast<const BitmapTextureQt*>(maskTexture); 145 QPixmap intermediatePixmap(pixmap.size()); 146 intermediatePixmap.fill(Qt::transparent); 147 QPainter maskPainter(&intermediatePixmap); 148 maskPainter.setCompositionMode(QPainter::CompositionMode_Source); 149 maskPainter.drawPixmap(0, 0, pixmap); 150 maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); 151 maskPainter.drawPixmap(QRect(0, 0, pixmap.width(), pixmap.height()), mask->m_pixmap, mask->sourceRect()); 152 maskPainter.end(); 153 pixmap = intermediatePixmap; 154 } 155 156 const qreal prevOpacity = painter->opacity(); 157 const QTransform prevTransform = painter->transform(); 158 painter->setOpacity(opacity); 159 painter->setTransform(matrix, true); 160 painter->drawPixmap(targetRect, pixmap, textureQt.sourceRect()); 161 painter->setTransform(prevTransform); 162 painter->setOpacity(prevOpacity); 163 } 164 165 PassOwnPtr<TextureMapper> TextureMapper::create(GraphicsContext* context) 166 { 167 #ifdef QT_OPENGL_LIB 168 if (context && context->platformContext()->paintEngine()->type() == QPaintEngine::OpenGL2) 169 return new TextureMapperGL; 170 #endif 171 return new TextureMapperQt; 172 } 173 174 PassRefPtr<BitmapTexture> TextureMapperQt::createTexture() 175 { 176 return adoptRef(new BitmapTextureQt()); 177 } 178 179 BitmapTextureQt::BitmapTextureQt() 180 : m_isPacked(false) 181 { 182 183 } 184 185 #ifdef QT_OPENGL_LIB 186 class RGBA32PremultimpliedBufferQt : public RGBA32PremultimpliedBuffer { 187 public: 188 virtual PlatformGraphicsContext* beginPaint(const IntRect& rect, bool opaque) 189 { 190 // m_image is only using during paint, it's safe to override it. 191 m_image = QImage(rect.size().width(), rect.size().height(), QImage::Format_ARGB32_Premultiplied); 192 if (!opaque) 193 m_image.fill(0); 194 m_painter.begin(&m_image); 195 TextureMapperQt::initialize(&m_painter); 196 m_painter.translate(-rect.x(), -rect.y()); 197 return &m_painter; 198 } 199 200 virtual void endPaint() { m_painter.end(); } 201 virtual const void* data() const { return m_image.constBits(); } 202 203 private: 204 QPainter m_painter; 205 QImage m_image; 206 }; 207 208 PassRefPtr<RGBA32PremultimpliedBuffer> RGBA32PremultimpliedBuffer::create() 209 { 210 return adoptRef(new RGBA32PremultimpliedBufferQt()); 211 } 212 213 #endif 214 }; 215