1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33 
34 #include "qgtk2painter_p.h"
35 
36 #include <QtCore/qglobal.h>
37 
38 // This class is primarily a wrapper around the gtk painter functions
39 // and takes care of converting all such calls into cached Qt pixmaps.
40 
41 #include "qgtkstyle_p_p.h"
42 #include <private/qhexstring_p.h>
43 #include <QtWidgets/QWidget>
44 #include <QtGui/QPixmapCache>
45 
46 QT_BEGIN_NAMESPACE
47 
48 // To recover alpha we apply the gtk painting function two times to
49 // white, and black window backgrounds. This can be used to
50 // recover the premultiplied alpha channel
renderTheme(uchar * bdata,uchar * wdata,const QRect & rect) const51 QPixmap QGtk2Painter::renderTheme(uchar *bdata, uchar *wdata, const QRect &rect) const
52 {
53     const int bytecount = rect.width() * rect.height() * 4;
54     for (int index = 0; index < bytecount ; index += 4) {
55         uchar val = bdata[index + GTK_BLUE];
56         if (m_alpha) {
57             int alphaval = qMax(bdata[index + GTK_BLUE] - wdata[index + GTK_BLUE],
58                                 bdata[index + GTK_GREEN] - wdata[index + GTK_GREEN]);
59             alphaval = qMax(alphaval, bdata[index + GTK_RED] - wdata[index + GTK_RED]) + 255;
60             bdata[index + QT_ALPHA] = alphaval;
61         }
62         bdata[index + QT_RED] = bdata[index + GTK_RED];
63         bdata[index + QT_GREEN] = bdata[index + GTK_GREEN];
64         bdata[index + QT_BLUE] = val;
65     }
66     QImage converted((const uchar*)bdata, rect.width(), rect.height(), m_alpha ?
67                      QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
68 
69     if (m_hflipped || m_vflipped) {
70         return QPixmap::fromImage(converted.mirrored(m_hflipped, m_vflipped));
71     } else {
72         // on raster graphicssystem we need to do a copy here, because
73         // we intend to deallocate the qimage bits shortly after...
74         return QPixmap::fromImage(converted.copy());
75     }
76 }
77 
78 // This macro is responsible for painting any GtkStyle painting function onto a QPixmap
79 #define DRAW_TO_CACHE(draw_func)                                               \
80     if (rect.width() > QWIDGETSIZE_MAX || rect.height() > QWIDGETSIZE_MAX)     \
81         return;                                                                \
82     QRect pixmapRect(0, 0, rect.width(), rect.height());                       \
83     {                                                                          \
84         GdkPixmap *pixmap = gdk_pixmap_new((GdkDrawable*)(m_window->window),   \
85                                            rect.width(), rect.height(), -1);   \
86         if (!pixmap)                                                           \
87             return;                                                            \
88         style = gtk_style_attach (style, m_window->window);                    \
89         gdk_draw_rectangle(pixmap, m_alpha ? style->black_gc : *style->bg_gc,  \
90                            true, 0, 0, rect.width(), rect.height());           \
91         draw_func;                                                             \
92         GdkPixbuf *imgb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,          \
93                                          rect.width(), rect.height());         \
94         if (!imgb)                                                             \
95             return;                                                            \
96         imgb = gdk_pixbuf_get_from_drawable(imgb, pixmap, NULL, 0, 0, 0, 0,    \
97                                             rect.width(), rect.height());      \
98         uchar* bdata = (uchar*)gdk_pixbuf_get_pixels(imgb);                    \
99         if (m_alpha) {                                                         \
100             gdk_draw_rectangle(pixmap, style->white_gc, true, 0, 0,            \
101                                rect.width(), rect.height());                   \
102             draw_func;                                                         \
103             GdkPixbuf *imgw = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,      \
104                                              rect.width(), rect.height());     \
105             if (!imgw)                                                         \
106                 return;                                                        \
107             imgw = gdk_pixbuf_get_from_drawable(imgw, pixmap, NULL, 0, 0, 0, 0,\
108                                                 rect.width(), rect.height());  \
109             uchar* wdata = (uchar*)gdk_pixbuf_get_pixels(imgw);                \
110             cache = renderTheme(bdata, wdata, rect);                           \
111             g_object_unref(imgw);                                              \
112         } else {                                                               \
113             cache = renderTheme(bdata, 0, rect);                               \
114         }                                                                      \
115         gdk_drawable_unref(pixmap);                                            \
116         g_object_unref(imgb);                                                  \
117     }
118 
QGtk2Painter()119 QGtk2Painter::QGtk2Painter() : QGtkPainter(), m_window(QGtkStylePrivate::gtkWidget("GtkWindow"))
120 {
121 }
122 
123 // Note currently painted without alpha for performance reasons
paintBoxGap(GtkWidget * gtkWidget,const gchar * part,const QRect & paintRect,GtkStateType state,GtkShadowType shadow,GtkPositionType gap_side,gint x,gint width,GtkStyle * style)124 void QGtk2Painter::paintBoxGap(GtkWidget *gtkWidget, const gchar* part,
125                               const QRect &paintRect, GtkStateType state,
126                               GtkShadowType shadow, GtkPositionType gap_side,
127                               gint x, gint width,
128                               GtkStyle *style)
129 {
130     if (!paintRect.isValid())
131         return;
132 
133     QPixmap cache;
134     QRect rect = paintRect;
135 
136     // To avoid exhausting cache on large tabframes we cheat a bit by
137     // tiling the center part.
138 
139     const int maxHeight = 256;
140     const int border = 16;
141     if (rect.height() > maxHeight && (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM))
142         rect.setHeight(2 * border + 1);
143 
144     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget)
145                          % HexString<uchar>(gap_side)
146                          % HexString<gint>(width)
147                          % HexString<gint>(x);
148 
149     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
150         DRAW_TO_CACHE(gtk_paint_box_gap (style,
151                                            pixmap,
152                                            state,
153                                            shadow,
154                                            NULL,
155                                            gtkWidget,
156                                            (const gchar*)part,
157                                            0, 0,
158                                            rect.width(),
159                                            rect.height(),
160                                            gap_side,
161                                            x,
162                                            width));
163         if (m_usePixmapCache)
164             QPixmapCache::insert(pixmapName, cache);
165     }
166     if (rect.size() != paintRect.size()) {
167         // We assume we can stretch the middle tab part
168         // Note: the side effect of this is that pinstripe patterns will get fuzzy
169         const QSize size = cache.size();
170         // top part
171         m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top(),
172                                     paintRect.width(), border), cache,
173                              QRect(0, 0, size.width(), border));
174 
175         // tiled center part
176         QPixmap tilePart(cache.width(), 1);
177         QPainter scanLinePainter(&tilePart);
178         scanLinePainter.drawPixmap(QRect(0, 0, tilePart.width(), tilePart.height()), cache, QRect(0, border, size.width(), 1));
179         scanLinePainter.end();
180         m_painter->drawTiledPixmap(QRect(paintRect.left(), paintRect.top() + border,
181                                          paintRect.width(), paintRect.height() - 2*border), tilePart);
182 
183         // bottom part
184         m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top() + paintRect.height() - border,
185                                     paintRect.width(), border), cache,
186                              QRect(0, size.height() - border, size.width(), border));
187     } else
188         m_painter->drawPixmap(paintRect.topLeft(), cache);
189 }
190 
paintBox(GtkWidget * gtkWidget,const gchar * part,const QRect & paintRect,GtkStateType state,GtkShadowType shadow,GtkStyle * style,const QString & pmKey)191 void QGtk2Painter::paintBox(GtkWidget *gtkWidget, const gchar* part,
192                            const QRect &paintRect, GtkStateType state,
193                            GtkShadowType shadow, GtkStyle *style,
194                            const QString &pmKey)
195 {
196     if (!paintRect.isValid())
197         return;
198 
199     QPixmap cache;
200     QRect rect = paintRect;
201 
202     // To avoid exhausting cache on large tabframes we cheat a bit by
203     // tiling the center part.
204 
205     const int maxHeight = 256;
206     const int maxArea = 256*512;
207     const int border = 32;
208     if (rect.height() > maxHeight && (rect.width()*rect.height() > maxArea))
209         rect.setHeight(2 * border + 1);
210 
211     QString pixmapName = uniqueName(QLS(part), state, shadow,
212                                     rect.size(), gtkWidget) % pmKey;
213 
214     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
215         DRAW_TO_CACHE(gtk_paint_box (style,
216                                            pixmap,
217                                            state,
218                                            shadow,
219                                            NULL,
220                                            gtkWidget,
221                                            part,
222                                            0, 0,
223                                            rect.width(),
224                                            rect.height()));
225         if (m_usePixmapCache)
226             QPixmapCache::insert(pixmapName, cache);
227     }
228     if (rect.size() != paintRect.size()) {
229         // We assume we can stretch the middle tab part
230         // Note: the side effect of this is that pinstripe patterns will get fuzzy
231         const QSize size = cache.size();
232         // top part
233         m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top(),
234                                     paintRect.width(), border), cache,
235                               QRect(0, 0, size.width(), border));
236 
237         // tiled center part
238         QPixmap tilePart(cache.width(), 1);
239         QPainter scanLinePainter(&tilePart);
240         scanLinePainter.drawPixmap(QRect(0, 0, tilePart.width(), tilePart.height()), cache, QRect(0, border, size.width(), 1));
241         scanLinePainter.end();
242         m_painter->drawTiledPixmap(QRect(paintRect.left(), paintRect.top() + border,
243                                          paintRect.width(), paintRect.height() - 2*border), tilePart);
244 
245         // bottom part
246         m_painter->drawPixmap(QRect(paintRect.left(), paintRect.top() + paintRect.height() - border,
247                                     paintRect.width(), border), cache,
248                               QRect(0, size.height() - border, size.width(), border));
249     } else
250         m_painter->drawPixmap(paintRect.topLeft(), cache);
251 }
252 
paintHline(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkStyle * style,int x1,int x2,int y,const QString & pmKey)253 void QGtk2Painter::paintHline(GtkWidget *gtkWidget, const gchar* part,
254                              const QRect &rect, GtkStateType state,
255                              GtkStyle *style, int x1, int x2, int y,
256                              const QString &pmKey)
257 {
258     if (!rect.isValid())
259         return;
260 
261     QPixmap cache;
262     QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget)
263                          % HexString<int>(x1)
264                          % HexString<int>(x2)
265                          % HexString<int>(y)
266                          % pmKey;
267     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
268         DRAW_TO_CACHE(gtk_paint_hline (style,
269                                          pixmap,
270                                          state,
271                                          NULL,
272                                          gtkWidget,
273                                          part,
274                                          x1, x2, y));
275         if (m_usePixmapCache)
276             QPixmapCache::insert(pixmapName, cache);
277     }
278 
279     m_painter->drawPixmap(rect.topLeft(), cache);
280 }
281 
paintVline(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkStyle * style,int y1,int y2,int x,const QString & pmKey)282 void QGtk2Painter::paintVline(GtkWidget *gtkWidget, const gchar* part,
283                              const QRect &rect, GtkStateType state,
284                              GtkStyle *style, int y1, int y2, int x,
285                              const QString &pmKey)
286 {
287     if (!rect.isValid())
288         return;
289 
290     QPixmap cache;
291     QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget)
292                         % HexString<int>(y1)
293                         % HexString<int>(y2)
294                         % HexString<int>(x)
295                         % pmKey;
296 
297     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
298         DRAW_TO_CACHE(gtk_paint_vline (style,
299                                          pixmap,
300                                          state,
301                                          NULL,
302                                          gtkWidget,
303                                          part,
304                                          y1, y2,
305                                          x));
306         if (m_usePixmapCache)
307             QPixmapCache::insert(pixmapName, cache);
308     }
309     m_painter->drawPixmap(rect.topLeft(), cache);
310 }
311 
312 
paintExpander(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkExpanderStyle expander_state,GtkStyle * style,const QString & pmKey)313 void QGtk2Painter::paintExpander(GtkWidget *gtkWidget,
314                                 const gchar* part, const QRect &rect,
315                                 GtkStateType state, GtkExpanderStyle expander_state,
316                                 GtkStyle *style, const QString &pmKey)
317 {
318     if (!rect.isValid())
319         return;
320 
321     QPixmap cache;
322     QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget)
323                          % HexString<uchar>(expander_state)
324                          % pmKey;
325 
326     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
327         DRAW_TO_CACHE(gtk_paint_expander (style, pixmap,
328                                             state, NULL,
329                                             gtkWidget, part,
330                                             rect.width()/2,
331                                             rect.height()/2,
332                                             expander_state));
333         if (m_usePixmapCache)
334             QPixmapCache::insert(pixmapName, cache);
335     }
336 
337     m_painter->drawPixmap(rect.topLeft(), cache);
338 }
339 
paintFocus(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkStyle * style,const QString & pmKey)340 void QGtk2Painter::paintFocus(GtkWidget *gtkWidget, const gchar* part,
341                              const QRect &rect, GtkStateType state,
342                              GtkStyle *style, const QString &pmKey)
343 {
344     if (!rect.isValid())
345         return;
346 
347     QPixmap cache;
348     QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) % pmKey;
349     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
350         DRAW_TO_CACHE(gtk_paint_focus (style, pixmap, state, NULL,
351                                          gtkWidget,
352                                          part,
353                                          0, 0,
354                                          rect.width(),
355                                          rect.height()));
356         if (m_usePixmapCache)
357             QPixmapCache::insert(pixmapName, cache);
358     }
359 
360     m_painter->drawPixmap(rect.topLeft(), cache);
361 }
362 
363 
paintResizeGrip(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkShadowType shadow,GdkWindowEdge edge,GtkStyle * style,const QString & pmKey)364 void QGtk2Painter::paintResizeGrip(GtkWidget *gtkWidget, const gchar* part,
365                                   const QRect &rect, GtkStateType state,
366                                   GtkShadowType shadow, GdkWindowEdge edge,
367                                   GtkStyle *style, const QString &pmKey)
368 {
369     if (!rect.isValid())
370         return;
371 
372     QPixmap cache;
373     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) % pmKey;
374     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
375         DRAW_TO_CACHE(gtk_paint_resize_grip (style, pixmap, state,
376                                                NULL, gtkWidget,
377                                                part, edge, 0, 0,
378                                                rect.width(),
379                                                rect.height()));
380         if (m_usePixmapCache)
381             QPixmapCache::insert(pixmapName, cache);
382     }
383 
384     m_painter->drawPixmap(rect.topLeft(), cache);
385 }
386 
387 
paintArrow(GtkWidget * gtkWidget,const gchar * part,const QRect & arrowrect,GtkArrowType arrow_type,GtkStateType state,GtkShadowType shadow,gboolean fill,GtkStyle * style,const QString & pmKey)388 void QGtk2Painter::paintArrow(GtkWidget *gtkWidget, const gchar* part,
389                              const QRect &arrowrect, GtkArrowType arrow_type,
390                              GtkStateType state, GtkShadowType shadow,
391                              gboolean fill, GtkStyle *style, const QString &pmKey)
392 {
393     QRect rect = m_cliprect.isValid() ? m_cliprect : arrowrect;
394     if (!rect.isValid())
395         return;
396 
397     QPixmap cache;
398     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size())
399                          % HexString<uchar>(arrow_type)
400                          % pmKey;
401 
402     GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
403     int xOffset = m_cliprect.isValid() ? arrowrect.x() - m_cliprect.x() : 0;
404     int yOffset = m_cliprect.isValid() ? arrowrect.y() - m_cliprect.y() : 0;
405     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
406         DRAW_TO_CACHE(gtk_paint_arrow (style, pixmap, state, shadow,
407                                          &gtkCliprect,
408                                          gtkWidget,
409                                          part,
410                                          arrow_type, fill,
411                                          xOffset, yOffset,
412                                          arrowrect.width(),
413                                          arrowrect.height()))
414         if (m_usePixmapCache)
415             QPixmapCache::insert(pixmapName, cache);
416     }
417 
418     m_painter->drawPixmap(rect.topLeft(), cache);
419 }
420 
421 
paintHandle(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkShadowType shadow,GtkOrientation orientation,GtkStyle * style)422 void QGtk2Painter::paintHandle(GtkWidget *gtkWidget, const gchar* part, const QRect &rect,
423                               GtkStateType state, GtkShadowType shadow,
424                               GtkOrientation orientation, GtkStyle *style)
425 {
426     if (!rect.isValid())
427         return;
428 
429     QPixmap cache;
430     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size())
431                          % HexString<uchar>(orientation);
432 
433     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
434         DRAW_TO_CACHE(gtk_paint_handle (style,
435                                           pixmap,
436                                           state,
437                                           shadow,
438                                           NULL,
439                                           gtkWidget,
440                                           part, 0, 0,
441                                           rect.width(),
442                                           rect.height(),
443                                           orientation));
444         if (m_usePixmapCache)
445             QPixmapCache::insert(pixmapName, cache);
446     }
447     m_painter->drawPixmap(rect.topLeft(), cache);
448 }
449 
450 
paintSlider(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkShadowType shadow,GtkStyle * style,GtkOrientation orientation,const QString & pmKey)451 void QGtk2Painter::paintSlider(GtkWidget *gtkWidget, const gchar* part, const QRect &rect,
452                               GtkStateType state, GtkShadowType shadow,
453                               GtkStyle *style, GtkOrientation orientation,
454                               const QString &pmKey)
455 {
456     if (!rect.isValid())
457         return;
458 
459     QPixmap cache;
460     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) % pmKey;
461     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
462         DRAW_TO_CACHE(gtk_paint_slider (style,
463                                           pixmap,
464                                           state,
465                                           shadow,
466                                           NULL,
467                                           gtkWidget,
468                                           part,
469                                           0, 0,
470                                           rect.width(),
471                                           rect.height(),
472                                           orientation));
473         if (m_usePixmapCache)
474             QPixmapCache::insert(pixmapName, cache);
475     }
476     m_painter->drawPixmap(rect.topLeft(), cache);
477 }
478 
479 
paintShadow(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkShadowType shadow,GtkStyle * style,const QString & pmKey)480 void QGtk2Painter::paintShadow(GtkWidget *gtkWidget, const gchar* part,
481                               const QRect &rect, GtkStateType state,
482                               GtkShadowType shadow, GtkStyle *style,
483                               const QString &pmKey)
484 
485 {
486     if (!rect.isValid())
487         return;
488 
489     QPixmap cache;
490     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey;
491     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
492         DRAW_TO_CACHE(gtk_paint_shadow(style, pixmap, state, shadow, NULL,
493                                          gtkWidget, part, 0, 0, rect.width(), rect.height()));
494         if (m_usePixmapCache)
495             QPixmapCache::insert(pixmapName, cache);
496     }
497     m_painter->drawPixmap(rect.topLeft(), cache);
498 }
499 
paintFlatBox(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkShadowType shadow,GtkStyle * style,const QString & pmKey)500 void QGtk2Painter::paintFlatBox(GtkWidget *gtkWidget, const gchar* part,
501                                const QRect &rect, GtkStateType state,
502                                GtkShadowType shadow, GtkStyle *style,
503                                const QString &pmKey)
504 {
505     if (!rect.isValid())
506         return;
507     QPixmap cache;
508     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey;
509     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
510         DRAW_TO_CACHE(gtk_paint_flat_box (style,
511                                             pixmap,
512                                             state,
513                                             shadow,
514                                             NULL,
515                                             gtkWidget,
516                                             part, 0, 0,
517                                             rect.width(),
518                                             rect.height()));
519         if (m_usePixmapCache)
520             QPixmapCache::insert(pixmapName, cache);
521     }
522     m_painter->drawPixmap(rect.topLeft(), cache);
523 }
524 
paintExtention(GtkWidget * gtkWidget,const gchar * part,const QRect & rect,GtkStateType state,GtkShadowType shadow,GtkPositionType gap_pos,GtkStyle * style)525 void QGtk2Painter::paintExtention(GtkWidget *gtkWidget,
526                                  const gchar *part, const QRect &rect,
527                                  GtkStateType state, GtkShadowType shadow,
528                                  GtkPositionType gap_pos, GtkStyle *style)
529 {
530     if (!rect.isValid())
531         return;
532 
533     QPixmap cache;
534     QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget)
535                          % HexString<uchar>(gap_pos);
536 
537     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
538         DRAW_TO_CACHE(gtk_paint_extension (style, pixmap, state, shadow,
539                                              NULL, gtkWidget,
540                                              (const gchar*)part, 0, 0,
541                                              rect.width(),
542                                              rect.height(),
543                                              gap_pos));
544         if (m_usePixmapCache)
545             QPixmapCache::insert(pixmapName, cache);
546     }
547 
548     m_painter->drawPixmap(rect.topLeft(), cache);
549 }
550 
paintOption(GtkWidget * gtkWidget,const QRect & radiorect,GtkStateType state,GtkShadowType shadow,GtkStyle * style,const QString & detail)551 void QGtk2Painter::paintOption(GtkWidget *gtkWidget, const QRect &radiorect,
552                               GtkStateType state, GtkShadowType shadow,
553                               GtkStyle *style, const QString &detail)
554 
555 {
556     QRect rect = m_cliprect.isValid() ? m_cliprect : radiorect;
557     if (!rect.isValid())
558         return;
559 
560     QPixmap cache;
561     QString pixmapName = uniqueName(detail, state, shadow, rect.size());
562     GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
563     int xOffset = m_cliprect.isValid() ? radiorect.x() - m_cliprect.x() : 0;
564     int yOffset = m_cliprect.isValid() ? radiorect.y() - m_cliprect.y() : 0;
565     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
566         DRAW_TO_CACHE(gtk_paint_option(style, pixmap,
567                                          state, shadow,
568                                          &gtkCliprect,
569                                          gtkWidget,
570                                          detail.toLatin1(),
571                                          xOffset, yOffset,
572                                          radiorect.width(),
573                                          radiorect.height()));
574 
575         if (m_usePixmapCache)
576             QPixmapCache::insert(pixmapName, cache);
577     }
578 
579     m_painter->drawPixmap(rect.topLeft(), cache);
580 }
581 
paintCheckbox(GtkWidget * gtkWidget,const QRect & checkrect,GtkStateType state,GtkShadowType shadow,GtkStyle * style,const QString & detail)582 void QGtk2Painter::paintCheckbox(GtkWidget *gtkWidget, const QRect &checkrect,
583                                 GtkStateType state, GtkShadowType shadow,
584                                 GtkStyle *style, const QString &detail)
585 
586 {
587     QRect rect = m_cliprect.isValid() ? m_cliprect : checkrect;
588     if (!rect.isValid())
589         return;
590 
591     QPixmap cache;
592     QString pixmapName = uniqueName(detail, state, shadow, rect.size());
593     GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
594     int xOffset = m_cliprect.isValid() ? checkrect.x() - m_cliprect.x() : 0;
595     int yOffset = m_cliprect.isValid() ? checkrect.y() - m_cliprect.y() : 0;
596     if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
597         DRAW_TO_CACHE(gtk_paint_check (style,
598                                          pixmap,
599                                          state,
600                                          shadow,
601                                          &gtkCliprect,
602                                          gtkWidget,
603                                          detail.toLatin1(),
604                                          xOffset, yOffset,
605                                          checkrect.width(),
606                                          checkrect.height()));
607         if (m_usePixmapCache)
608             QPixmapCache::insert(pixmapName, cache);
609     }
610 
611     m_painter->drawPixmap(rect.topLeft(), cache);
612 }
613 
614 QT_END_NAMESPACE
615