summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp')
-rw-r--r--Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp151
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();