Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | Bug 29092 - Fix glyphs rendering for cairo-qpainter-surface |
michael@0 | 2 | diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp |
michael@0 | 3 | index 2ac06ef..5b61b42 100644 |
michael@0 | 4 | --- a/src/cairo-qt-surface.cpp |
michael@0 | 5 | +++ b/src/cairo-qt-surface.cpp |
michael@0 | 6 | @@ -45,6 +45,7 @@ |
michael@0 | 7 | #include "cairo-surface-clipper-private.h" |
michael@0 | 8 | #include "cairo-types-private.h" |
michael@0 | 9 | |
michael@0 | 10 | +#include "cairo-ft.h" |
michael@0 | 11 | #include "cairo-qt.h" |
michael@0 | 12 | |
michael@0 | 13 | #include <memory> |
michael@0 | 14 | @@ -58,14 +59,10 @@ |
michael@0 | 15 | #include <QtGui/QPen> |
michael@0 | 16 | #include <QtGui/QWidget> |
michael@0 | 17 | #include <QtGui/QX11Info> |
michael@0 | 18 | +#include <QtCore/QVarLengthArray> |
michael@0 | 19 | |
michael@0 | 20 | -#if CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 21 | -#include "cairo-xlib.h" |
michael@0 | 22 | -#include "cairo-xlib-xrender.h" |
michael@0 | 23 | -// I hate X |
michael@0 | 24 | -#undef Status |
michael@0 | 25 | -#undef CursorShape |
michael@0 | 26 | -#undef Bool |
michael@0 | 27 | +#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT) |
michael@0 | 28 | +extern void qt_draw_glyphs(QPainter *, const quint32 *glyphs, const QPointF *positions, int count); |
michael@0 | 29 | #endif |
michael@0 | 30 | |
michael@0 | 31 | #include <sys/time.h> |
michael@0 | 32 | @@ -118,15 +115,6 @@ struct cairo_qt_surface_t { |
michael@0 | 33 | |
michael@0 | 34 | cairo_bool_t supports_porter_duff; |
michael@0 | 35 | |
michael@0 | 36 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 37 | - /* temporary, so that we can share the xlib surface's glyphs code */ |
michael@0 | 38 | - bool xlib_has_clipping; |
michael@0 | 39 | - cairo_surface_t *xlib_equiv; |
michael@0 | 40 | - QRect xlib_clip_bounds; |
michael@0 | 41 | - int xlib_clip_serial; |
michael@0 | 42 | - QPoint redir_offset; |
michael@0 | 43 | -#endif |
michael@0 | 44 | - |
michael@0 | 45 | QPainter *p; |
michael@0 | 46 | |
michael@0 | 47 | /* The pixmap/image constructors will store their objects here */ |
michael@0 | 48 | @@ -145,11 +133,6 @@ struct cairo_qt_surface_t { |
michael@0 | 49 | */ |
michael@0 | 50 | static cairo_bool_t _qpixmaps_have_no_alpha = FALSE; |
michael@0 | 51 | |
michael@0 | 52 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 53 | -slim_hidden_proto (cairo_xlib_surface_create); |
michael@0 | 54 | -slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format); |
michael@0 | 55 | -#endif |
michael@0 | 56 | - |
michael@0 | 57 | /** |
michael@0 | 58 | ** Helper methods |
michael@0 | 59 | **/ |
michael@0 | 60 | @@ -498,11 +481,6 @@ _cairo_qt_surface_finish (void *abstract_surface) |
michael@0 | 61 | |
michael@0 | 62 | _cairo_surface_clipper_reset (&qs->clipper); |
michael@0 | 63 | |
michael@0 | 64 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 65 | - if (qs->xlib_equiv) |
michael@0 | 66 | - cairo_surface_destroy (qs->xlib_equiv); |
michael@0 | 67 | -#endif |
michael@0 | 68 | - |
michael@0 | 69 | if (qs->image) |
michael@0 | 70 | delete qs->image; |
michael@0 | 71 | |
michael@0 | 72 | @@ -1392,33 +1370,40 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface, |
michael@0 | 73 | cairo_clip_t *clip, |
michael@0 | 74 | int *remaining_glyphs) |
michael@0 | 75 | { |
michael@0 | 76 | +#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT) |
michael@0 | 77 | cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; |
michael@0 | 78 | |
michael@0 | 79 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 80 | - /* If we have an equivalent X surface, let the xlib surface handle this |
michael@0 | 81 | - * until we figure out how to do this natively with Qt. |
michael@0 | 82 | - */ |
michael@0 | 83 | - if (qs->xlib_equiv) { |
michael@0 | 84 | - D(fprintf(stderr, "q[%p] show_glyphs (x11 equiv) op:%s nglyphs: %d\n", abstract_surface, _opstr(op), num_glyphs)); |
michael@0 | 85 | - |
michael@0 | 86 | - for (int i = 0; i < num_glyphs; i++) { |
michael@0 | 87 | - glyphs[i].x -= qs->redir_offset.x(); |
michael@0 | 88 | - glyphs[i].y -= qs->redir_offset.y(); |
michael@0 | 89 | - } |
michael@0 | 90 | - |
michael@0 | 91 | - return (cairo_int_status_t) |
michael@0 | 92 | - _cairo_surface_show_text_glyphs (qs->xlib_equiv, |
michael@0 | 93 | - op, source, |
michael@0 | 94 | - NULL, 0, |
michael@0 | 95 | - glyphs, num_glyphs, |
michael@0 | 96 | - NULL, 0, |
michael@0 | 97 | - (cairo_text_cluster_flags_t) 0, |
michael@0 | 98 | - scaled_font, |
michael@0 | 99 | - clip); |
michael@0 | 100 | + // pick out the colour to use from the cairo source |
michael@0 | 101 | + cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) source; |
michael@0 | 102 | + cairo_scaled_glyph_t* glyph; |
michael@0 | 103 | + // documentation says you have to freeze the cache, but I don't believe it |
michael@0 | 104 | + _cairo_scaled_font_freeze_cache(scaled_font); |
michael@0 | 105 | + |
michael@0 | 106 | + QColor tempColour(solid->color.red * 255, solid->color.green * 255, solid->color.blue * 255); |
michael@0 | 107 | + QVarLengthArray<QPointF> positions(num_glyphs); |
michael@0 | 108 | + QVarLengthArray<unsigned int> glyphss(num_glyphs); |
michael@0 | 109 | + FT_Face face = cairo_ft_scaled_font_lock_face (scaled_font); |
michael@0 | 110 | + const FT_Size_Metrics& ftMetrics = face->size->metrics; |
michael@0 | 111 | + QFont font(face->family_name); |
michael@0 | 112 | + font.setStyleStrategy(QFont::NoFontMerging); |
michael@0 | 113 | + font.setBold(face->style_flags & FT_STYLE_FLAG_BOLD); |
michael@0 | 114 | + font.setItalic(face->style_flags & FT_STYLE_FLAG_ITALIC); |
michael@0 | 115 | + font.setKerning(face->face_flags & FT_FACE_FLAG_KERNING); |
michael@0 | 116 | + font.setPixelSize(ftMetrics.y_ppem); |
michael@0 | 117 | + cairo_ft_scaled_font_unlock_face(scaled_font); |
michael@0 | 118 | + qs->p->setFont(font); |
michael@0 | 119 | + qs->p->setPen(tempColour); |
michael@0 | 120 | + for (int currentGlyph = 0; currentGlyph < num_glyphs; currentGlyph++) { |
michael@0 | 121 | + positions[currentGlyph].setX(glyphs[currentGlyph].x); |
michael@0 | 122 | + positions[currentGlyph].setY(glyphs[currentGlyph].y); |
michael@0 | 123 | + glyphss[currentGlyph] = glyphs[currentGlyph].index; |
michael@0 | 124 | } |
michael@0 | 125 | -#endif |
michael@0 | 126 | - |
michael@0 | 127 | + qt_draw_glyphs(qs->p, glyphss.data(), positions.data(), num_glyphs); |
michael@0 | 128 | + _cairo_scaled_font_thaw_cache(scaled_font); |
michael@0 | 129 | + return CAIRO_INT_STATUS_SUCCESS; |
michael@0 | 130 | +#else |
michael@0 | 131 | return CAIRO_INT_STATUS_UNSUPPORTED; |
michael@0 | 132 | +#endif |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | static cairo_int_status_t |
michael@0 | 136 | @@ -1555,24 +1540,6 @@ _cairo_qt_surface_composite (cairo_operator_t op, |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | static cairo_status_t |
michael@0 | 140 | -_cairo_qt_surface_flush (void *abstract_surface) |
michael@0 | 141 | -{ |
michael@0 | 142 | - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; |
michael@0 | 143 | - |
michael@0 | 144 | - if (qs->p == NULL) |
michael@0 | 145 | - return CAIRO_STATUS_SUCCESS; |
michael@0 | 146 | - |
michael@0 | 147 | - if (qs->image || qs->pixmap) { |
michael@0 | 148 | - qs->p->end (); |
michael@0 | 149 | - qs->p->begin (qs->p->device ()); |
michael@0 | 150 | - } else { |
michael@0 | 151 | - qs->p->restore (); |
michael@0 | 152 | - } |
michael@0 | 153 | - |
michael@0 | 154 | - return CAIRO_STATUS_SUCCESS; |
michael@0 | 155 | -} |
michael@0 | 156 | - |
michael@0 | 157 | -static cairo_status_t |
michael@0 | 158 | _cairo_qt_surface_mark_dirty (void *abstract_surface, |
michael@0 | 159 | int x, int y, |
michael@0 | 160 | int width, int height) |
michael@0 | 161 | @@ -1609,7 +1576,7 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = { |
michael@0 | 162 | _cairo_qt_surface_get_extents, |
michael@0 | 163 | NULL, /* old_show_glyphs */ |
michael@0 | 164 | NULL, /* get_font_options */ |
michael@0 | 165 | - _cairo_qt_surface_flush, |
michael@0 | 166 | + NULL, /* flush */ |
michael@0 | 167 | _cairo_qt_surface_mark_dirty, |
michael@0 | 168 | NULL, /* scaled_font_fini */ |
michael@0 | 169 | NULL, /* scaled_glyph_fini */ |
michael@0 | 170 | @@ -1629,64 +1596,6 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = { |
michael@0 | 171 | NULL, /* show_text_glyphs */ |
michael@0 | 172 | }; |
michael@0 | 173 | |
michael@0 | 174 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 175 | -static cairo_surface_t * |
michael@0 | 176 | -_cairo_qt_create_xlib_surface (cairo_qt_surface_t *qs) |
michael@0 | 177 | -{ |
michael@0 | 178 | - if (!qs->p) |
michael@0 | 179 | - return NULL; |
michael@0 | 180 | - |
michael@0 | 181 | - QPaintDevice *pd = qs->p->device(); |
michael@0 | 182 | - if (!pd) |
michael@0 | 183 | - return NULL; |
michael@0 | 184 | - |
michael@0 | 185 | - QPoint offs; |
michael@0 | 186 | - QPaintDevice *rpd = QPainter::redirected(pd, &offs); |
michael@0 | 187 | - if (rpd) { |
michael@0 | 188 | - pd = rpd; |
michael@0 | 189 | - qs->redir_offset = offs; |
michael@0 | 190 | - } |
michael@0 | 191 | - |
michael@0 | 192 | - if (pd->devType() == QInternal::Widget) { |
michael@0 | 193 | - QWidget *w = (QWidget*) pd; |
michael@0 | 194 | - QX11Info xinfo = w->x11Info(); |
michael@0 | 195 | - |
michael@0 | 196 | - return cairo_xlib_surface_create (xinfo.display(), |
michael@0 | 197 | - (Drawable) w->handle (), |
michael@0 | 198 | - (Visual *) xinfo.visual (), |
michael@0 | 199 | - w->width (), w->height ()); |
michael@0 | 200 | - } else if (pd->devType() == QInternal::Pixmap) { |
michael@0 | 201 | - QPixmap *pixmap = (QPixmap*) pd; |
michael@0 | 202 | - QX11Info xinfo = pixmap->x11Info (); |
michael@0 | 203 | - XRenderPictFormat *xrender_format; |
michael@0 | 204 | - int pict_format; |
michael@0 | 205 | - |
michael@0 | 206 | - switch (pixmap->depth ()) { |
michael@0 | 207 | - case 1: |
michael@0 | 208 | - pict_format = PictStandardA1; break; |
michael@0 | 209 | - case 8: |
michael@0 | 210 | - pict_format = PictStandardA8; break; |
michael@0 | 211 | - case 24: |
michael@0 | 212 | - pict_format = PictStandardRGB24; break; |
michael@0 | 213 | - default: |
michael@0 | 214 | - ASSERT_NOT_REACHED; |
michael@0 | 215 | - case 32: |
michael@0 | 216 | - pict_format = PictStandardARGB32; break; |
michael@0 | 217 | - } |
michael@0 | 218 | - xrender_format = XRenderFindStandardFormat (xinfo.display (), |
michael@0 | 219 | - pict_format); |
michael@0 | 220 | - |
michael@0 | 221 | - return cairo_xlib_surface_create_with_xrender_format (xinfo.display(), |
michael@0 | 222 | - (Drawable) pixmap->handle (), |
michael@0 | 223 | - ScreenOfDisplay (xinfo.display (), |
michael@0 | 224 | - xinfo.screen ()), |
michael@0 | 225 | - xrender_format, |
michael@0 | 226 | - pixmap->width (), pixmap->height ()); |
michael@0 | 227 | - } else |
michael@0 | 228 | - return NULL; |
michael@0 | 229 | -} |
michael@0 | 230 | -#endif |
michael@0 | 231 | - |
michael@0 | 232 | cairo_surface_t * |
michael@0 | 233 | cairo_qt_surface_create (QPainter *painter) |
michael@0 | 234 | { |
michael@0 | 235 | @@ -1717,10 +1626,6 @@ cairo_qt_surface_create (QPainter *painter) |
michael@0 | 236 | |
michael@0 | 237 | qs->window = painter->window(); |
michael@0 | 238 | |
michael@0 | 239 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 240 | - qs->xlib_equiv = _cairo_qt_create_xlib_surface (qs); |
michael@0 | 241 | -#endif |
michael@0 | 242 | - |
michael@0 | 243 | D(fprintf(stderr, "qpainter_surface_create: window: [%d %d %d %d] pd:%d\n", |
michael@0 | 244 | qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(), |
michael@0 | 245 | qs->supports_porter_duff)); |
michael@0 | 246 | @@ -1819,10 +1724,6 @@ cairo_qt_surface_create_with_qpixmap (cairo_content_t content, |
michael@0 | 247 | |
michael@0 | 248 | qs->window = QRect(0, 0, width, height); |
michael@0 | 249 | |
michael@0 | 250 | -#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE |
michael@0 | 251 | - qs->xlib_equiv = _cairo_qt_create_xlib_surface (qs); |
michael@0 | 252 | -#endif |
michael@0 | 253 | - |
michael@0 | 254 | D(fprintf(stderr, "qpainter_surface_create: qpixmap: [%d %d %d %d] pd:%d\n", |
michael@0 | 255 | qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(), |
michael@0 | 256 | qs->supports_porter_duff)); |