summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-02-03 12:51:13 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-02-03 12:51:13 +0000
commitd15a71f128c73ce1da19e6ff5a4e2fe044b58749 (patch)
tree913c314cdf14ddaef8998e23e6321b8fdacc36f7
parent10110d58cee179cded8e4c4ff8a8d02c477585bd (diff)
qt: Update for fallback compositor
We now need to explicitly manage fallbacks and to provide an implementation for map-to-image/unmap-image.
-rw-r--r--src/cairo-qt-surface.cpp210
1 files changed, 140 insertions, 70 deletions
diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp
index b75f5223..ce05dba7 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,