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