[cairo-commit] src/cairo-qt-surface.cpp

Chris Wilson ickle at kemper.freedesktop.org
Sun Feb 3 04:52:34 PST 2013


 src/cairo-qt-surface.cpp |  210 +++++++++++++++++++++++++++++++----------------
 1 file changed, 140 insertions(+), 70 deletions(-)

New commits:
commit d15a71f128c73ce1da19e6ff5a4e2fe044b58749
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 3 12:51:13 2013 +0000

    qt: Update for fallback compositor
    
    We now need to explicitly manage fallbacks and to provide an
    implementation for map-to-image/unmap-image.

diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp
index b75f522..ce05dba 100644
--- a/src/cairo-qt-surface.cpp
+++ b/src/cairo-qt-surface.cpp
@@ -48,6 +48,7 @@
 #include "cairo-image-surface-private.h"
 #include "cairo-pattern-private.h"
 #include "cairo-surface-backend-private.h"
+#include "cairo-surface-fallback-private.h"
 
 #include "cairo-ft.h"
 #include "cairo-qt.h"
@@ -64,7 +65,7 @@
 #include <QWidget>
 #include <QtCore/QVarLengthArray>
 
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)
+#if ((QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)) && 0
 extern void qt_draw_glyphs(QPainter *, const quint32 *glyphs, const QPointF *positions, int count);
 #endif
 
@@ -197,6 +198,9 @@ _qpainter_compositionmode_from_cairo_op (cairo_operator_t op)
 static bool
 _op_is_supported (cairo_qt_surface_t *qs, cairo_operator_t op)
 {
+    if (qs->p == NULL)
+	return false;
+
     if (qs->supports_porter_duff) {
 	switch (op) {
 	case CAIRO_OPERATOR_CLEAR:
@@ -555,32 +559,105 @@ _cairo_qt_surface_release_source_image (void *abstract_surface,
     cairo_surface_destroy (&image->base);
 }
 
-static cairo_status_t
-_cairo_qt_surface_acquire_dest_image (void *abstract_surface,
-				      cairo_rectangle_int_t *interest_rect,
-				      cairo_image_surface_t **image_out,
-				      cairo_rectangle_int_t *image_rect,
-				      void **image_extra)
+struct _qimage_surface {
+    cairo_image_surface_t image;
+    QImage *qimg;
+};
+
+static cairo_surface_t *
+map_qimage_to_image (QImage *qimg, const cairo_rectangle_int_t *extents)
 {
-    cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
-    QImage *qimg = NULL;
+    struct _qimage_surface  *surface;
+    pixman_image_t *pixman_image;
+    pixman_format_code_t pixman_format;
+    uint8_t *data;
 
-    D(fprintf(stderr, "q[%p] acquire_dest_image\n", abstract_surface));
+    if (qimg == NULL)
+        return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
 
-    *image_extra = NULL;
+    switch (qimg->format()) {
+    case QImage::Format_ARGB32_Premultiplied:
+	pixman_format = PIXMAN_a8r8g8b8;
+	break;
+    case QImage::Format_RGB32:
+	pixman_format = PIXMAN_x8r8g8b8;
+	break;
+    case QImage::Format_Indexed8: // XXX not quite
+	pixman_format = PIXMAN_a8;
+	break;
+#ifdef WORDS_BIGENDIAN
+    case QImage::Format_Mono:
+#else
+    case QImage::Format_MonoLSB:
+#endif
+	pixman_format = PIXMAN_a1;
+	break;
 
-    if (qs->image_equiv) {
-        *image_out = (cairo_image_surface_t*)
-                     cairo_surface_reference (qs->image_equiv);
+    case QImage::Format_Invalid:
+#ifdef WORDS_BIGENDIAN
+    case QImage::Format_MonoLSB:
+#else
+    case QImage::Format_Mono:
+#endif
+    case QImage::Format_ARGB32:
+    case QImage::Format_RGB16:
+    case QImage::Format_ARGB8565_Premultiplied:
+    case QImage::Format_RGB666:
+    case QImage::Format_ARGB6666_Premultiplied:
+    case QImage::Format_RGB555:
+    case QImage::Format_ARGB8555_Premultiplied:
+    case QImage::Format_RGB888:
+    case QImage::Format_RGB444:
+    case QImage::Format_ARGB4444_Premultiplied:
+    case QImage::NImageFormats:
+    default:
+	delete qimg;
+	return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_FORMAT);
+    }
 
-        image_rect->x = qs->window.x();
-        image_rect->y = qs->window.y();
-        image_rect->width = qs->window.width();
-        image_rect->height = qs->window.height();
+    data = qimg->bits();
+    data += extents->y * qimg->bytesPerLine();
+    data += extents->x * PIXMAN_FORMAT_BPP (pixman_format) / 8;
+
+    pixman_image = pixman_image_create_bits (pixman_format,
+					     extents->width,
+					     extents->height,
+					     (uint32_t *)data,
+					     qimg->bytesPerLine());
+    if (pixman_image == NULL) {
+	delete qimg;
+	return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
-        return CAIRO_STATUS_SUCCESS;
+    surface = (struct _qimage_surface *) malloc (sizeof(*surface));
+    if (unlikely (surface == NULL)) {
+	pixman_image_unref (pixman_image);
+	delete qimg;
+	return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
     }
 
+    _cairo_image_surface_init (&surface->image, pixman_image, pixman_format);
+    surface->qimg = qimg;
+
+    cairo_surface_set_device_offset (&surface->image.base,
+				     -extents->x, -extents->y);
+
+    return &surface->image.base;
+}
+
+static cairo_image_surface_t *
+_cairo_qt_surface_map_to_image (void *abstract_surface,
+				const cairo_rectangle_int_t *extents)
+{
+    cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
+    QImage *qimg = NULL;
+
+    D(fprintf(stderr, "q[%p] acquire_dest_image\n", abstract_surface));
+
+    if (qs->image_equiv)
+	return _cairo_image_surface_map_to_image (qs->image_equiv,
+						  extents);
+
     QPoint offset;
 
     if (qs->pixmap) {
@@ -590,7 +667,7 @@ _cairo_qt_surface_acquire_dest_image (void *abstract_surface,
         // how we can grab an image from it
         QPaintDevice *pd = qs->p->device();
 	if (!pd)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_image_surface_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
 
 	QPaintDevice *rpd = QPainter::redirected(pd, &offset);
 	if (rpd)
@@ -605,50 +682,42 @@ _cairo_qt_surface_acquire_dest_image (void *abstract_surface,
         }
     }
 
-    if (qimg == NULL)
-        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    *image_out = (cairo_image_surface_t*)
-                 cairo_image_surface_create_for_data (qimg->bits(),
-                                                      _cairo_format_from_qimage_format (qimg->format()),
-                                                      qimg->width(), qimg->height(),
-                                                      qimg->bytesPerLine());
-    *image_extra = qimg;
-
-    image_rect->x = qs->window.x() + offset.x();
-    image_rect->y = qs->window.y() + offset.y();
-    image_rect->width = qs->window.width() - offset.x();
-    image_rect->height = qs->window.height() - offset.y();
-
-    return CAIRO_STATUS_SUCCESS;
+    return (cairo_image_surface_t *) map_qimage_to_image (qimg, extents);
 }
 
-static void
-_cairo_qt_surface_release_dest_image (void *abstract_surface,
-				      cairo_rectangle_int_t *interest_rect,
-				      cairo_image_surface_t *image,
-				      cairo_rectangle_int_t *image_rect,
-				      void *image_extra)
+static cairo_int_status_t
+_cairo_qt_surface_unmap_image (void *abstract_surface,
+			       cairo_image_surface_t *image)
 {
     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
-    D(fprintf(stderr, "q[%p] release_dest_image\n", abstract_surface));
 
-    cairo_surface_destroy (&image->base);
+    D(fprintf(stderr, "q[%p] release_dest_image\n", abstract_surface));
 
-    if (image_extra) {
-        QImage *qimg = (QImage*) image_extra;
+    if (!qs->image_equiv) {
+	struct _qimage_surface  *qimage = (struct _qimage_surface  *)image;
 
         // XXX should I be using setBackgroundMode here instead of setCompositionMode?
         if (qs->supports_porter_duff)
             qs->p->setCompositionMode (QPainter::CompositionMode_Source);
 
-        qs->p->drawImage (image_rect->x, image_rect->y, *qimg);
+        qs->p->drawImage ((int)qimage->image.base.device_transform.x0,
+			  (int)qimage->image.base.device_transform.y0,
+			  *qimage->qimg,
+			  (int)qimage->image.base.device_transform.x0,
+			  (int)qimage->image.base.device_transform.y0,
+			  (int)qimage->image.width,
+			  (int)qimage->image.height);
 
         if (qs->supports_porter_duff)
             qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
 
-        delete qimg;
+	delete qimage->qimg;
     }
+
+    cairo_surface_finish (&image->base);
+    cairo_surface_destroy (&image->base);
+
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
 static cairo_bool_t
@@ -1212,11 +1281,8 @@ _cairo_qt_surface_paint (void *abstract_surface,
 
     D(fprintf(stderr, "q[%p] paint op:%s\n", abstract_surface, _opstr(op)));
 
-    if (!qs->p)
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
     if (! _op_is_supported (qs, op))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _cairo_surface_fallback_paint (abstract_surface, op, source, clip);
 
     status = _cairo_qt_surface_set_clip (qs, clip);
     if (unlikely (status))
@@ -1250,11 +1316,10 @@ _cairo_qt_surface_fill (void *abstract_surface,
 
     D(fprintf(stderr, "q[%p] fill op:%s\n", abstract_surface, _opstr(op)));
 
-    if (!qs->p)
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
     if (! _op_is_supported (qs, op))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _cairo_surface_fallback_fill (abstract_surface, op,
+					     source, path, fill_rule,
+					     tolerance, antialias, clip);
 
     cairo_int_status_t status = _cairo_qt_surface_set_clip (qs, clip);
     if (unlikely (status))
@@ -1297,17 +1362,16 @@ _cairo_qt_surface_stroke (void *abstract_surface,
 
     D(fprintf(stderr, "q[%p] stroke op:%s\n", abstract_surface, _opstr(op)));
 
-    if (!qs->p)
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
     if (! _op_is_supported (qs, op))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	return _cairo_surface_fallback_stroke (abstract_surface, op,
+					       source, path, style, ctm,
+					       ctm_inverse, tolerance,
+					       antialias, clip);
 
     cairo_int_status_t int_status = _cairo_qt_surface_set_clip (qs, clip);
     if (unlikely (int_status))
 	return int_status;
 
-
     QMatrix savedMatrix = qs->p->worldMatrix();
 
     if (qs->supports_porter_duff)
@@ -1342,7 +1406,7 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
 			       cairo_scaled_font_t *scaled_font,
 			       const cairo_clip_t *clip)
 {
-#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)
+#if ((QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)) && 0
     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
 
     // pick out the colour to use from the cairo source
@@ -1374,7 +1438,9 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
     _cairo_scaled_font_thaw_cache(scaled_font);
     return CAIRO_INT_STATUS_SUCCESS;
 #else
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    return _cairo_surface_fallback_glyphs (abstract_surface, op,
+					   source, glyphs, num_glyphs,
+					   scaled_font, clip);
 #endif
 }
 
@@ -1389,10 +1455,7 @@ _cairo_qt_surface_mask (void *abstract_surface,
 
     D(fprintf(stderr, "q[%p] mask op:%s\n", abstract_surface, _opstr(op)));
 
-    if (!qs->p)
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
+    if (qs->p && mask->type == CAIRO_PATTERN_TYPE_SOLID) {
         cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
         cairo_int_status_t result;
 
@@ -1406,7 +1469,7 @@ _cairo_qt_surface_mask (void *abstract_surface,
     }
 
     // otherwise skip for now
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    return _cairo_surface_fallback_mask (abstract_surface, op, source, mask, clip);
 }
 
 static cairo_status_t
@@ -1429,21 +1492,28 @@ _cairo_qt_surface_mark_dirty (void *abstract_surface,
 static const cairo_surface_backend_t cairo_qt_surface_backend = {
     CAIRO_SURFACE_TYPE_QT,
     _cairo_qt_surface_finish,
+
     _cairo_default_context_create, /* XXX */
+
     _cairo_qt_surface_create_similar,
     NULL, /* similar image */
-    NULL, /* map to image */
-    NULL, /* unmap image */
+    _cairo_qt_surface_map_to_image,
+    _cairo_qt_surface_unmap_image,
+
     _cairo_surface_default_source,
     _cairo_qt_surface_acquire_source_image,
     _cairo_qt_surface_release_source_image,
     NULL, /* snapshot */
+
     NULL, /* copy_page */
     NULL, /* show_page */
+
     _cairo_qt_surface_get_extents,
     NULL, /* get_font_options */
+
     NULL, /* flush */
     _cairo_qt_surface_mark_dirty,
+
     _cairo_qt_surface_paint,
     _cairo_qt_surface_mask,
     _cairo_qt_surface_stroke,


More information about the cairo-commit mailing list