From 840780151de2cd52677f7cde3662ce3b804a4c20 Mon Sep 17 00:00:00 2001
From: Benjamin Otte <otte@gnome.org>
Date: Tue, 13 Oct 2009 19:26:43 +0200
Subject: [PATCH 03/12] Make get*ImageData() functions use cairo

Only unpremultiplying is still done manually. I don't think there's a
way to do it with cairo yet.
---
 .../platform/graphics/cairo/ImageBufferCairo.cpp   |   85 ++++++-------------
 1 files changed, 27 insertions(+), 58 deletions(-)

diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index daafe97..a2c00aa 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -152,73 +152,42 @@ static cairo_surface_t * createSurfaceForImageData(ImageData* source, bool alpha
       format, source->width(), source->height(), source->width() * 4);
 }
 
-template <Multiply multiplied>
-PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
 {
-    ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
-
-    PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
-    unsigned char* dataSrc = cairo_image_surface_get_data(data.m_surface);
-    unsigned char* dataDst = result->data()->data()->data();
-
-    if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
-        memset(dataDst, 0, result->data()->length());
-
-    int originx = rect.x();
-    int destx = 0;
-    if (originx < 0) {
-        destx = -originx;
-        originx = 0;
-    }
-    int endx = rect.x() + rect.width();
-    if (endx > size.width())
-        endx = size.width();
-    int numColumns = endx - originx;
-
-    int originy = rect.y();
-    int desty = 0;
-    if (originy < 0) {
-        desty = -originy;
-        originy = 0;
-    }
-    int endy = rect.y() + rect.height();
-    if (endy > size.height())
-        endy = size.height();
-    int numRows = endy - originy;
-
-    int stride = cairo_image_surface_get_stride(data.m_surface);
-    unsigned destBytesPerRow = 4 * rect.width();
-
-    unsigned char* destRows = dataDst + desty * destBytesPerRow + destx * 4;
-    for (int y = 0; y < numRows; ++y) {
-        unsigned* row = reinterpret_cast<unsigned*>(dataSrc + stride * (y + originy));
-        for (int x = 0; x < numColumns; x++) {
-            int basex = x * 4;
-            unsigned* pixel = row + x + originx;
-            Color pixelColor;
-            if (multiplied == Unmultiplied)
-                pixelColor = colorFromPremultipliedARGB(*pixel);
-            else
-                pixelColor = Color(*pixel);
-            destRows[basex]     = pixelColor.red();
-            destRows[basex + 1] = pixelColor.green();
-            destRows[basex + 2] = pixelColor.blue();
-            destRows[basex + 3] = pixelColor.alpha();
+    RefPtr<ImageData> result = getPremultipliedImageData (rect);
+
+    /* unpremultiply data */
+    unsigned char* data = result->data()->data()->data();
+    unsigned size = result->width() * result->height();
+    for (unsigned i = 0; i < size; ++i) {
+        unsigned alpha = data[3];
+        if (alpha == 0)
+          data[0] = data[1] = data[2] = 0;
+        else {
+          data[0] = (data[0] * 255 + alpha / 2) / alpha;
+          data[1] = (data[1] * 255 + alpha / 2) / alpha;
+          data[2] = (data[2] * 255 + alpha / 2) / alpha;
         }
-        destRows += destBytesPerRow;
+        data += 4;
     }
 
     return result;
 }
 
-PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
-{
-    return getImageData<Unmultiplied>(rect, m_data, m_size);
-}
-
 PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
 {
-    return getImageData<Premultiplied>(rect, m_data, m_size);
+    RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
+    cairo_surface_t *result_surface = createSurfaceForImageData(&*result, true);
+    cairo_t *cr = cairo_create (result_surface);
+
+    cairo_set_source_surface (cr, m_data.m_surface, -rect.x(), -rect.y());
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    cairo_paint (cr);
+
+    cairo_destroy (cr);
+    cairo_surface_destroy (result_surface);
+
+    return result;
 }
 
 void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
-- 
1.6.3.3

