Raw File
cairo_qt_glyphs.patch
Bug 29092 - Fix glyphs rendering for cairo-qpainter-surface
diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp
index 2ac06ef..5b61b42 100644
--- a/src/cairo-qt-surface.cpp
+++ b/src/cairo-qt-surface.cpp
@@ -45,6 +45,7 @@
 #include "cairo-surface-clipper-private.h"
 #include "cairo-types-private.h"
 
+#include "cairo-ft.h"
 #include "cairo-qt.h"
 
 #include <memory>
@@ -58,14 +59,10 @@
 #include <QtGui/QPen>
 #include <QtGui/QWidget>
 #include <QtGui/QX11Info>
+#include <QtCore/QVarLengthArray>
 
-#if CAIRO_HAS_XLIB_XRENDER_SURFACE
-#include "cairo-xlib.h"
-#include "cairo-xlib-xrender.h"
-// I hate X
-#undef Status
-#undef CursorShape
-#undef Bool
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)
+extern void qt_draw_glyphs(QPainter *, const quint32 *glyphs, const QPointF *positions, int count);
 #endif
 
 #include <sys/time.h>
@@ -118,15 +115,6 @@ struct cairo_qt_surface_t {
 
     cairo_bool_t supports_porter_duff;
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-    /* temporary, so that we can share the xlib surface's glyphs code */
-    bool xlib_has_clipping;
-    cairo_surface_t *xlib_equiv;
-    QRect xlib_clip_bounds;
-    int xlib_clip_serial;
-    QPoint redir_offset;
-#endif
-
     QPainter *p;
 
     /* The pixmap/image constructors will store their objects here */
@@ -145,11 +133,6 @@ struct cairo_qt_surface_t {
  */
 static cairo_bool_t _qpixmaps_have_no_alpha = FALSE;
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-slim_hidden_proto (cairo_xlib_surface_create);
-slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
-#endif
-
 /**
  ** Helper methods
  **/
@@ -498,11 +481,6 @@ _cairo_qt_surface_finish (void *abstract_surface)
 
     _cairo_surface_clipper_reset (&qs->clipper);
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-    if (qs->xlib_equiv)
-        cairo_surface_destroy (qs->xlib_equiv);
-#endif
-
     if (qs->image)
         delete qs->image;
 
@@ -1392,33 +1370,40 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
 			       cairo_clip_t *clip,
 			       int *remaining_glyphs)
 {
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)
     cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-    /* If we have an equivalent X surface, let the xlib surface handle this
-     * until we figure out how to do this natively with Qt.
-     */
-    if (qs->xlib_equiv) {
-	D(fprintf(stderr, "q[%p] show_glyphs (x11 equiv) op:%s nglyphs: %d\n", abstract_surface, _opstr(op), num_glyphs));
-
-	for (int i = 0; i < num_glyphs; i++) {
-	    glyphs[i].x -= qs->redir_offset.x();
-	    glyphs[i].y -= qs->redir_offset.y();
-	}
-
-        return (cairo_int_status_t)
-               _cairo_surface_show_text_glyphs (qs->xlib_equiv,
-						op, source,
-						NULL, 0,
-						glyphs, num_glyphs,
-						NULL, 0,
-						(cairo_text_cluster_flags_t) 0,
-						scaled_font,
-						clip);
+    // pick out the colour to use from the cairo source
+    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) source;
+    cairo_scaled_glyph_t* glyph;
+    // documentation says you have to freeze the cache, but I don't believe it
+    _cairo_scaled_font_freeze_cache(scaled_font);
+
+    QColor tempColour(solid->color.red * 255, solid->color.green * 255, solid->color.blue * 255);
+    QVarLengthArray<QPointF> positions(num_glyphs);
+    QVarLengthArray<unsigned int> glyphss(num_glyphs);
+    FT_Face face = cairo_ft_scaled_font_lock_face (scaled_font);
+    const FT_Size_Metrics& ftMetrics = face->size->metrics;
+    QFont font(face->family_name);
+    font.setStyleStrategy(QFont::NoFontMerging);
+    font.setBold(face->style_flags & FT_STYLE_FLAG_BOLD);
+    font.setItalic(face->style_flags & FT_STYLE_FLAG_ITALIC);
+    font.setKerning(face->face_flags & FT_FACE_FLAG_KERNING);
+    font.setPixelSize(ftMetrics.y_ppem);
+    cairo_ft_scaled_font_unlock_face(scaled_font);
+    qs->p->setFont(font);
+    qs->p->setPen(tempColour);
+    for (int currentGlyph = 0; currentGlyph < num_glyphs; currentGlyph++) {
+        positions[currentGlyph].setX(glyphs[currentGlyph].x);
+        positions[currentGlyph].setY(glyphs[currentGlyph].y);
+        glyphss[currentGlyph] = glyphs[currentGlyph].index;
     }
-#endif
-
+    qt_draw_glyphs(qs->p, glyphss.data(), positions.data(), num_glyphs);
+    _cairo_scaled_font_thaw_cache(scaled_font);
+    return CAIRO_INT_STATUS_SUCCESS;
+#else
     return CAIRO_INT_STATUS_UNSUPPORTED;
+#endif
 }
 
 static cairo_int_status_t
@@ -1555,24 +1540,6 @@ _cairo_qt_surface_composite (cairo_operator_t op,
 }
 
 static cairo_status_t
-_cairo_qt_surface_flush (void *abstract_surface)
-{
-    cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
-
-    if (qs->p == NULL)
-	return CAIRO_STATUS_SUCCESS;
-
-    if (qs->image || qs->pixmap) {
-	qs->p->end ();
-	qs->p->begin (qs->p->device ());
-    } else {
-	qs->p->restore ();
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
 _cairo_qt_surface_mark_dirty (void *abstract_surface,
 			      int x, int y,
 			      int width, int height)
@@ -1609,7 +1576,7 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = {
     _cairo_qt_surface_get_extents,
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
-    _cairo_qt_surface_flush,
+    NULL, /* flush */
     _cairo_qt_surface_mark_dirty,
     NULL, /* scaled_font_fini */
     NULL, /* scaled_glyph_fini */
@@ -1629,64 +1596,6 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = {
     NULL, /* show_text_glyphs */
 };
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-static cairo_surface_t *
-_cairo_qt_create_xlib_surface (cairo_qt_surface_t *qs)
-{
-    if (!qs->p)
-	return NULL;
-
-    QPaintDevice *pd = qs->p->device();
-    if (!pd)
-	return NULL;
-
-    QPoint offs;
-    QPaintDevice *rpd = QPainter::redirected(pd, &offs);
-    if (rpd) {
-	pd = rpd;
-	qs->redir_offset = offs;
-    }
-
-    if (pd->devType() == QInternal::Widget) {
-	QWidget *w = (QWidget*) pd;
-	QX11Info xinfo = w->x11Info();
-
-	return cairo_xlib_surface_create (xinfo.display(),
-					  (Drawable) w->handle (),
-					  (Visual *) xinfo.visual (),
-					  w->width (), w->height ());
-    } else if (pd->devType() == QInternal::Pixmap) {
-	QPixmap *pixmap = (QPixmap*) pd;
-	QX11Info xinfo = pixmap->x11Info ();
-	XRenderPictFormat *xrender_format;
-	int pict_format;
-
-	switch (pixmap->depth ()) {
-	case 1:
-	    pict_format = PictStandardA1; break;
-	case 8:
-	    pict_format = PictStandardA8; break;
-	case 24:
-	    pict_format = PictStandardRGB24; break;
-	default:
-	    ASSERT_NOT_REACHED;
-	case 32:
-	    pict_format = PictStandardARGB32; break;
-	}
-	xrender_format = XRenderFindStandardFormat (xinfo.display (),
-		                                    pict_format);
-
-	return cairo_xlib_surface_create_with_xrender_format (xinfo.display(),
-					  (Drawable) pixmap->handle (),
-					  ScreenOfDisplay (xinfo.display (),
-							   xinfo.screen ()),
-					  xrender_format,
-					  pixmap->width (), pixmap->height ());
-    } else
-	return NULL;
-}
-#endif
-
 cairo_surface_t *
 cairo_qt_surface_create (QPainter *painter)
 {
@@ -1717,10 +1626,6 @@ cairo_qt_surface_create (QPainter *painter)
 
     qs->window = painter->window();
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-    qs->xlib_equiv = _cairo_qt_create_xlib_surface (qs);
-#endif
-
     D(fprintf(stderr, "qpainter_surface_create: window: [%d %d %d %d] pd:%d\n",
               qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
               qs->supports_porter_duff));
@@ -1819,10 +1724,6 @@ cairo_qt_surface_create_with_qpixmap (cairo_content_t content,
 
     qs->window = QRect(0, 0, width, height);
 
-#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
-    qs->xlib_equiv = _cairo_qt_create_xlib_surface (qs);
-#endif
-
     D(fprintf(stderr, "qpainter_surface_create: qpixmap: [%d %d %d %d] pd:%d\n",
               qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(),
               qs->supports_porter_duff));
back to top