summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/cairo_qt_glyphs.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/cairo_qt_glyphs.patch')
-rw-r--r--gfx/cairo/cairo_qt_glyphs.patch256
1 files changed, 256 insertions, 0 deletions
diff --git a/gfx/cairo/cairo_qt_glyphs.patch b/gfx/cairo/cairo_qt_glyphs.patch
new file mode 100644
index 0000000000..b123562876
--- /dev/null
+++ b/gfx/cairo/cairo_qt_glyphs.patch
@@ -0,0 +1,256 @@
+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));