diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp | 151 |
1 files changed, 64 insertions, 87 deletions
diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 32dd39a5f..ac27dc25a 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -32,7 +32,6 @@ #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" -#include "NativeImageQt.h" #include "StillImageQt.h" #include "TransparencyLayer.h" #include <wtf/text/CString.h> @@ -43,22 +42,23 @@ #include <QImage> #include <QImageWriter> #include <QPainter> +#include <QPixmap> #include <math.h> namespace WebCore { ImageBufferData::ImageBufferData(const IntSize& size) - : m_nativeImage(size, NativeImageQt::defaultFormatForAlphaEnabledImages()) + : m_pixmap(size) { - if (m_nativeImage.isNull()) + if (m_pixmap.isNull()) return; - m_nativeImage.fill(QColor(Qt::transparent)); + m_pixmap.fill(QColor(Qt::transparent)); QPainter* painter = new QPainter; m_painter = adoptPtr(painter); - if (!painter->begin(&m_nativeImage)) + if (!painter->begin(&m_pixmap)) return; // Since ImageBuffer is used mainly for Canvas, explicitly initialize @@ -76,7 +76,22 @@ ImageBufferData::ImageBufferData(const IntSize& size) painter->setBrush(brush); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - m_image = StillImage::createForRendering(&m_nativeImage); + m_image = StillImage::createForRendering(&m_pixmap); +} + +QImage ImageBufferData::toQImage() const +{ + QPaintEngine* paintEngine = m_pixmap.paintEngine(); + if (!paintEngine || paintEngine->type() != QPaintEngine::Raster) + return m_pixmap.toImage(); + + // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it. + // For performance reasons, we don't want that here, so we temporarily redirect the paint engine. + QPaintDevice* currentPaintDevice = paintEngine->paintDevice(); + paintEngine->setPaintDevice(0); + QImage image = m_pixmap.toImage(); + paintEngine->setPaintDevice(currentPaintDevice); + return image; } ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success) @@ -105,9 +120,9 @@ GraphicsContext* ImageBuffer::context() const PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const { if (copyBehavior == CopyBackingStore) - return StillImage::create(m_data.m_nativeImage); + return StillImage::create(m_data.m_pixmap); - return StillImage::createForRendering(&m_data.m_nativeImage); + return StillImage::createForRendering(&m_data.m_pixmap); } void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, @@ -134,12 +149,12 @@ void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& src void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) const { - QImage* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); + QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); if (!nativeImage) return; IntRect rect = enclosingIntRect(floatRect); - QImage alphaMask = *nativeImage; + QPixmap alphaMask = *nativeImage; context->pushTransparencyLayerInternal(rect, 1.0, alphaMask); } @@ -150,7 +165,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) if (isPainting) m_data.m_painter->end(); - QImage image = m_data.m_nativeImage.convertToFormat(QImage::Format_ARGB32); + QImage image = m_data.toQImage().convertToFormat(QImage::Format_ARGB32); ASSERT(!image.isNull()); uchar* bits = image.bits(); @@ -167,10 +182,20 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) } } - m_data.m_nativeImage = image; + m_data.m_pixmap = QPixmap::fromImage(image); if (isPainting) - m_data.m_painter->begin(&m_data.m_nativeImage); + m_data.m_painter->begin(&m_data.m_pixmap); +} + +static inline quint32 convertABGRToARGB(quint32 pixel) +{ + return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); +} + +static inline quint32 convertARGBToABGR(quint32 pixel) +{ + return convertABGRToARGB(pixel); } template <Multiply multiplied> @@ -209,7 +234,7 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe int numRows = endy - originy; // NOTE: For unmultiplied data, we undo the premultiplication below. - QImage image = imageData.m_nativeImage.convertToFormat(NativeImageQt::defaultFormatForAlphaEnabledImages()); + QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); ASSERT(!image.isNull()); @@ -217,40 +242,18 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe const uchar* bits = image.constBits(); quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]); - - if (multiplied == Unmultiplied) { - for (int y = 0; y < numRows; ++y) { - const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - QRgb pixel = scanLine[x + originx]; - int alpha = qAlpha(pixel); - // Un-premultiply and convert RGB to BGR. - if (alpha == 255) - destRows[x] = (0xFF000000 - | (qBlue(pixel) << 16) - | (qGreen(pixel) << 8) - | (qRed(pixel))); - else if (alpha > 0) - destRows[x] = ((alpha << 24) - | (((255 * qBlue(pixel)) / alpha)) << 16) - | (((255 * qGreen(pixel)) / alpha) << 8) - | ((255 * qRed(pixel)) / alpha); - else - destRows[x] = 0; - } - destRows += rect.width(); - } - } else { - for (int y = 0; y < numRows; ++y) { - const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - QRgb pixel = scanLine[x + originx]; - // Convert RGB to BGR. - destRows[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); - - } - destRows += rect.width(); + for (int y = 0; y < numRows; ++y) { + const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); + for (int x = 0; x < numColumns; x++) { + QRgb pixel = scanLine[x + originx]; + Color pixelColor; + if (multiplied == Unmultiplied) + pixelColor = colorFromPremultipliedARGB(Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)).rgb()); + else + pixelColor = Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)); + destRows[x] = convertARGBToABGR(pixelColor.rgb()); } + destRows += rect.width(); } return result.release(); @@ -266,22 +269,6 @@ PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe return getImageData<Premultiplied>(rect, m_data, m_size); } -static inline unsigned int premultiplyABGRtoARGB(unsigned int x) -{ - unsigned int a = x >> 24; - if (a == 255) - return (x << 16) | ((x >> 16) & 0xff) | (x & 0xff00ff00); - unsigned int t = (x & 0xff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t = ((t << 16) | (t >> 16)) & 0xff00ff; - - x = ((x >> 8) & 0xff) * a; - x = (x + ((x >> 8) & 0xff) + 0x80); - x &= 0xff00; - x |= t | (a << 24); - return x; -} - void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) { ASSERT(sourceRect.width() > 0); @@ -319,31 +306,21 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c const quint32* srcScanLine = reinterpret_cast_ptr<const quint32*>(source->data() + originy * srcBytesPerRow + originx * 4); - if (multiplied == Unmultiplied) { - for (int y = 0; y < numRows; ++y) { - quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - // Premultiply and convert BGR to RGB. - quint32 pixel = srcScanLine[x]; - destScanLine[x] = premultiplyABGRtoARGB(pixel); - } - srcScanLine += sourceSize.width(); - } - } else { - for (int y = 0; y < numRows; ++y) { - quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - // Convert BGR to RGB. - quint32 pixel = srcScanLine[x]; - destScanLine[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); - } - srcScanLine += sourceSize.width(); + for (int y = 0; y < numRows; ++y) { + quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); + for (int x = 0; x < numColumns; x++) { + quint32 pixel = convertABGRToARGB(srcScanLine[x]); + if (multiplied == Unmultiplied) + destScanLine[x] = premultipliedARGBFromColor(Color(pixel)); + else + destScanLine[x] = pixel; } + srcScanLine += sourceSize.width(); } bool isPainting = m_data.m_painter->isActive(); if (!isPainting) - m_data.m_painter->begin(&m_data.m_nativeImage); + m_data.m_painter->begin(&m_data.m_pixmap); else { m_data.m_painter->save(); @@ -362,7 +339,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c m_data.m_painter->restore(); } -static bool encodeImage(const QImage& image, const String& format, const double* quality, QByteArray& data) +static bool encodeImage(const QPixmap& pixmap, const String& format, const double* quality, QByteArray& data) { int compressionQuality = 100; if (quality && *quality >= 0.0 && *quality <= 1.0) @@ -370,7 +347,7 @@ static bool encodeImage(const QImage& image, const String& format, const double* QBuffer buffer(&data); buffer.open(QBuffer::WriteOnly); - bool success = image.save(&buffer, format.utf8().data(), compressionQuality); + bool success = pixmap.save(&buffer, format.utf8().data(), compressionQuality); buffer.close(); return success; @@ -382,10 +359,10 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo // QImageWriter does not support mimetypes. It does support Qt image formats (png, // gif, jpeg..., xpm) so skip the image/ to get the Qt image format used to encode - // the m_nativeImage image. + // the m_pixmap image. QByteArray data; - if (!encodeImage(m_data.m_nativeImage, mimeType.substring(sizeof "image"), quality, data)) + if (!encodeImage(m_data.m_pixmap, mimeType.substring(sizeof "image"), quality, data)) return "data:,"; return "data:" + mimeType + ";base64," + data.toBase64().data(); |