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