Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
  2. /* cairo - a vector graphics library with display and print output
  3.  *
  4.  * Copyright © 2008 Mozilla Corporation
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it either under the terms of the GNU Lesser General Public
  8.  * License version 2.1 as published by the Free Software Foundation
  9.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  10.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  11.  * notice, a recipient may use your version of this file under either
  12.  * the MPL or the LGPL.
  13.  *
  14.  * You should have received a copy of the LGPL along with this library
  15.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  17.  * You should have received a copy of the MPL along with this library
  18.  * in the file COPYING-MPL-1.1
  19.  *
  20.  * The contents of this file are subject to the Mozilla Public License
  21.  * Version 1.1 (the "License"); you may not use this file except in
  22.  * compliance with the License. You may obtain a copy of the License at
  23.  * http://www.mozilla.org/MPL/
  24.  *
  25.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  26.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  27.  * the specific language governing rights and limitations.
  28.  *
  29.  * The Original Code is the cairo graphics library.
  30.  *
  31.  * The Initial Developer of the Original Code is Mozilla Corporation.
  32.  *
  33.  * Contributor(s):
  34.  *      Vladimir Vukicevic <vladimir@mozilla.com>
  35.  */
  36.  
  37. /* Get INT16_MIN etc. as per C99 */
  38. #define __STDC_LIMIT_MACROS
  39.  
  40. #include "cairoint.h"
  41.  
  42. #include "cairo-clip-private.h"
  43. #include "cairo-default-context-private.h"
  44. #include "cairo-error-private.h"
  45. #include "cairo-region-private.h"
  46. #include "cairo-surface-clipper-private.h"
  47. #include "cairo-types-private.h"
  48. #include "cairo-image-surface-private.h"
  49. #include "cairo-pattern-private.h"
  50. #include "cairo-surface-backend-private.h"
  51. #include "cairo-surface-fallback-private.h"
  52.  
  53. #include "cairo-ft.h"
  54. #include "cairo-qt.h"
  55.  
  56. #include <memory>
  57.  
  58. #include <QtGui/QPainter>
  59. #include <QtGui/QPaintEngine>
  60. #include <QtGui/QPaintDevice>
  61. #include <QtGui/QImage>
  62. #include <QtGui/QPixmap>
  63. #include <QtGui/QBrush>
  64. #include <QtGui/QPen>
  65. #include <QWidget>
  66. #include <QtCore/QVarLengthArray>
  67.  
  68. #if ((QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)) && 0
  69. extern void qt_draw_glyphs(QPainter *, const quint32 *glyphs, const QPointF *positions, int count);
  70. #endif
  71.  
  72. #include <sys/time.h>
  73.  
  74. /* Enable workaround slow regional Qt paths */
  75. #define ENABLE_FAST_FILL 0
  76. #define ENABLE_FAST_CLIP 0
  77.  
  78. #if 0
  79. #define D(x)  x
  80. static const char *
  81. _opstr (cairo_operator_t op)
  82. {
  83.     const char *ops[] = {
  84.         "CLEAR",
  85.         "SOURCE",
  86.         "OVER",
  87.         "IN",
  88.         "OUT",
  89.         "ATOP",
  90.         "DEST",
  91.         "DEST_OVER",
  92.         "DEST_IN",
  93.         "DEST_OUT",
  94.         "DEST_ATOP",
  95.         "XOR",
  96.         "ADD",
  97.         "SATURATE"
  98.     };
  99.  
  100.     if (op < CAIRO_OPERATOR_CLEAR || op > CAIRO_OPERATOR_SATURATE)
  101.         return "(\?\?\?)";
  102.  
  103.     return ops[op];
  104. }
  105. #else
  106. #define D(x) do { } while(0)
  107. #endif
  108.  
  109. #ifndef CAIRO_INT_STATUS_SUCCESS
  110. #define CAIRO_INT_STATUS_SUCCESS ((cairo_int_status_t) CAIRO_STATUS_SUCCESS)
  111. #endif
  112.  
  113. /* Qt::PenStyle optimization based on the assumption that dots are 1*w and dashes are 3*w. */
  114. #define DOT_LENGTH  1.0
  115. #define DASH_LENGTH 3.0
  116.  
  117. struct cairo_qt_surface_t {
  118.     cairo_surface_t base;
  119.  
  120.     cairo_bool_t supports_porter_duff;
  121.  
  122.     QPainter *p;
  123.  
  124.     /* The pixmap/image constructors will store their objects here */
  125.     QPixmap *pixmap;
  126.     QImage *image;
  127.  
  128.     QRect window;
  129.  
  130.     cairo_surface_clipper_t clipper;
  131.  
  132.     cairo_surface_t *image_equiv;
  133. };
  134.  
  135. /* Will be true if we ever try to create a QPixmap and end
  136.  * up with one without an alpha channel.
  137.  */
  138. static cairo_bool_t _qpixmaps_have_no_alpha = FALSE;
  139.  
  140. /*
  141.  * Helper methods
  142.  */
  143.  
  144. static QPainter::CompositionMode
  145. _qpainter_compositionmode_from_cairo_op (cairo_operator_t op)
  146. {
  147.     switch (op) {
  148.     case CAIRO_OPERATOR_CLEAR:
  149.         return QPainter::CompositionMode_Clear;
  150.  
  151.     case CAIRO_OPERATOR_SOURCE:
  152.         return QPainter::CompositionMode_Source;
  153.     case CAIRO_OPERATOR_OVER:
  154.         return QPainter::CompositionMode_SourceOver;
  155.     case CAIRO_OPERATOR_IN:
  156.         return QPainter::CompositionMode_SourceIn;
  157.     case CAIRO_OPERATOR_OUT:
  158.         return QPainter::CompositionMode_SourceOut;
  159.     case CAIRO_OPERATOR_ATOP:
  160.         return QPainter::CompositionMode_SourceAtop;
  161.  
  162.     case CAIRO_OPERATOR_DEST:
  163.         return QPainter::CompositionMode_Destination;
  164.     case CAIRO_OPERATOR_DEST_OVER:
  165.         return QPainter::CompositionMode_DestinationOver;
  166.     case CAIRO_OPERATOR_DEST_IN:
  167.         return QPainter::CompositionMode_DestinationIn;
  168.     case CAIRO_OPERATOR_DEST_OUT:
  169.         return QPainter::CompositionMode_DestinationOut;
  170.     case CAIRO_OPERATOR_DEST_ATOP:
  171.         return QPainter::CompositionMode_DestinationAtop;
  172.  
  173.     case CAIRO_OPERATOR_XOR:
  174.         return QPainter::CompositionMode_Xor;
  175.  
  176.     default:
  177.     case CAIRO_OPERATOR_ADD:
  178.     case CAIRO_OPERATOR_SATURATE:
  179.     case CAIRO_OPERATOR_MULTIPLY:
  180.     case CAIRO_OPERATOR_SCREEN:
  181.     case CAIRO_OPERATOR_OVERLAY:
  182.     case CAIRO_OPERATOR_DARKEN:
  183.     case CAIRO_OPERATOR_LIGHTEN:
  184.     case CAIRO_OPERATOR_COLOR_DODGE:
  185.     case CAIRO_OPERATOR_COLOR_BURN:
  186.     case CAIRO_OPERATOR_HARD_LIGHT:
  187.     case CAIRO_OPERATOR_SOFT_LIGHT:
  188.     case CAIRO_OPERATOR_DIFFERENCE:
  189.     case CAIRO_OPERATOR_EXCLUSION:
  190.     case CAIRO_OPERATOR_HSL_HUE:
  191.     case CAIRO_OPERATOR_HSL_SATURATION:
  192.     case CAIRO_OPERATOR_HSL_COLOR:
  193.     case CAIRO_OPERATOR_HSL_LUMINOSITY:
  194.         ASSERT_NOT_REACHED;
  195.     }
  196. }
  197.  
  198. static bool
  199. _op_is_supported (cairo_qt_surface_t *qs, cairo_operator_t op)
  200. {
  201.     if (qs->p == NULL)
  202.         return false;
  203.  
  204.     if (qs->supports_porter_duff) {
  205.         switch (op) {
  206.         case CAIRO_OPERATOR_CLEAR:
  207.         case CAIRO_OPERATOR_SOURCE:
  208.         case CAIRO_OPERATOR_OVER:
  209.         case CAIRO_OPERATOR_IN:
  210.         case CAIRO_OPERATOR_OUT:
  211.         case CAIRO_OPERATOR_ATOP:
  212.  
  213.         case CAIRO_OPERATOR_DEST:
  214.         case CAIRO_OPERATOR_DEST_OVER:
  215.         case CAIRO_OPERATOR_DEST_IN:
  216.         case CAIRO_OPERATOR_DEST_OUT:
  217.         case CAIRO_OPERATOR_DEST_ATOP:
  218.  
  219.         case CAIRO_OPERATOR_XOR:
  220.             return TRUE;
  221.  
  222.         default:
  223.             ASSERT_NOT_REACHED;
  224.         case CAIRO_OPERATOR_ADD:
  225.         case CAIRO_OPERATOR_SATURATE:
  226.         case CAIRO_OPERATOR_MULTIPLY:
  227.         case CAIRO_OPERATOR_SCREEN:
  228.         case CAIRO_OPERATOR_OVERLAY:
  229.         case CAIRO_OPERATOR_DARKEN:
  230.         case CAIRO_OPERATOR_LIGHTEN:
  231.         case CAIRO_OPERATOR_COLOR_DODGE:
  232.         case CAIRO_OPERATOR_COLOR_BURN:
  233.         case CAIRO_OPERATOR_HARD_LIGHT:
  234.         case CAIRO_OPERATOR_SOFT_LIGHT:
  235.         case CAIRO_OPERATOR_DIFFERENCE:
  236.         case CAIRO_OPERATOR_EXCLUSION:
  237.         case CAIRO_OPERATOR_HSL_HUE:
  238.         case CAIRO_OPERATOR_HSL_SATURATION:
  239.         case CAIRO_OPERATOR_HSL_COLOR:
  240.         case CAIRO_OPERATOR_HSL_LUMINOSITY:
  241.             return FALSE;
  242.  
  243.         }
  244.     } else {
  245.         return op == CAIRO_OPERATOR_OVER;
  246.     }
  247. }
  248.  
  249. static cairo_format_t
  250. _cairo_format_from_qimage_format (QImage::Format fmt)
  251. {
  252.     switch (fmt) {
  253.     case QImage::Format_ARGB32_Premultiplied:
  254.         return CAIRO_FORMAT_ARGB32;
  255.     case QImage::Format_RGB32:
  256.         return CAIRO_FORMAT_RGB24;
  257.     case QImage::Format_Indexed8: // XXX not quite
  258.         return CAIRO_FORMAT_A8;
  259. #ifdef WORDS_BIGENDIAN
  260.     case QImage::Format_Mono:
  261. #else
  262.     case QImage::Format_MonoLSB:
  263. #endif
  264.         return CAIRO_FORMAT_A1;
  265.  
  266.     case QImage::Format_Invalid:
  267. #ifdef WORDS_BIGENDIAN
  268.     case QImage::Format_MonoLSB:
  269. #else
  270.     case QImage::Format_Mono:
  271. #endif
  272.     case QImage::Format_ARGB32:
  273.     case QImage::Format_RGB16:
  274.     case QImage::Format_ARGB8565_Premultiplied:
  275.     case QImage::Format_RGB666:
  276.     case QImage::Format_ARGB6666_Premultiplied:
  277.     case QImage::Format_RGB555:
  278.     case QImage::Format_ARGB8555_Premultiplied:
  279.     case QImage::Format_RGB888:
  280.     case QImage::Format_RGB444:
  281.     case QImage::Format_ARGB4444_Premultiplied:
  282.     case QImage::NImageFormats:
  283.     default:
  284.         ASSERT_NOT_REACHED;
  285.         return (cairo_format_t) -1;
  286.     }
  287. }
  288.  
  289. static QImage::Format
  290. _qimage_format_from_cairo_format (cairo_format_t fmt)
  291. {
  292.     switch (fmt) {
  293.     case CAIRO_FORMAT_INVALID:
  294.         ASSERT_NOT_REACHED;
  295.     case CAIRO_FORMAT_ARGB32:
  296.         return QImage::Format_ARGB32_Premultiplied;
  297.     case CAIRO_FORMAT_RGB24:
  298.         return QImage::Format_RGB32;
  299.     case CAIRO_FORMAT_RGB16_565:
  300.         return QImage::Format_RGB16;
  301.     case CAIRO_FORMAT_A8:
  302.         return QImage::Format_Indexed8; // XXX not quite
  303.     case CAIRO_FORMAT_A1:
  304. #ifdef WORDS_BIGENDIAN
  305.         return QImage::Format_Mono; // XXX think we need to choose between this and LSB
  306. #else
  307.         return QImage::Format_MonoLSB;
  308. #endif
  309.     }
  310.  
  311.     return QImage::Format_Mono;
  312. }
  313.  
  314. static inline QMatrix
  315. _qmatrix_from_cairo_matrix (const cairo_matrix_t& m)
  316. {
  317.     return QMatrix(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
  318. }
  319.  
  320. /* Path conversion */
  321. typedef struct _qpainter_path_transform {
  322.     QPainterPath path;
  323.     const cairo_matrix_t *ctm_inverse;
  324. } qpainter_path_data;
  325.  
  326. /* cairo path -> execute in context */
  327. static cairo_status_t
  328. _cairo_path_to_qpainterpath_move_to (void *closure, const cairo_point_t *point)
  329. {
  330.     qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure);
  331.     double x = _cairo_fixed_to_double (point->x);
  332.     double y = _cairo_fixed_to_double (point->y);
  333.  
  334.     if (pdata->ctm_inverse)
  335.         cairo_matrix_transform_point (pdata->ctm_inverse, &x, &y);
  336.  
  337.     pdata->path.moveTo(x, y);
  338.  
  339.     return CAIRO_STATUS_SUCCESS;
  340. }
  341.  
  342. static cairo_status_t
  343. _cairo_path_to_qpainterpath_line_to (void *closure, const cairo_point_t *point)
  344. {
  345.     qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure);
  346.     double x = _cairo_fixed_to_double (point->x);
  347.     double y = _cairo_fixed_to_double (point->y);
  348.  
  349.     if (pdata->ctm_inverse)
  350.         cairo_matrix_transform_point (pdata->ctm_inverse, &x, &y);
  351.  
  352.     pdata->path.lineTo(x, y);
  353.  
  354.     return CAIRO_STATUS_SUCCESS;
  355. }
  356.  
  357. static cairo_status_t
  358. _cairo_path_to_qpainterpath_curve_to (void *closure, const cairo_point_t *p0, const cairo_point_t *p1, const cairo_point_t *p2)
  359. {
  360.     qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure);
  361.     double x0 = _cairo_fixed_to_double (p0->x);
  362.     double y0 = _cairo_fixed_to_double (p0->y);
  363.     double x1 = _cairo_fixed_to_double (p1->x);
  364.     double y1 = _cairo_fixed_to_double (p1->y);
  365.     double x2 = _cairo_fixed_to_double (p2->x);
  366.     double y2 = _cairo_fixed_to_double (p2->y);
  367.  
  368.     if (pdata->ctm_inverse) {
  369.         cairo_matrix_transform_point (pdata->ctm_inverse, &x0, &y0);
  370.         cairo_matrix_transform_point (pdata->ctm_inverse, &x1, &y1);
  371.         cairo_matrix_transform_point (pdata->ctm_inverse, &x2, &y2);
  372.     }
  373.  
  374.     pdata->path.cubicTo (x0, y0, x1, y1, x2, y2);
  375.  
  376.     return CAIRO_STATUS_SUCCESS;
  377. }
  378.  
  379. static cairo_status_t
  380. _cairo_path_to_qpainterpath_close_path (void *closure)
  381. {
  382.     qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure);
  383.  
  384.     pdata->path.closeSubpath();
  385.  
  386.     return CAIRO_STATUS_SUCCESS;
  387. }
  388.  
  389. static inline QPainterPath
  390. path_to_qt (const cairo_path_fixed_t *path,
  391.             const cairo_matrix_t *ctm_inverse = NULL)
  392. {
  393.     qpainter_path_data data;
  394.     cairo_status_t status;
  395.  
  396.     if (ctm_inverse && _cairo_matrix_is_identity (ctm_inverse))
  397.         ctm_inverse = NULL;
  398.     data.ctm_inverse = ctm_inverse;
  399.  
  400.     status = _cairo_path_fixed_interpret (path,
  401.                                           _cairo_path_to_qpainterpath_move_to,
  402.                                           _cairo_path_to_qpainterpath_line_to,
  403.                                           _cairo_path_to_qpainterpath_curve_to,
  404.                                           _cairo_path_to_qpainterpath_close_path,
  405.                                           &data);
  406.     assert (status == CAIRO_STATUS_SUCCESS);
  407.  
  408.     return data.path;
  409. }
  410.  
  411. static inline QPainterPath
  412. path_to_qt (const cairo_path_fixed_t *path,
  413.             cairo_fill_rule_t fill_rule,
  414.             cairo_matrix_t *ctm_inverse = NULL)
  415. {
  416.     QPainterPath qpath = path_to_qt (path, ctm_inverse);
  417.  
  418.     qpath.setFillRule (fill_rule == CAIRO_FILL_RULE_WINDING ?
  419.                         Qt::WindingFill :
  420.                         Qt::OddEvenFill);
  421.  
  422.     return qpath;
  423. }
  424.  
  425. /*
  426.  * Surface backend methods
  427.  */
  428. static cairo_surface_t *
  429. _cairo_qt_surface_create_similar (void *abstract_surface,
  430.                                   cairo_content_t content,
  431.                                   int width,
  432.                                   int height)
  433. {
  434.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  435.     bool use_pixmap;
  436.  
  437.     D(fprintf(stderr, "q[%p] create_similar: %d %d [%d] -> ", abstract_surface, width, height, content));
  438.  
  439.     use_pixmap = qs->image == NULL;
  440.     if (use_pixmap) {
  441.         switch (content) {
  442.         case CAIRO_CONTENT_ALPHA:
  443.             use_pixmap = FALSE;
  444.             break;
  445.         case CAIRO_CONTENT_COLOR:
  446.             break;
  447.         case CAIRO_CONTENT_COLOR_ALPHA:
  448.             use_pixmap = ! _qpixmaps_have_no_alpha;
  449.             break;
  450.         }
  451.     }
  452.  
  453.     if (use_pixmap) {
  454.         cairo_surface_t *result =
  455.             cairo_qt_surface_create_with_qpixmap (content, width, height);
  456.  
  457.         /* XXX result->content is always content. ??? */
  458.         if (result->content == content) {
  459.             D(fprintf(stderr, "qpixmap content: %d\n", content));
  460.             return result;
  461.         }
  462.  
  463.         _qpixmaps_have_no_alpha = TRUE;
  464.         cairo_surface_destroy (result);
  465.     }
  466.  
  467.     D(fprintf (stderr, "qimage\n"));
  468.     return cairo_qt_surface_create_with_qimage
  469.         (_cairo_format_from_content (content), width, height);
  470. }
  471.  
  472. static cairo_status_t
  473. _cairo_qt_surface_finish (void *abstract_surface)
  474. {
  475.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  476.  
  477.     D(fprintf(stderr, "q[%p] finish\n", abstract_surface));
  478.  
  479.     /* Only delete p if we created it */
  480.     if (qs->image || qs->pixmap)
  481.         delete qs->p;
  482.     else
  483.         qs->p->restore ();
  484.  
  485.     if (qs->image_equiv)
  486.         cairo_surface_destroy (qs->image_equiv);
  487.  
  488.     _cairo_surface_clipper_reset (&qs->clipper);
  489.  
  490.     if (qs->image)
  491.         delete qs->image;
  492.  
  493.     if (qs->pixmap)
  494.         delete qs->pixmap;
  495.  
  496.     return CAIRO_STATUS_SUCCESS;
  497. }
  498.  
  499. static void
  500. _qimg_destroy (void *closure)
  501. {
  502.     QImage *qimg = (QImage *) closure;
  503.     delete qimg;
  504. }
  505.  
  506. static cairo_status_t
  507. _cairo_qt_surface_acquire_source_image (void *abstract_surface,
  508.                                         cairo_image_surface_t **image_out,
  509.                                         void **image_extra)
  510. {
  511.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  512.  
  513.     D(fprintf(stderr, "q[%p] acquire_source_image\n", abstract_surface));
  514.  
  515.     *image_extra = NULL;
  516.  
  517.     if (qs->image_equiv) {
  518.         *image_out = (cairo_image_surface_t*)
  519.                      cairo_surface_reference (qs->image_equiv);
  520.  
  521.         return CAIRO_STATUS_SUCCESS;
  522.     }
  523.  
  524.     if (qs->pixmap) {
  525.         QImage *qimg = new QImage(qs->pixmap->toImage());
  526.         cairo_surface_t *image;
  527.         cairo_status_t status;
  528.  
  529.         image = cairo_image_surface_create_for_data (qimg->bits(),
  530.                                                      _cairo_format_from_qimage_format (qimg->format()),
  531.                                                      qimg->width(), qimg->height(),
  532.                                                      qimg->bytesPerLine());
  533.  
  534.         status = _cairo_user_data_array_set_data (&image->user_data,
  535.                                                   (const cairo_user_data_key_t *)&_qimg_destroy,
  536.                                                   qimg,
  537.                                                   _qimg_destroy);
  538.         if (status) {
  539.             cairo_surface_destroy (image);
  540.             return status;
  541.         }
  542.  
  543.         *image_out = (cairo_image_surface_t *) image;
  544.         return CAIRO_STATUS_SUCCESS;
  545.     }
  546.  
  547.     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  548. }
  549.  
  550. static void
  551. _cairo_qt_surface_release_source_image (void *abstract_surface,
  552.                                         cairo_image_surface_t *image,
  553.                                         void *image_extra)
  554. {
  555.     //cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  556.  
  557.     D(fprintf(stderr, "q[%p] release_source_image\n", abstract_surface));
  558.  
  559.     cairo_surface_destroy (&image->base);
  560. }
  561.  
  562. struct _qimage_surface {
  563.     cairo_image_surface_t image;
  564.     QImage *qimg;
  565. };
  566.  
  567. static cairo_surface_t *
  568. map_qimage_to_image (QImage *qimg, const cairo_rectangle_int_t *extents)
  569. {
  570.     struct _qimage_surface  *surface;
  571.     pixman_image_t *pixman_image;
  572.     pixman_format_code_t pixman_format;
  573.     uint8_t *data;
  574.  
  575.     if (qimg == NULL)
  576.         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  577.  
  578.     switch (qimg->format()) {
  579.     case QImage::Format_ARGB32_Premultiplied:
  580.         pixman_format = PIXMAN_a8r8g8b8;
  581.         break;
  582.     case QImage::Format_RGB32:
  583.         pixman_format = PIXMAN_x8r8g8b8;
  584.         break;
  585.     case QImage::Format_Indexed8: // XXX not quite
  586.         pixman_format = PIXMAN_a8;
  587.         break;
  588. #ifdef WORDS_BIGENDIAN
  589.     case QImage::Format_Mono:
  590. #else
  591.     case QImage::Format_MonoLSB:
  592. #endif
  593.         pixman_format = PIXMAN_a1;
  594.         break;
  595.  
  596.     case QImage::Format_Invalid:
  597. #ifdef WORDS_BIGENDIAN
  598.     case QImage::Format_MonoLSB:
  599. #else
  600.     case QImage::Format_Mono:
  601. #endif
  602.     case QImage::Format_ARGB32:
  603.     case QImage::Format_RGB16:
  604.     case QImage::Format_ARGB8565_Premultiplied:
  605.     case QImage::Format_RGB666:
  606.     case QImage::Format_ARGB6666_Premultiplied:
  607.     case QImage::Format_RGB555:
  608.     case QImage::Format_ARGB8555_Premultiplied:
  609.     case QImage::Format_RGB888:
  610.     case QImage::Format_RGB444:
  611.     case QImage::Format_ARGB4444_Premultiplied:
  612.     case QImage::NImageFormats:
  613.     default:
  614.         delete qimg;
  615.         return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_FORMAT);
  616.     }
  617.  
  618.     data = qimg->bits();
  619.     data += extents->y * qimg->bytesPerLine();
  620.     data += extents->x * PIXMAN_FORMAT_BPP (pixman_format) / 8;
  621.  
  622.     pixman_image = pixman_image_create_bits (pixman_format,
  623.                                              extents->width,
  624.                                              extents->height,
  625.                                              (uint32_t *)data,
  626.                                              qimg->bytesPerLine());
  627.     if (pixman_image == NULL) {
  628.         delete qimg;
  629.         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  630.     }
  631.  
  632.     surface = (struct _qimage_surface *) malloc (sizeof(*surface));
  633.     if (unlikely (surface == NULL)) {
  634.         pixman_image_unref (pixman_image);
  635.         delete qimg;
  636.         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  637.     }
  638.  
  639.     _cairo_image_surface_init (&surface->image, pixman_image, pixman_format);
  640.     surface->qimg = qimg;
  641.  
  642.     cairo_surface_set_device_offset (&surface->image.base,
  643.                                      -extents->x, -extents->y);
  644.  
  645.     return &surface->image.base;
  646. }
  647.  
  648. static cairo_image_surface_t *
  649. _cairo_qt_surface_map_to_image (void *abstract_surface,
  650.                                 const cairo_rectangle_int_t *extents)
  651. {
  652.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  653.     QImage *qimg = NULL;
  654.  
  655.     D(fprintf(stderr, "q[%p] acquire_dest_image\n", abstract_surface));
  656.  
  657.     if (qs->image_equiv)
  658.         return _cairo_image_surface_map_to_image (qs->image_equiv,
  659.                                                   extents);
  660.  
  661.     QPoint offset;
  662.  
  663.     if (qs->pixmap) {
  664.         qimg = new QImage(qs->pixmap->toImage());
  665.     } else {
  666.         // Try to figure out what kind of QPaintDevice we have, and
  667.         // how we can grab an image from it
  668.         QPaintDevice *pd = qs->p->device();
  669.         if (!pd)
  670.             return (cairo_image_surface_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  671.  
  672.         QPaintDevice *rpd = QPainter::redirected(pd, &offset);
  673.         if (rpd)
  674.             pd = rpd;
  675.  
  676.         if (pd->devType() == QInternal::Image) {
  677.             qimg = new QImage(((QImage*) pd)->copy());
  678.         } else if (pd->devType() == QInternal::Pixmap) {
  679.             qimg = new QImage(((QPixmap*) pd)->toImage());
  680.         } else if (pd->devType() == QInternal::Widget) {
  681.             qimg = new QImage(QPixmap::grabWindow(((QWidget*)pd)->winId()).toImage());
  682.         }
  683.     }
  684.  
  685.     return (cairo_image_surface_t *) map_qimage_to_image (qimg, extents);
  686. }
  687.  
  688. static cairo_int_status_t
  689. _cairo_qt_surface_unmap_image (void *abstract_surface,
  690.                                cairo_image_surface_t *image)
  691. {
  692.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  693.  
  694.     D(fprintf(stderr, "q[%p] release_dest_image\n", abstract_surface));
  695.  
  696.     if (!qs->image_equiv) {
  697.         struct _qimage_surface  *qimage = (struct _qimage_surface  *)image;
  698.  
  699.         // XXX should I be using setBackgroundMode here instead of setCompositionMode?
  700.         if (qs->supports_porter_duff)
  701.             qs->p->setCompositionMode (QPainter::CompositionMode_Source);
  702.  
  703.         qs->p->drawImage ((int)qimage->image.base.device_transform.x0,
  704.                           (int)qimage->image.base.device_transform.y0,
  705.                           *qimage->qimg,
  706.                           (int)qimage->image.base.device_transform.x0,
  707.                           (int)qimage->image.base.device_transform.y0,
  708.                           (int)qimage->image.width,
  709.                           (int)qimage->image.height);
  710.  
  711.         if (qs->supports_porter_duff)
  712.             qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
  713.  
  714.         delete qimage->qimg;
  715.     }
  716.  
  717.     cairo_surface_finish (&image->base);
  718.     cairo_surface_destroy (&image->base);
  719.  
  720.     return CAIRO_INT_STATUS_SUCCESS;
  721. }
  722.  
  723. static cairo_bool_t
  724. _cairo_qt_surface_get_extents (void *abstract_surface,
  725.                                cairo_rectangle_int_t *extents)
  726. {
  727.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  728.  
  729.     extents->x = qs->window.x();
  730.     extents->y = qs->window.y();
  731.     extents->width  = qs->window.width();
  732.     extents->height = qs->window.height();
  733.  
  734.     return TRUE;
  735. }
  736.  
  737. static cairo_status_t
  738. _cairo_qt_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
  739.                                                cairo_path_fixed_t *path,
  740.                                                cairo_fill_rule_t fill_rule,
  741.                                                double tolerance,
  742.                                                cairo_antialias_t antialias)
  743. {
  744.     cairo_qt_surface_t *qs = cairo_container_of (clipper,
  745.                                                  cairo_qt_surface_t,
  746.                                                  clipper);
  747.  
  748.     if (path == NULL) {
  749.         if (qs->pixmap || qs->image) {
  750.             // we own p
  751.             qs->p->setClipping (false);
  752.         } else {
  753.             qs->p->restore ();
  754.             qs->p->save ();
  755.         }
  756.     } else {
  757.         // XXX Antialiasing is ignored
  758.         qs->p->setClipPath (path_to_qt (path, fill_rule), Qt::IntersectClip);
  759.     }
  760.  
  761.     return CAIRO_STATUS_SUCCESS;
  762. }
  763.  
  764. static void
  765. _cairo_qt_surface_set_clip_region (cairo_qt_surface_t *qs,
  766.                                    const cairo_region_t *clip_region)
  767. {
  768.     _cairo_surface_clipper_reset (&qs->clipper);
  769.  
  770.     if (clip_region == NULL) {
  771.         // How the clip path is reset depends on whether we own p or not
  772.         if (qs->pixmap || qs->image) {
  773.             // we own p
  774.             qs->p->setClipping (false);
  775.         } else {
  776.             qs->p->restore ();
  777.             qs->p->save ();
  778.         }
  779.     } else {
  780.         QRegion qr;
  781.         int num_rects = cairo_region_num_rectangles (clip_region);
  782.         for (int i = 0; i < num_rects; ++i) {
  783.             cairo_rectangle_int_t rect;
  784.  
  785.             cairo_region_get_rectangle (clip_region, i, &rect);
  786.  
  787.             QRect r(rect.x, rect.y, rect.width, rect.height);
  788.             qr = qr.unite(r);
  789.         }
  790.  
  791.         qs->p->setClipRegion (qr, Qt::IntersectClip);
  792.     }
  793. }
  794.  
  795. static cairo_int_status_t
  796. _cairo_qt_surface_set_clip (cairo_qt_surface_t *qs,
  797.                             const cairo_clip_t *clip)
  798. {
  799.     cairo_int_status_t status;
  800.  
  801.     D(fprintf(stderr, "q[%p] intersect_clip_path %s\n", abstract_surface, path ? "(path)" : "(clear)"));
  802.  
  803.     if (clip == NULL) {
  804.         _cairo_surface_clipper_reset (&qs->clipper);
  805.         // How the clip path is reset depends on whether we own p or not
  806.         if (qs->pixmap || qs->image) {
  807.             // we own p
  808.             qs->p->setClipping (false);
  809.         } else {
  810.             qs->p->restore ();
  811.             qs->p->save ();
  812.         }
  813.  
  814.         return CAIRO_INT_STATUS_SUCCESS;
  815.     }
  816.  
  817. #if ENABLE_FAST_CLIP
  818.     // Qt will implicitly enable clipping, and will use ReplaceClip
  819.     // instead of IntersectClip if clipping was disabled before
  820.  
  821.     // Note: Qt is really bad at dealing with clip paths.  It doesn't
  822.     // seem to usefully recognize rectangular paths, instead going down
  823.     // extremely slow paths whenever a clip path is set.  So,
  824.     // we do a bunch of work here to try to get rectangles or regions
  825.     // down to Qt for clipping.
  826.  
  827.     cairo_region_t *clip_region = NULL;
  828.  
  829.     status = _cairo_clip_get_region (clip, &clip_region);
  830.     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  831.         // We weren't able to extract a region from the traps.
  832.         // Just hand the path down to QPainter.
  833.         status = (cairo_int_status_t)
  834.             _cairo_surface_clipper_set_clip (&qs->clipper, clip);
  835.     } else if (status == CAIRO_INT_STATUS_SUCCESS) {
  836.         _cairo_qt_surface_set_clip_region (qs, clip_region);
  837.         status = CAIRO_INT_STATUS_SUCCESS;
  838.     }
  839. #else
  840.     status = (cairo_int_status_t)
  841.         _cairo_surface_clipper_set_clip (&qs->clipper, clip);
  842. #endif
  843.  
  844.     return status;
  845. }
  846.  
  847. /*
  848.  * Brush conversion
  849.  */
  850.  
  851. struct PatternToBrushConverter {
  852.     PatternToBrushConverter (const cairo_pattern_t *pattern) :
  853.         mAcquiredImageParent(0),
  854.         mAcquiredImage(0),
  855.         mAcquiredImageExtra(0)
  856.     {
  857.         if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
  858.             cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
  859.             QColor color;
  860.             color.setRgbF(solid->color.red,
  861.                           solid->color.green,
  862.                           solid->color.blue,
  863.                           solid->color.alpha);
  864.  
  865.             mBrush = QBrush(color);
  866.         } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
  867.             cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) pattern;
  868.             cairo_surface_t *surface = spattern->surface;
  869.  
  870.             if (surface->type == CAIRO_SURFACE_TYPE_QT) {
  871.                 cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
  872.  
  873.                 if (qs->image) {
  874.                     mBrush = QBrush(*qs->image);
  875.                 } else if (qs->pixmap) {
  876.                     mBrush = QBrush(*qs->pixmap);
  877.                 } else {
  878.                     // do something smart
  879.                     mBrush = QBrush(0xff0000ff);
  880.                 }
  881.             } else {
  882.                 cairo_image_surface_t *isurf = NULL;
  883.  
  884.                 if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
  885.                     isurf = (cairo_image_surface_t*) surface;
  886.                 } else {
  887.                     void *image_extra;
  888.  
  889.                     if (_cairo_surface_acquire_source_image (surface, &isurf, &image_extra) == CAIRO_STATUS_SUCCESS) {
  890.                         mAcquiredImageParent = surface;
  891.                         mAcquiredImage = isurf;
  892.                         mAcquiredImageExtra = image_extra;
  893.                     } else {
  894.                         isurf = NULL;
  895.                     }
  896.                 }
  897.  
  898.                 if (isurf) {
  899.                     mBrush = QBrush (QImage ((const uchar *) isurf->data,
  900.                                                  isurf->width,
  901.                                                  isurf->height,
  902.                                                  isurf->stride,
  903.                                                  _qimage_format_from_cairo_format (isurf->format)));
  904.                 } else {
  905.                     mBrush = QBrush(0x0000ffff);
  906.                 }
  907.             }
  908.         } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
  909.                    pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
  910.         {
  911.             QGradient *grad;
  912.             cairo_bool_t reverse_stops = FALSE;
  913.             cairo_bool_t emulate_reflect = FALSE;
  914.             double offset = 0.0;
  915.  
  916.             cairo_extend_t extend = pattern->extend;
  917.  
  918.             cairo_gradient_pattern_t *gpat = (cairo_gradient_pattern_t *) pattern;
  919.  
  920.             if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
  921.                 cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *) pattern;
  922.                 grad = new QLinearGradient (lpat->pd1.x, lpat->pd1.y,
  923.                                             lpat->pd2.x, lpat->pd2.y);
  924.             } else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
  925.                 cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *) pattern;
  926.  
  927.                 /* Based on the SVG surface code */
  928.  
  929.                 cairo_circle_double_t *c0, *c1;
  930.                 double x0, y0, r0, x1, y1, r1;
  931.  
  932.                 if (rpat->cd1.radius < rpat->cd2.radius) {
  933.                     c0 = &rpat->cd1;
  934.                     c1 = &rpat->cd2;
  935.                     reverse_stops = FALSE;
  936.                 } else {
  937.                     c0 = &rpat->cd2;
  938.                     c1 = &rpat->cd1;
  939.                     reverse_stops = TRUE;
  940.                 }
  941.  
  942.                 x0 = c0->center.x;
  943.                 y0 = c0->center.y;
  944.                 r0 = c0->radius;
  945.                 x1 = c1->center.x;
  946.                 y1 = c1->center.y;
  947.                 r1 = c1->radius;
  948.  
  949.                 if (r0 == r1) {
  950.                     grad = new QRadialGradient (x1, y1, r1, x1, y1);
  951.                 } else {
  952.                     double fx = (r1 * x0 - r0 * x1) / (r1 - r0);
  953.                     double fy = (r1 * y0 - r0 * y1) / (r1 - r0);
  954.  
  955.                     /* QPainter doesn't support the inner circle and use instead a gradient focal.
  956.                      * That means we need to emulate the cairo behaviour by processing the
  957.                      * cairo gradient stops.
  958.                      * The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle,
  959.                      * it's just a matter of stop position translation and calculation of
  960.                      * the corresponding SVG radial gradient focal.
  961.                      * The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new
  962.                      * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT
  963.                      * case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop
  964.                      * list that maps to the original cairo stop list.
  965.                      */
  966.                     if ((extend == CAIRO_EXTEND_REFLECT || extend == CAIRO_EXTEND_REPEAT) && r0 > 0.0) {
  967.                         double r_org = r1;
  968.                         double r, x, y;
  969.  
  970.                         if (extend == CAIRO_EXTEND_REFLECT) {
  971.                             r1 = 2 * r1 - r0;
  972.                             emulate_reflect = TRUE;
  973.                         }
  974.  
  975.                         offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0;
  976.                         r = r1 - r0;
  977.  
  978.                         /* New position of outer circle. */
  979.                         x = r * (x1 - fx) / r_org + fx;
  980.                         y = r * (y1 - fy) / r_org + fy;
  981.  
  982.                         x1 = x;
  983.                         y1 = y;
  984.                         r1 = r;
  985.                         r0 = 0.0;
  986.                     } else {
  987.                         offset = r0 / r1;
  988.                     }
  989.  
  990.                     grad = new QRadialGradient (x1, y1, r1, fx, fy);
  991.  
  992.                     if (extend == CAIRO_EXTEND_NONE && r0 != 0.0)
  993.                         grad->setColorAt (r0 / r1, Qt::transparent);
  994.                 }
  995.             }
  996.  
  997.             switch (extend) {
  998.                 case CAIRO_EXTEND_NONE:
  999.                 case CAIRO_EXTEND_PAD:
  1000.                     grad->setSpread(QGradient::PadSpread);
  1001.  
  1002.                     grad->setColorAt (0.0, Qt::transparent);
  1003.                     grad->setColorAt (1.0, Qt::transparent);
  1004.                     break;
  1005.  
  1006.                 case CAIRO_EXTEND_REFLECT:
  1007.                     grad->setSpread(QGradient::ReflectSpread);
  1008.                     break;
  1009.  
  1010.                 case CAIRO_EXTEND_REPEAT:
  1011.                     grad->setSpread(QGradient::RepeatSpread);
  1012.                     break;
  1013.             }
  1014.  
  1015.             for (unsigned int i = 0; i < gpat->n_stops; i++) {
  1016.                 int index = i;
  1017.                 if (reverse_stops)
  1018.                     index = gpat->n_stops - i - 1;
  1019.  
  1020.                 double offset = gpat->stops[i].offset;
  1021.                 QColor color;
  1022.                 color.setRgbF (gpat->stops[i].color.red,
  1023.                                gpat->stops[i].color.green,
  1024.                                gpat->stops[i].color.blue,
  1025.                                gpat->stops[i].color.alpha);
  1026.  
  1027.                 if (emulate_reflect) {
  1028.                     offset = offset / 2.0;
  1029.                     grad->setColorAt (1.0 - offset, color);
  1030.                 }
  1031.  
  1032.                 grad->setColorAt (offset, color);
  1033.             }
  1034.  
  1035.             mBrush = QBrush(*grad);
  1036.  
  1037.             delete grad;
  1038.         }
  1039.  
  1040.         if (mBrush.style() != Qt::NoBrush  &&
  1041.             pattern->type != CAIRO_PATTERN_TYPE_SOLID &&
  1042.             ! _cairo_matrix_is_identity (&pattern->matrix))
  1043.         {
  1044.             cairo_matrix_t pm = pattern->matrix;
  1045.             cairo_status_t status = cairo_matrix_invert (&pm);
  1046.             assert (status == CAIRO_STATUS_SUCCESS);
  1047.             mBrush.setMatrix (_qmatrix_from_cairo_matrix (pm));
  1048.         }
  1049.     }
  1050.  
  1051.     ~PatternToBrushConverter () {
  1052.         if (mAcquiredImageParent)
  1053.             _cairo_surface_release_source_image (mAcquiredImageParent, mAcquiredImage, mAcquiredImageExtra);
  1054.     }
  1055.  
  1056.     operator QBrush& () {
  1057.         return mBrush;
  1058.     }
  1059.  
  1060.     QBrush mBrush;
  1061.  
  1062.     private:
  1063.     cairo_surface_t *mAcquiredImageParent;
  1064.     cairo_image_surface_t *mAcquiredImage;
  1065.     void *mAcquiredImageExtra;
  1066. };
  1067.  
  1068. struct PatternToPenConverter {
  1069.     PatternToPenConverter (const cairo_pattern_t *source,
  1070.                            const cairo_stroke_style_t *style) :
  1071.         mBrushConverter(source)
  1072.     {
  1073.         Qt::PenJoinStyle join = Qt::MiterJoin;
  1074.         Qt::PenCapStyle cap = Qt::SquareCap;
  1075.  
  1076.         switch (style->line_cap) {
  1077.         case CAIRO_LINE_CAP_BUTT:
  1078.             cap = Qt::FlatCap;
  1079.             break;
  1080.         case CAIRO_LINE_CAP_ROUND:
  1081.             cap = Qt::RoundCap;
  1082.             break;
  1083.         case CAIRO_LINE_CAP_SQUARE:
  1084.             cap = Qt::SquareCap;
  1085.             break;
  1086.         }
  1087.  
  1088.         switch (style->line_join) {
  1089.         case CAIRO_LINE_JOIN_MITER:
  1090.             join = Qt::MiterJoin;
  1091.             break;
  1092.         case CAIRO_LINE_JOIN_ROUND:
  1093.             join = Qt::RoundJoin;
  1094.             break;
  1095.         case CAIRO_LINE_JOIN_BEVEL:
  1096.             join = Qt::BevelJoin;
  1097.             break;
  1098.         }
  1099.  
  1100.         mPen = QPen(mBrushConverter, style->line_width, Qt::SolidLine, cap, join);
  1101.         mPen.setMiterLimit (style->miter_limit);
  1102.  
  1103.         if (style->dash && style->num_dashes) {
  1104.             Qt::PenStyle pstyle = Qt::NoPen;
  1105.  
  1106.             if (style->num_dashes == 2) {
  1107.                 if ((style->dash[0] == style->line_width &&
  1108.                         style->dash[1] == style->line_width && style->line_width <= 2.0) ||
  1109.                     (style->dash[0] == 0.0 &&
  1110.                         style->dash[1] == style->line_width * 2 && cap == Qt::RoundCap))
  1111.                 {
  1112.                     pstyle = Qt::DotLine;
  1113.                 } else if (style->dash[0] == style->line_width * DASH_LENGTH &&
  1114.                            style->dash[1] == style->line_width * DASH_LENGTH &&
  1115.                            cap == Qt::FlatCap)
  1116.                 {
  1117.                     pstyle = Qt::DashLine;
  1118.                 }
  1119.             }
  1120.  
  1121.             if (pstyle != Qt::NoPen) {
  1122.                 mPen.setStyle(pstyle);
  1123.                 return;
  1124.             }
  1125.  
  1126.             unsigned int odd_dash = style->num_dashes % 2;
  1127.  
  1128.             QVector<qreal> dashes (odd_dash ? style->num_dashes * 2 : style->num_dashes);
  1129.             for (unsigned int i = 0; i < odd_dash+1; i++) {
  1130.                 for (unsigned int j = 0; j < style->num_dashes; j++) {
  1131.                     // In Qt, the dash lengths are given in units of line width, whereas
  1132.                     // in cairo, they are in user-space units.  We'll always apply the CTM,
  1133.                     // so all we have to do here is divide cairo's dash lengths by the line
  1134.                     // width.
  1135.                     dashes.append (style->dash[j] / style->line_width);
  1136.                 }
  1137.             }
  1138.  
  1139.             mPen.setDashPattern(dashes);
  1140.             mPen.setDashOffset(style->dash_offset / style->line_width);
  1141.         }
  1142.     }
  1143.  
  1144.     ~PatternToPenConverter() { }
  1145.  
  1146.     operator QPen& () {
  1147.         return mPen;
  1148.     }
  1149.  
  1150.     QPen mPen;
  1151.     PatternToBrushConverter mBrushConverter;
  1152. };
  1153.  
  1154. /*
  1155.  * Core drawing operations
  1156.  */
  1157.  
  1158. static bool
  1159. _cairo_qt_fast_fill (cairo_qt_surface_t *qs,
  1160.                      const cairo_pattern_t *source,
  1161.                      const cairo_path_fixed_t *path = NULL,
  1162.                      cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING,
  1163.                      double tolerance = 0.0,
  1164.                      cairo_antialias_t antialias = CAIRO_ANTIALIAS_NONE)
  1165. {
  1166. #if ENABLE_FAST_FILL
  1167.     QImage *qsSrc_image = NULL;
  1168.     QPixmap *qsSrc_pixmap = NULL;
  1169.     std::auto_ptr<QImage> qsSrc_image_d;
  1170.  
  1171.  
  1172.     if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
  1173.         cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) source;
  1174.         if (spattern->surface->type == CAIRO_SURFACE_TYPE_QT) {
  1175.             cairo_qt_surface_t *p = (cairo_qt_surface_t*) spattern->surface;
  1176.  
  1177.             qsSrc_image = p->image;
  1178.             qsSrc_pixmap = p->pixmap;
  1179.         } else if (spattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
  1180.             cairo_image_surface_t *p = (cairo_image_surface_t*) spattern->surface;
  1181.             qsSrc_image = new QImage((const uchar*) p->data,
  1182.                                      p->width,
  1183.                                      p->height,
  1184.                                      p->stride,
  1185.                                      _qimage_format_from_cairo_format(p->format));
  1186.             qsSrc_image_d.reset(qsSrc_image);
  1187.         }
  1188.     }
  1189.  
  1190.     if (!qsSrc_image && !qsSrc_pixmap)
  1191.         return false;
  1192.  
  1193.     // We can only drawTiledPixmap; there's no drawTiledImage
  1194.     if (! qsSrc_pixmap &&
  1195.         (source->extend == CAIRO_EXTEND_REPEAT ||
  1196.          source->extend == CAIRO_EXTEND_REFLECT))
  1197.     {
  1198.         return false;
  1199.     }
  1200.  
  1201.     QMatrix sourceMatrix = _qmatrix_from_cairo_matrix (source->matrix);
  1202.  
  1203.     // We can draw this faster by clipping and calling drawImage/drawPixmap.
  1204.     // Use our own clipping function so that we can get the
  1205.     // region handling to end up with the fastest possible clip.
  1206.     //
  1207.     // XXX Antialiasing will fail pretty hard here, since we can't clip with AA
  1208.     // with QPainter.
  1209.     qs->p->save();
  1210.  
  1211.     if (path) {
  1212.         cairo_int_status_t status;
  1213.  
  1214.         cairo_clip_t clip, old_clip = qs->clipper.clip;
  1215.  
  1216.         _cairo_clip_init_copy (&clip, &qs->clipper.clip);
  1217.         status = (cairo_int_status_t) _cairo_clip_clip (&clip,
  1218.                                                         path,
  1219.                                                         fill_rule,
  1220.                                                         tolerance,
  1221.                                                         antialias);
  1222.         if (unlikely (status)) {
  1223.             qs->p->restore();
  1224.             return false;
  1225.         }
  1226.  
  1227.         status = _cairo_qt_surface_set_clip (qs, &clip);
  1228.         if (unlikely (status)) {
  1229.             qs->p->restore();
  1230.             return false;
  1231.         }
  1232.  
  1233.         _cairo_clip_reset (&clip);
  1234.         qs->clipper.clip = old_clip;
  1235.     }
  1236.  
  1237.     qs->p->setWorldMatrix (sourceMatrix.inverted(), true);
  1238.  
  1239.     switch (source->extend) {
  1240.     case CAIRO_EXTEND_REPEAT:
  1241.     // XXX handle reflect by tiling 4 times first
  1242.     case CAIRO_EXTEND_REFLECT: {
  1243.             assert (qsSrc_pixmap);
  1244.  
  1245.             // Render the tiling to cover the entire destination window (because
  1246.             // it'll be clipped).  Transform the window rect by the inverse
  1247.             // of the current world transform so that the device coordinates
  1248.             // end up as the right thing.
  1249.             QRectF dest = qs->p->worldTransform().inverted().mapRect(QRectF(qs->window));
  1250.             QPointF origin = sourceMatrix.map(QPointF(0.0, 0.0));
  1251.  
  1252.             qs->p->drawTiledPixmap (dest, *qsSrc_pixmap, origin);
  1253.         }
  1254.         break;
  1255.     case CAIRO_EXTEND_NONE:
  1256.     case CAIRO_EXTEND_PAD: // XXX not exactly right, but good enough
  1257.     default:
  1258.         if (qsSrc_image)
  1259.             qs->p->drawImage (0, 0, *qsSrc_image);
  1260.         else if (qsSrc_pixmap)
  1261.             qs->p->drawPixmap (0, 0, *qsSrc_pixmap);
  1262.         break;
  1263.     }
  1264.  
  1265.     qs->p->restore();
  1266.  
  1267.     return true;
  1268. #else
  1269.     return false;
  1270. #endif
  1271. }
  1272.  
  1273. static cairo_int_status_t
  1274. _cairo_qt_surface_paint (void *abstract_surface,
  1275.                          cairo_operator_t op,
  1276.                          const cairo_pattern_t *source,
  1277.                          const cairo_clip_t            *clip)
  1278. {
  1279.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  1280.     cairo_int_status_t status;
  1281.  
  1282.     D(fprintf(stderr, "q[%p] paint op:%s\n", abstract_surface, _opstr(op)));
  1283.  
  1284.     if (! _op_is_supported (qs, op))
  1285.         return _cairo_surface_fallback_paint (abstract_surface, op, source, clip);
  1286.  
  1287.     status = _cairo_qt_surface_set_clip (qs, clip);
  1288.     if (unlikely (status))
  1289.         return status;
  1290.  
  1291.     if (qs->supports_porter_duff)
  1292.         qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
  1293.  
  1294.     if (! _cairo_qt_fast_fill (qs, source)) {
  1295.         PatternToBrushConverter brush (source);
  1296.         qs->p->fillRect (qs->window, brush);
  1297.     }
  1298.  
  1299.     if (qs->supports_porter_duff)
  1300.         qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
  1301.  
  1302.     return CAIRO_INT_STATUS_SUCCESS;
  1303. }
  1304.  
  1305. static cairo_int_status_t
  1306. _cairo_qt_surface_fill (void *abstract_surface,
  1307.                         cairo_operator_t op,
  1308.                         const cairo_pattern_t *source,
  1309.                         const cairo_path_fixed_t *path,
  1310.                         cairo_fill_rule_t fill_rule,
  1311.                         double tolerance,
  1312.                         cairo_antialias_t antialias,
  1313.                         const cairo_clip_t *clip)
  1314. {
  1315.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  1316.  
  1317.     D(fprintf(stderr, "q[%p] fill op:%s\n", abstract_surface, _opstr(op)));
  1318.  
  1319.     if (! _op_is_supported (qs, op))
  1320.         return _cairo_surface_fallback_fill (abstract_surface, op,
  1321.                                              source, path, fill_rule,
  1322.                                              tolerance, antialias, clip);
  1323.  
  1324.     cairo_int_status_t status = _cairo_qt_surface_set_clip (qs, clip);
  1325.     if (unlikely (status))
  1326.         return status;
  1327.  
  1328.     if (qs->supports_porter_duff)
  1329.         qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
  1330.  
  1331.     // XXX Qt4.3, 4.4 misrenders some complex paths if antialiasing is
  1332.     // enabled
  1333.     //qs->p->setRenderHint (QPainter::Antialiasing, antialias == CAIRO_ANTIALIAS_NONE ? false : true);
  1334.     qs->p->setRenderHint (QPainter::SmoothPixmapTransform, source->filter != CAIRO_FILTER_FAST);
  1335.  
  1336.     if (! _cairo_qt_fast_fill (qs, source,
  1337.                                path, fill_rule, tolerance, antialias))
  1338.     {
  1339.         PatternToBrushConverter brush(source);
  1340.         qs->p->fillPath (path_to_qt (path, fill_rule), brush);
  1341.     }
  1342.  
  1343.     if (qs->supports_porter_duff)
  1344.         qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
  1345.  
  1346.     return CAIRO_INT_STATUS_SUCCESS;
  1347. }
  1348.  
  1349. static cairo_int_status_t
  1350. _cairo_qt_surface_stroke (void *abstract_surface,
  1351.                           cairo_operator_t op,
  1352.                           const cairo_pattern_t *source,
  1353.                           const cairo_path_fixed_t *path,
  1354.                           const cairo_stroke_style_t *style,
  1355.                           const cairo_matrix_t *ctm,
  1356.                           const cairo_matrix_t *ctm_inverse,
  1357.                           double tolerance,
  1358.                           cairo_antialias_t antialias,
  1359.                           const cairo_clip_t *clip)
  1360. {
  1361.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  1362.  
  1363.     D(fprintf(stderr, "q[%p] stroke op:%s\n", abstract_surface, _opstr(op)));
  1364.  
  1365.     if (! _op_is_supported (qs, op))
  1366.         return _cairo_surface_fallback_stroke (abstract_surface, op,
  1367.                                                source, path, style, ctm,
  1368.                                                ctm_inverse, tolerance,
  1369.                                                antialias, clip);
  1370.  
  1371.     cairo_int_status_t int_status = _cairo_qt_surface_set_clip (qs, clip);
  1372.     if (unlikely (int_status))
  1373.         return int_status;
  1374.  
  1375.     QMatrix savedMatrix = qs->p->worldMatrix();
  1376.  
  1377.     if (qs->supports_porter_duff)
  1378.         qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
  1379.  
  1380.     qs->p->setWorldMatrix (_qmatrix_from_cairo_matrix (*ctm), true);
  1381.     // XXX Qt4.3, 4.4 misrenders some complex paths if antialiasing is
  1382.     // enabled
  1383.     //qs->p->setRenderHint (QPainter::Antialiasing, antialias == CAIRO_ANTIALIAS_NONE ? false : true);
  1384.     qs->p->setRenderHint (QPainter::SmoothPixmapTransform, source->filter != CAIRO_FILTER_FAST);
  1385.  
  1386.     PatternToPenConverter pen(source, style);
  1387.  
  1388.     qs->p->setPen(pen);
  1389.     qs->p->drawPath(path_to_qt (path, ctm_inverse));
  1390.     qs->p->setPen(Qt::black);
  1391.  
  1392.     qs->p->setWorldMatrix (savedMatrix, false);
  1393.  
  1394.     if (qs->supports_porter_duff)
  1395.         qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver);
  1396.  
  1397.     return CAIRO_INT_STATUS_SUCCESS;
  1398. }
  1399.  
  1400. static cairo_int_status_t
  1401. _cairo_qt_surface_show_glyphs (void *abstract_surface,
  1402.                                cairo_operator_t op,
  1403.                                const cairo_pattern_t *source,
  1404.                                cairo_glyph_t *glyphs,
  1405.                                int num_glyphs,
  1406.                                cairo_scaled_font_t *scaled_font,
  1407.                                const cairo_clip_t *clip)
  1408. {
  1409. #if ((QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)) && 0
  1410.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  1411.  
  1412.     // pick out the colour to use from the cairo source
  1413.     cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) source;
  1414.     cairo_scaled_glyph_t* glyph;
  1415.     // documentation says you have to freeze the cache, but I don't believe it
  1416.     _cairo_scaled_font_freeze_cache(scaled_font);
  1417.  
  1418.     QColor tempColour(solid->color.red * 255, solid->color.green * 255, solid->color.blue * 255);
  1419.     QVarLengthArray<QPointF> positions(num_glyphs);
  1420.     QVarLengthArray<unsigned int> glyphss(num_glyphs);
  1421.     FT_Face face = cairo_ft_scaled_font_lock_face (scaled_font);
  1422.     const FT_Size_Metrics& ftMetrics = face->size->metrics;
  1423.     QFont font(face->family_name);
  1424.     font.setStyleStrategy(QFont::NoFontMerging);
  1425.     font.setBold(face->style_flags & FT_STYLE_FLAG_BOLD);
  1426.     font.setItalic(face->style_flags & FT_STYLE_FLAG_ITALIC);
  1427.     font.setKerning(face->face_flags & FT_FACE_FLAG_KERNING);
  1428.     font.setPixelSize(ftMetrics.y_ppem);
  1429.     cairo_ft_scaled_font_unlock_face(scaled_font);
  1430.     qs->p->setFont(font);
  1431.     qs->p->setPen(tempColour);
  1432.     for (int currentGlyph = 0; currentGlyph < num_glyphs; currentGlyph++) {
  1433.         positions[currentGlyph].setX(glyphs[currentGlyph].x);
  1434.         positions[currentGlyph].setY(glyphs[currentGlyph].y);
  1435.         glyphss[currentGlyph] = glyphs[currentGlyph].index;
  1436.     }
  1437.     qt_draw_glyphs(qs->p, glyphss.data(), positions.data(), num_glyphs);
  1438.     _cairo_scaled_font_thaw_cache(scaled_font);
  1439.     return CAIRO_INT_STATUS_SUCCESS;
  1440. #else
  1441.     return _cairo_surface_fallback_glyphs (abstract_surface, op,
  1442.                                            source, glyphs, num_glyphs,
  1443.                                            scaled_font, clip);
  1444. #endif
  1445. }
  1446.  
  1447. static cairo_int_status_t
  1448. _cairo_qt_surface_mask (void *abstract_surface,
  1449.                         cairo_operator_t op,
  1450.                         const cairo_pattern_t *source,
  1451.                         const cairo_pattern_t *mask,
  1452.                         const cairo_clip_t          *clip)
  1453. {
  1454.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  1455.  
  1456.     D(fprintf(stderr, "q[%p] mask op:%s\n", abstract_surface, _opstr(op)));
  1457.  
  1458.     if (qs->p && mask->type == CAIRO_PATTERN_TYPE_SOLID) {
  1459.         cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
  1460.         cairo_int_status_t result;
  1461.  
  1462.         qs->p->setOpacity (solid_mask->color.alpha);
  1463.  
  1464.         result = _cairo_qt_surface_paint (abstract_surface, op, source, clip);
  1465.  
  1466.         qs->p->setOpacity (1.0);
  1467.  
  1468.         return result;
  1469.     }
  1470.  
  1471.     // otherwise skip for now
  1472.     return _cairo_surface_fallback_mask (abstract_surface, op, source, mask, clip);
  1473. }
  1474.  
  1475. static cairo_status_t
  1476. _cairo_qt_surface_mark_dirty (void *abstract_surface,
  1477.                               int x, int y,
  1478.                               int width, int height)
  1479. {
  1480.     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
  1481.  
  1482.     if (qs->p && !(qs->image || qs->pixmap))
  1483.         qs->p->save ();
  1484.  
  1485.     return CAIRO_STATUS_SUCCESS;
  1486. }
  1487.  
  1488. /*
  1489.  * Backend struct
  1490.  */
  1491.  
  1492. static const cairo_surface_backend_t cairo_qt_surface_backend = {
  1493.     CAIRO_SURFACE_TYPE_QT,
  1494.     _cairo_qt_surface_finish,
  1495.  
  1496.     _cairo_default_context_create, /* XXX */
  1497.  
  1498.     _cairo_qt_surface_create_similar,
  1499.     NULL, /* similar image */
  1500.     _cairo_qt_surface_map_to_image,
  1501.     _cairo_qt_surface_unmap_image,
  1502.  
  1503.     _cairo_surface_default_source,
  1504.     _cairo_qt_surface_acquire_source_image,
  1505.     _cairo_qt_surface_release_source_image,
  1506.     NULL, /* snapshot */
  1507.  
  1508.     NULL, /* copy_page */
  1509.     NULL, /* show_page */
  1510.  
  1511.     _cairo_qt_surface_get_extents,
  1512.     NULL, /* get_font_options */
  1513.  
  1514.     NULL, /* flush */
  1515.     _cairo_qt_surface_mark_dirty,
  1516.  
  1517.     _cairo_qt_surface_paint,
  1518.     _cairo_qt_surface_mask,
  1519.     _cairo_qt_surface_stroke,
  1520.     _cairo_qt_surface_fill,
  1521.     NULL, /* fill_stroke */
  1522.     _cairo_qt_surface_show_glyphs
  1523. };
  1524.  
  1525. cairo_surface_t *
  1526. cairo_qt_surface_create (QPainter *painter)
  1527. {
  1528.     cairo_qt_surface_t *qs;
  1529.  
  1530.     qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t));
  1531.     if (qs == NULL)
  1532.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  1533.  
  1534.     memset (qs, 0, sizeof(cairo_qt_surface_t));
  1535.  
  1536.     _cairo_surface_init (&qs->base,
  1537.                          &cairo_qt_surface_backend,
  1538.                          NULL, /* device */
  1539.                          CAIRO_CONTENT_COLOR_ALPHA);
  1540.  
  1541.     _cairo_surface_clipper_init (&qs->clipper,
  1542.                                  _cairo_qt_surface_clipper_intersect_clip_path);
  1543.  
  1544.     qs->p = painter;
  1545.     if (qs->p->paintEngine())
  1546.         qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
  1547.     else
  1548.         qs->supports_porter_duff = FALSE;
  1549.  
  1550.     // Save so that we can always get back to the original state
  1551.     qs->p->save();
  1552.  
  1553.     qs->window = painter->window();
  1554.  
  1555.     D(fprintf(stderr, "qpainter_surface_create: window: [%d %d %d %d] pd:%d\n",
  1556.               qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
  1557.               qs->supports_porter_duff));
  1558.  
  1559.     return &qs->base;
  1560. }
  1561.  
  1562. cairo_surface_t *
  1563. cairo_qt_surface_create_with_qimage (cairo_format_t format,
  1564.                                      int width,
  1565.                                      int height)
  1566. {
  1567.     cairo_qt_surface_t *qs;
  1568.  
  1569.     qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t));
  1570.     if (qs == NULL)
  1571.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  1572.  
  1573.     memset (qs, 0, sizeof(cairo_qt_surface_t));
  1574.  
  1575.     _cairo_surface_init (&qs->base,
  1576.                          &cairo_qt_surface_backend,
  1577.                          NULL, /* device */
  1578.                          _cairo_content_from_format (format));
  1579.  
  1580.     _cairo_surface_clipper_init (&qs->clipper,
  1581.                                  _cairo_qt_surface_clipper_intersect_clip_path);
  1582.  
  1583.  
  1584.     QImage *image = new QImage (width, height,
  1585.                                 _qimage_format_from_cairo_format (format));
  1586.  
  1587.     qs->image = image;
  1588.  
  1589.     if (!image->isNull()) {
  1590.         qs->p = new QPainter(image);
  1591.         qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
  1592.     }
  1593.  
  1594.     qs->image_equiv = cairo_image_surface_create_for_data (image->bits(),
  1595.                                                            format,
  1596.                                                            width, height,
  1597.                                                            image->bytesPerLine());
  1598.  
  1599.     qs->window = QRect(0, 0, width, height);
  1600.  
  1601.     D(fprintf(stderr, "qpainter_surface_create: qimage: [%d %d %d %d] pd:%d\n",
  1602.               qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
  1603.               qs->supports_porter_duff));
  1604.  
  1605.     return &qs->base;
  1606. }
  1607.  
  1608. cairo_surface_t *
  1609. cairo_qt_surface_create_with_qpixmap (cairo_content_t content,
  1610.                                       int width,
  1611.                                       int height)
  1612. {
  1613.     cairo_qt_surface_t *qs;
  1614.  
  1615.     if ((content & CAIRO_CONTENT_COLOR) == 0)
  1616.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
  1617.  
  1618.     qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t));
  1619.     if (qs == NULL)
  1620.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  1621.  
  1622.     memset (qs, 0, sizeof(cairo_qt_surface_t));
  1623.  
  1624.     QPixmap *pixmap = new QPixmap (width, height);
  1625.     if (pixmap == NULL) {
  1626.         free (qs);
  1627.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  1628.     }
  1629.  
  1630.     // By default, a QPixmap is opaque; however, if it's filled
  1631.     // with a color with a transparency component, it is converted
  1632.     // to a format that preserves transparency.
  1633.     if (content == CAIRO_CONTENT_COLOR_ALPHA)
  1634.         pixmap->fill(Qt::transparent);
  1635.  
  1636.     _cairo_surface_init (&qs->base,
  1637.                          &cairo_qt_surface_backend,
  1638.                          NULL, /* device */
  1639.                          content);
  1640.  
  1641.     _cairo_surface_clipper_init (&qs->clipper,
  1642.                                  _cairo_qt_surface_clipper_intersect_clip_path);
  1643.  
  1644.     qs->pixmap = pixmap;
  1645.  
  1646.     if (!pixmap->isNull()) {
  1647.         qs->p = new QPainter(pixmap);
  1648.         qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
  1649.     }
  1650.  
  1651.     qs->window = QRect(0, 0, width, height);
  1652.  
  1653.     D(fprintf(stderr, "qpainter_surface_create: qpixmap: [%d %d %d %d] pd:%d\n",
  1654.               qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
  1655.               qs->supports_porter_duff));
  1656.  
  1657.     return &qs->base;
  1658. }
  1659.  
  1660. QPainter *
  1661. cairo_qt_surface_get_qpainter (cairo_surface_t *surface)
  1662. {
  1663.     cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
  1664.  
  1665.     if (surface->type != CAIRO_SURFACE_TYPE_QT)
  1666.         return NULL;
  1667.  
  1668.     return qs->p;
  1669. }
  1670.  
  1671. QImage *
  1672. cairo_qt_surface_get_qimage (cairo_surface_t *surface)
  1673. {
  1674.     cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
  1675.  
  1676.     if (surface->type != CAIRO_SURFACE_TYPE_QT)
  1677.         return NULL;
  1678.  
  1679.     return qs->image;
  1680. }
  1681.  
  1682. cairo_surface_t *
  1683. cairo_qt_surface_get_image (cairo_surface_t *surface)
  1684. {
  1685.     cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
  1686.  
  1687.     if (surface->type != CAIRO_SURFACE_TYPE_QT)
  1688.         return NULL;
  1689.  
  1690.     return qs->image_equiv;
  1691. }
  1692.  
  1693. /*
  1694.  * TODO:
  1695.  *
  1696.  * - Figure out why QBrush isn't working with non-repeated images
  1697.  *
  1698.  * - Correct repeat mode; right now, every surface source is EXTEND_REPEAT
  1699.  *   - implement EXTEND_NONE (?? probably need to clip to the extents of the source)
  1700.  *   - implement EXTEND_REFLECT (create temporary and copy 4x, then EXTEND_REPEAT that)
  1701.  *
  1702.  * - stroke-image failure
  1703.  *
  1704.  * - Implement mask() with non-solid masks (probably will need to use a temporary and use IN)
  1705.  *
  1706.  * - Implement gradient sources
  1707.  *
  1708.  * - Make create_similar smarter -- create QPixmaps in more circumstances
  1709.  *   (e.g. if the pixmap can have alpha)
  1710.  *
  1711.  * - Implement show_glyphs() in terms of Qt
  1712.  *
  1713.  */
  1714.