Qt 4.8
qpaintengine_x11.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qplatformdefs.h"
43 
44 #include "private/qpixmap_x11_p.h"
45 
46 #include "qapplication.h"
47 #include "qdebug.h"
48 #include "qfont.h"
49 #include "qwidget.h"
50 #include "qbitmap.h"
51 #include "qpixmapcache.h"
52 #include "qtextcodec.h"
53 #include "qcoreevent.h"
54 #include "qiodevice.h"
55 #include <qmath.h>
56 
57 #include "qpainter_p.h"
58 #include <qtextlayout.h>
59 #include <qvarlengtharray.h>
60 #include <private/qfont_p.h>
61 #include <private/qtextengine_p.h>
62 #include <private/qpaintengine_x11_p.h>
63 #include <private/qfontengine_x11_p.h>
64 #include <private/qwidget_p.h>
65 #include <private/qpainterpath_p.h>
66 
67 #include "qpen.h"
68 #include "qcolor.h"
69 #include "qcolormap.h"
70 
71 #include <private/qpaintengine_p.h>
72 #include "qpaintengine_x11_p.h"
73 
74 #include <private/qt_x11_p.h>
75 #include <private/qnumeric_p.h>
76 #include <limits.h>
77 
78 #ifndef QT_NO_XRENDER
79 #include <private/qtessellator_p.h>
80 #endif
81 
82 #include <private/qstylehelper_p.h>
83 
85 
86 extern Drawable qt_x11Handle(const QPaintDevice *pd);
87 extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
88 extern QPixmap qt_pixmapForBrush(int brushStyle, bool invert); //in qbrush.cpp
89 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
90 
91 // use the same rounding as in qrasterizer.cpp (6 bit fixed point)
92 static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
93 
94 #undef X11 // defined in qt_x11_p.h
95 
101 {
102  if (p && p->paintEngine()
103  && p->paintEngine()->isActive()
104  && p->paintEngine()->type() == QPaintEngine::X11) {
105  return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc;
106  }
107  return 0;
108 }
109 
116 {
117  if (p && p->paintEngine()
118  && p->paintEngine()->isActive()
119  && p->paintEngine()->type() == QPaintEngine::X11) {
120  return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc_brush;
121  }
122  return 0;
123 }
124 #define X11 qt_x11Data
125 
126 #ifndef QT_NO_XRENDER
128  PictOpOver, //CompositionMode_SourceOver,
129  PictOpOverReverse, //CompositionMode_DestinationOver,
130  PictOpClear, //CompositionMode_Clear,
131  PictOpSrc, //CompositionMode_Source,
132  PictOpDst, //CompositionMode_Destination,
133  PictOpIn, //CompositionMode_SourceIn,
134  PictOpInReverse, //CompositionMode_DestinationIn,
135  PictOpOut, //CompositionMode_SourceOut,
136  PictOpOutReverse, //CompositionMode_DestinationOut,
137  PictOpAtop, //CompositionMode_SourceAtop,
138  PictOpAtopReverse, //CompositionMode_DestinationAtop,
139  PictOpXor //CompositionMode_Xor
140 };
141 
143 {
145  return compositionModeToRenderOp[mode];
146 }
147 
148 static inline bool complexPictOp(int op)
149 {
150  return op != PictOpOver && op != PictOpSrc;
151 }
152 #endif
153 
154 // hack, so we don't have to make QRegion::clipRectangles() public or include
155 // X11 headers in qregion.h
156 Q_GUI_EXPORT void *qt_getClipRects(const QRegion &r, int &num)
157 {
158  return r.clipRectangles(num);
159 }
160 
161 static inline void x11SetClipRegion(Display *dpy, GC gc, GC gc2,
162 #ifndef QT_NO_XRENDER
163  Picture picture,
164 #else
165  Qt::HANDLE picture,
166 #endif
167  const QRegion &r)
168 {
169  int num;
170  XRectangle *rects = (XRectangle *)qt_getClipRects(r, num);
171 
172  if (gc)
173  XSetClipRectangles( dpy, gc, 0, 0, rects, num, YXBanded );
174  if (gc2)
175  XSetClipRectangles( dpy, gc2, 0, 0, rects, num, YXBanded );
176 
177 #ifndef QT_NO_XRENDER
178  if (picture)
179  XRenderSetPictureClipRectangles(dpy, picture, 0, 0, rects, num);
180 #else
181  Q_UNUSED(picture);
182 #endif // QT_NO_XRENDER
183 }
184 
185 
186 static inline void x11ClearClipRegion(Display *dpy, GC gc, GC gc2,
187 #ifndef QT_NO_XRENDER
188  Picture picture
189 #else
190  Qt::HANDLE picture
191 #endif
192  )
193 {
194  if (gc)
195  XSetClipMask(dpy, gc, XNone);
196  if (gc2)
197  XSetClipMask(dpy, gc2, XNone);
198 
199 #ifndef QT_NO_XRENDER
200  if (picture) {
201  XRenderPictureAttributes attrs;
202  attrs.clip_mask = XNone;
203  XRenderChangePicture (dpy, picture, CPClipMask, &attrs);
204  }
205 #else
206  Q_UNUSED(picture);
207 #endif // QT_NO_XRENDER
208 }
209 
210 
211 #define DITHER_SIZE 16
213  { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
214  { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
215  { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
216  { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
217  { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
218  { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
219  { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
220  { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
221  { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
222  { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
223  { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
224  { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
225  { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
226  { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
227  { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
228  { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
229 };
230 
231 static QPixmap qt_patternForAlpha(uchar alpha, int screen)
232 {
233  QPixmap pm;
234  QString key = QLatin1Literal("$qt-alpha-brush$")
235  % HexString<uchar>(alpha)
236  % HexString<int>(screen);
237 
238  if (!QPixmapCache::find(key, pm)) {
239  // #### why not use a mono image here????
241  pattern.fill(0xffffffff);
242  for (int y = 0; y < DITHER_SIZE; ++y) {
243  for (int x = 0; x < DITHER_SIZE; ++x) {
244  if (base_dither_matrix[x][y] <= alpha)
245  pattern.setPixel(x, y, 0x00000000);
246  }
247  }
248  pm = QBitmap::fromImage(pattern);
249  pm.x11SetScreen(screen);
250  QPixmapCache::insert(key, pm);
251  }
252  return pm;
253 }
254 
255 #if !defined(QT_NO_XRENDER)
256 
258 {
259 public:
262  XTrapezoid *traps;
264  int size;
265  void addTrap(const Trapezoid &trap);
266  QRect tessellate(const QPointF *points, int nPoints, bool winding) {
267  size = 0;
268  setWinding(winding);
269  return QTessellator::tessellate(points, nPoints).toRect();
270  }
271  void done() {
272  if (allocated > 64) {
273  free(traps);
274  traps = 0;
275  allocated = 0;
276  }
277  }
278 };
279 
281 {
282  if (size == allocated) {
283  allocated = qMax(2*allocated, 64);
284  traps = q_check_ptr((XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid)));
285  }
286  traps[size].top = Q27Dot5ToXFixed(trap.top);
287  traps[size].bottom = Q27Dot5ToXFixed(trap.bottom);
288  traps[size].left.p1.x = Q27Dot5ToXFixed(trap.topLeft->x);
289  traps[size].left.p1.y = Q27Dot5ToXFixed(trap.topLeft->y);
290  traps[size].left.p2.x = Q27Dot5ToXFixed(trap.bottomLeft->x);
291  traps[size].left.p2.y = Q27Dot5ToXFixed(trap.bottomLeft->y);
292  traps[size].right.p1.x = Q27Dot5ToXFixed(trap.topRight->x);
293  traps[size].right.p1.y = Q27Dot5ToXFixed(trap.topRight->y);
294  traps[size].right.p2.x = Q27Dot5ToXFixed(trap.bottomRight->x);
295  traps[size].right.p2.y = Q27Dot5ToXFixed(trap.bottomRight->y);
296  ++size;
297 }
298 
299 #endif // !defined(QT_NO_XRENDER)
300 
301 
302 #ifndef QT_NO_XRENDER
303 static Picture getPatternFill(int screen, const QBrush &b)
304 {
305  if (!X11->use_xrender)
306  return XNone;
307 
308  XRenderColor color = X11->preMultiply(b.color());
309  XRenderColor bg_color;
310 
311  bg_color = X11->preMultiply(QColor(0, 0, 0, 0));
312 
313  for (int i = 0; i < X11->pattern_fill_count; ++i) {
314  if (X11->pattern_fills[i].screen == screen
315  && X11->pattern_fills[i].opaque == false
316  && X11->pattern_fills[i].style == b.style()
317  && X11->pattern_fills[i].color.alpha == color.alpha
318  && X11->pattern_fills[i].color.red == color.red
319  && X11->pattern_fills[i].color.green == color.green
320  && X11->pattern_fills[i].color.blue == color.blue
321  && X11->pattern_fills[i].bg_color.alpha == bg_color.alpha
322  && X11->pattern_fills[i].bg_color.red == bg_color.red
323  && X11->pattern_fills[i].bg_color.green == bg_color.green
324  && X11->pattern_fills[i].bg_color.blue == bg_color.blue)
325  return X11->pattern_fills[i].picture;
326  }
327  // none found, replace one
328  int i = qrand() % 16;
329 
330  if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) {
331  XRenderFreePicture (X11->display, X11->pattern_fills[i].picture);
332  X11->pattern_fills[i].picture = 0;
333  }
334 
335  if (!X11->pattern_fills[i].picture) {
336  Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 8, 8, 32);
337  XRenderPictureAttributes attrs;
338  attrs.repeat = True;
339  X11->pattern_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
340  XRenderFindStandardFormat(X11->display, PictStandardARGB32),
341  CPRepeat, &attrs);
342  XFreePixmap (X11->display, pixmap);
343  }
344 
345  X11->pattern_fills[i].screen = screen;
346  X11->pattern_fills[i].color = color;
347  X11->pattern_fills[i].bg_color = bg_color;
348  X11->pattern_fills[i].opaque = false;
349  X11->pattern_fills[i].style = b.style();
350 
351  XRenderFillRectangle(X11->display, PictOpSrc, X11->pattern_fills[i].picture, &bg_color, 0, 0, 8, 8);
352 
353  QPixmap pattern(qt_pixmapForBrush(b.style(), true));
354  XRenderPictureAttributes attrs;
355  attrs.repeat = true;
356  XRenderChangePicture(X11->display, pattern.x11PictureHandle(), CPRepeat, &attrs);
357 
358  Picture fill_fg = X11->getSolidFill(screen, b.color());
359  XRenderComposite(X11->display, PictOpOver, fill_fg, pattern.x11PictureHandle(),
360  X11->pattern_fills[i].picture,
361  0, 0, 0, 0, 0, 0, 8, 8);
362 
363  return X11->pattern_fills[i].picture;
364 }
365 
366 static void qt_render_bitmap(Display *dpy, int scrn, Picture src, Picture dst,
367  int sx, int sy, int x, int y, int sw, int sh,
368  const QPen &pen)
369 {
370  Picture fill_fg = X11->getSolidFill(scrn, pen.color());
371  XRenderComposite(dpy, PictOpOver,
372  fill_fg, src, dst, sx, sy, sx, sy, x, y, sw, sh);
373 }
374 #endif
375 
377 {
378  dpy = 0;
379  scrn = 0;
380  hd = 0;
381  picture = 0;
382  xinfo = 0;
383 #ifndef QT_NO_XRENDER
384  current_brush = 0;
385  composition_mode = PictOpOver;
386  tessellator = new QXRenderTessellator;
387 #endif
388 }
389 
391 {
392  if (adapted_pen_origin)
393  XSetTSOrigin(dpy, gc, p.x(), p.y());
394  if (adapted_brush_origin)
395  XSetTSOrigin(dpy, gc_brush, p.x(), p.y());
396 }
397 
399 {
400  if (adapted_pen_origin)
401  XSetTSOrigin(dpy, gc, 0, 0);
402  if (adapted_brush_origin)
403  XSetTSOrigin(dpy, gc_brush, 0, 0);
404 }
405 
407 {
408  int clipped_count = 0;
409  qt_float_point *clipped_points = 0;
410  polygonClipper.clipPolygon((qt_float_point *) poly.data(), poly.size(),
411  &clipped_points, &clipped_count);
412  clipped_poly->resize(clipped_count);
413  for (int i=0; i<clipped_count; ++i)
414  (*clipped_poly)[i] = *((QPointF *)(&clipped_points[i]));
415 }
416 
418 {
420  QPainter *painter = q->state ? static_cast<QPainterState *>(q->state)->painter : 0;
421  if (painter && painter->hasClipping()) {
422  if (q->testDirty(QPaintEngine::DirtyTransform))
423  q->updateMatrix(q->state->transform());
424  QPolygonF clip_poly_dev(matrix.map(painter->clipPath().toFillPolygon()));
425  QPolygonF clipped_poly_dev;
426  clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
427  q->updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip);
428  } else {
429  q->updateClipRegion_dev(QRegion(), Qt::NoClip);
430  }
431 }
432 
433 static QPaintEngine::PaintEngineFeatures qt_decide_features()
434 {
435  QPaintEngine::PaintEngineFeatures features =
441 
442  if (X11->use_xrender) {
443  features |= QPaintEngine::Antialiasing;
444  features |= QPaintEngine::PorterDuff;
445  features |= QPaintEngine::MaskedBrush;
446 #if 0
447  if (X11->xrender_version > 10) {
449  // ###
450  }
451 #endif
452  }
453 
454  return features;
455 }
456 
457 /*
458  * QX11PaintEngine members
459  */
460 
463 {
464  d_func()->init();
465 }
466 
469 {
470  d_func()->init();
471 }
472 
474 {
475 #ifndef QT_NO_XRENDER
477  delete d->tessellator;
478 #endif
479 }
480 
482 {
484  d->xinfo = qt_x11Info(pdev);
485  QWidget *w = d->pdev->devType() == QInternal::Widget ? static_cast<QWidget *>(d->pdev) : 0;
486  const bool isAlienWidget = w && !w->internalWinId() && w->testAttribute(Qt::WA_WState_Created);
487 #ifndef QT_NO_XRENDER
488  if (w) {
489  if (isAlienWidget)
490  d->picture = (::Picture)w->nativeParentWidget()->x11PictureHandle();
491  else
492  d->picture = (::Picture)w->x11PictureHandle();
493  } else if (pdev->devType() == QInternal::Pixmap) {
494  const QPixmap *pm = static_cast<const QPixmap *>(pdev);
495  QX11PixmapData *data = static_cast<QX11PixmapData*>(pm->data.data());
496  if (X11->use_xrender && data->depth() != 32 && data->x11_mask)
497  data->convertToARGB32();
498  d->picture = (::Picture)static_cast<const QPixmap *>(pdev)->x11PictureHandle();
499  }
500 #else
501  d->picture = 0;
502 #endif
503  d->hd = !isAlienWidget ? qt_x11Handle(pdev) : qt_x11Handle(w->nativeParentWidget());
504 
505  Q_ASSERT(d->xinfo != 0);
506  d->dpy = d->xinfo->display(); // get display variable
507  d->scrn = d->xinfo->screen(); // get screen variable
508 
509  d->crgn = QRegion();
510  d->gc = XCreateGC(d->dpy, d->hd, 0, 0);
511  d->gc_brush = XCreateGC(d->dpy, d->hd, 0, 0);
512  d->has_alpha_brush = false;
513  d->has_alpha_pen = false;
514  d->has_clipping = false;
515  d->has_complex_xform = false;
516  d->has_scaling_xform = false;
517  d->has_non_scaling_xform = true;
518  d->xform_scale = 1;
519  d->has_custom_pen = false;
520  d->matrix = QTransform();
521  d->pdev_depth = d->pdev->depth();
522  d->render_hints = 0;
523  d->txop = QTransform::TxNone;
524  d->use_path_fallback = false;
525 #if !defined(QT_NO_XRENDER)
526  d->composition_mode = PictOpOver;
527 #endif
528  d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3;
529  d->opacity = 1;
530 
531  // Set up the polygon clipper. Note: This will only work in
532  // polyline mode as long as we have a buffer zone, since a
533  // polyline may be clipped into several non-connected polylines.
534  const int BUFFERZONE = 1000;
535  QRect devClipRect(-BUFFERZONE, -BUFFERZONE,
536  pdev->width() + 2*BUFFERZONE, pdev->height() + 2*BUFFERZONE);
537  d->polygonClipper.setBoundingRect(devClipRect);
538 
539  if (isAlienWidget) {
540  // Set system clip for alien widgets painting outside the paint event.
541  // This is not a problem with native windows since the windowing system
542  // will handle the clip.
543  QWidgetPrivate *wd = w->d_func();
544  QRegion widgetClip(wd->clipRect());
545  wd->clipToEffectiveMask(widgetClip);
546  wd->subtractOpaqueSiblings(widgetClip);
547  widgetClip.translate(w->mapTo(w->nativeParentWidget(), QPoint()));
548  setSystemClip(widgetClip);
549  }
550 
551  QPixmap::x11SetDefaultScreen(d->xinfo->screen());
552 
553  if (w && w->testAttribute(Qt::WA_PaintUnclipped)) { // paint direct on device
556  XSetSubwindowMode(d->dpy, d->gc, IncludeInferiors);
557  XSetSubwindowMode(d->dpy, d->gc_brush, IncludeInferiors);
558 #ifndef QT_NO_XRENDER
559  XRenderPictureAttributes attrs;
560  attrs.subwindow_mode = IncludeInferiors;
561  XRenderChangePicture(d->dpy, d->picture, CPSubwindowMode, &attrs);
562 #endif
563  }
564 
569 
570  return true;
571 }
572 
574 {
576 
577 #if !defined(QT_NO_XRENDER)
578  if (d->picture) {
579  // reset clipping/subwindow mode on our render picture
580  XRenderPictureAttributes attrs;
581  attrs.subwindow_mode = ClipByChildren;
582  attrs.clip_mask = XNone;
583  XRenderChangePicture(d->dpy, d->picture, CPClipMask|CPSubwindowMode, &attrs);
584  }
585 #endif
586 
587  if (d->gc_brush && d->pdev->painters < 2) {
588  XFreeGC(d->dpy, d->gc_brush);
589  d->gc_brush = 0;
590  }
591 
592  if (d->gc && d->pdev->painters < 2) {
593  XFreeGC(d->dpy, d->gc);
594  d->gc = 0;
595  }
596 
597  // Restore system clip for alien widgets painting outside the paint event.
598  if (d->pdev->devType() == QInternal::Widget && !static_cast<QWidget *>(d->pdev)->internalWinId())
600 
601  return true;
602 }
603 
604 static bool clipLine(QLineF *line, const QRect &rect)
605 {
606  qreal x1 = line->x1();
607  qreal x2 = line->x2();
608  qreal y1 = line->y1();
609  qreal y2 = line->y2();
610 
611  qreal left = rect.x();
612  qreal right = rect.x() + rect.width() - 1;
613  qreal top = rect.y();
614  qreal bottom = rect.y() + rect.height() - 1;
615 
616  enum { Left, Right, Top, Bottom };
617  // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html
618  int p1 = ((x1 < left) << Left)
619  | ((x1 > right) << Right)
620  | ((y1 < top) << Top)
621  | ((y1 > bottom) << Bottom);
622  int p2 = ((x2 < left) << Left)
623  | ((x2 > right) << Right)
624  | ((y2 < top) << Top)
625  | ((y2 > bottom) << Bottom);
626 
627  if (p1 & p2)
628  // completely outside
629  return false;
630 
631  if (p1 | p2) {
632  qreal dx = x2 - x1;
633  qreal dy = y2 - y1;
634 
635  // clip x coordinates
636  if (x1 < left) {
637  y1 += dy/dx * (left - x1);
638  x1 = left;
639  } else if (x1 > right) {
640  y1 -= dy/dx * (x1 - right);
641  x1 = right;
642  }
643  if (x2 < left) {
644  y2 += dy/dx * (left - x2);
645  x2 = left;
646  } else if (x2 > right) {
647  y2 -= dy/dx * (x2 - right);
648  x2 = right;
649  }
650  p1 = ((y1 < top) << Top)
651  | ((y1 > bottom) << Bottom);
652  p2 = ((y2 < top) << Top)
653  | ((y2 > bottom) << Bottom);
654  if (p1 & p2)
655  return false;
656  // clip y coordinates
657  if (y1 < top) {
658  x1 += dx/dy * (top - y1);
659  y1 = top;
660  } else if (y1 > bottom) {
661  x1 -= dx/dy * (y1 - bottom);
662  y1 = bottom;
663  }
664  if (y2 < top) {
665  x2 += dx/dy * (top - y2);
666  y2 = top;
667  } else if (y2 > bottom) {
668  x2 -= dx/dy * (y2 - bottom);
669  y2 = bottom;
670  }
671  *line = QLineF(QPointF(x1, y1), QPointF(x2, y2));
672  }
673  return true;
674 }
675 
676 void QX11PaintEngine::drawLines(const QLine *lines, int lineCount)
677 {
678  Q_ASSERT(lines);
679  Q_ASSERT(lineCount);
681  if (d->has_alpha_brush
682  || d->has_alpha_pen
683  || d->has_custom_pen
684  || (d->cpen.widthF() > 0 && d->has_complex_xform
685  && !d->has_non_scaling_xform)
686  || (d->render_hints & QPainter::Antialiasing)) {
687  for (int i = 0; i < lineCount; ++i) {
688  QPainterPath path(lines[i].p1());
689  path.lineTo(lines[i].p2());
690  drawPath(path);
691  }
692  return;
693  }
694 
695  if (d->has_pen) {
696  for (int i = 0; i < lineCount; ++i) {
697  QLineF linef;
698  if (d->txop == QTransform::TxNone) {
699  linef = lines[i];
700  } else {
701  linef = d->matrix.map(QLineF(lines[i]));
702  }
703  if (clipLine(&linef, d->polygonClipper.boundingRect())) {
704  int x1 = qRound(linef.x1() + aliasedCoordinateDelta);
705  int y1 = qRound(linef.y1() + aliasedCoordinateDelta);
706  int x2 = qRound(linef.x2() + aliasedCoordinateDelta);
707  int y2 = qRound(linef.y2() + aliasedCoordinateDelta);
708 
709  XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2);
710  }
711  }
712  }
713 }
714 
715 void QX11PaintEngine::drawLines(const QLineF *lines, int lineCount)
716 {
717  Q_ASSERT(lines);
718  Q_ASSERT(lineCount);
720  if (d->has_alpha_brush
721  || d->has_alpha_pen
722  || d->has_custom_pen
723  || (d->cpen.widthF() > 0 && d->has_complex_xform
724  && !d->has_non_scaling_xform)
725  || (d->render_hints & QPainter::Antialiasing)) {
726  for (int i = 0; i < lineCount; ++i) {
727  QPainterPath path(lines[i].p1());
728  path.lineTo(lines[i].p2());
729  drawPath(path);
730  }
731  return;
732  }
733 
734  if (d->has_pen) {
735  for (int i = 0; i < lineCount; ++i) {
736  QLineF linef = d->matrix.map(lines[i]);
737  if (clipLine(&linef, d->polygonClipper.boundingRect())) {
738  int x1 = qRound(linef.x1() + aliasedCoordinateDelta);
739  int y1 = qRound(linef.y1() + aliasedCoordinateDelta);
740  int x2 = qRound(linef.x2() + aliasedCoordinateDelta);
741  int y2 = qRound(linef.y2() + aliasedCoordinateDelta);
742 
743  XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2);
744  }
745  }
746  }
747 }
748 
749 static inline QLine clipStraightLine(const QRect &clip, const QLine &l)
750 {
751  if (l.p1().x() == l.p2().x()) {
752  int x = qBound(clip.left(), l.p1().x(), clip.right());
753  int y1 = qBound(clip.top(), l.p1().y(), clip.bottom());
754  int y2 = qBound(clip.top(), l.p2().y(), clip.bottom());
755 
756  return QLine(x, y1, x, y2);
757  } else {
758  Q_ASSERT(l.p1().y() == l.p2().y());
759 
760  int x1 = qBound(clip.left(), l.p1().x(), clip.right());
761  int x2 = qBound(clip.left(), l.p2().x(), clip.right());
762  int y = qBound(clip.top(), l.p1().y(), clip.bottom());
763 
764  return QLine(x1, y, x2, y);
765  }
766 }
767 
768 void QX11PaintEngine::drawRects(const QRectF *rects, int rectCount)
769 {
771  Q_ASSERT(rects);
772  Q_ASSERT(rectCount);
773 
774  if (rectCount != 1
775  || d->has_pen
776  || d->has_alpha_brush
777  || d->has_complex_xform
778  || d->has_custom_pen
779  || d->cbrush.style() != Qt::SolidPattern
780 #if !defined(QT_NO_XRENDER)
781  || complexPictOp(d->composition_mode)
782 #endif
783  )
784  {
785  QPaintEngine::drawRects(rects, rectCount);
786  return;
787  }
788 
789  QPoint alignedOffset;
790  if (d->txop == QTransform::TxTranslate) {
791  QPointF offset(d->matrix.dx(), d->matrix.dy());
792  alignedOffset = offset.toPoint();
793  if (offset != QPointF(alignedOffset)) {
794  QPaintEngine::drawRects(rects, rectCount);
795  return;
796  }
797  }
798 
799  const QRectF& r = rects[0];
800  QRect alignedRect = r.toAlignedRect();
801  if (r != QRectF(alignedRect)) {
802  QPaintEngine::drawRects(rects, rectCount);
803  return;
804  }
805  alignedRect.translate(alignedOffset);
806 
807  QRect clip(d->polygonClipper.boundingRect());
808  alignedRect = alignedRect.intersected(clip);
809  if (alignedRect.isEmpty())
810  return;
811 
812  // simple-case:
813  // the rectangle is pixel-aligned
814  // the fill brush is just a solid non-alpha color
815  // the painter transform is only integer translation
816  // ignore: antialiasing and just XFillRectangles directly
817  XRectangle xrect;
818  xrect.x = short(alignedRect.x());
819  xrect.y = short(alignedRect.y());
820  xrect.width = ushort(alignedRect.width());
821  xrect.height = ushort(alignedRect.height());
822  XFillRectangles(d->dpy, d->hd, d->gc_brush, &xrect, 1);
823 }
824 
825 void QX11PaintEngine::drawRects(const QRect *rects, int rectCount)
826 {
828  Q_ASSERT(rects);
829  Q_ASSERT(rectCount);
830 
831  if (d->has_alpha_pen
832  || d->has_complex_xform
833  || d->has_custom_pen
834  || (d->render_hints & QPainter::Antialiasing))
835  {
836  for (int i = 0; i < rectCount; ++i) {
837  QPainterPath path;
838  path.addRect(rects[i]);
839  drawPath(path);
840  }
841  return;
842  }
843 
844  QRect clip(d->polygonClipper.boundingRect());
845  QPoint offset(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
846 #if !defined(QT_NO_XRENDER)
847  ::Picture pict = d->picture;
848 
849  if (X11->use_xrender && pict && d->has_brush && d->pdev_depth != 1
850  && (d->has_texture || d->has_alpha_brush || complexPictOp(d->composition_mode)))
851  {
852  XRenderColor xc;
853  if (!d->has_texture && !d->has_pattern)
854  xc = X11->preMultiply(d->cbrush.color());
855 
856  for (int i = 0; i < rectCount; ++i) {
857  QRect r(rects[i]);
858  if (d->txop == QTransform::TxTranslate)
859  r.translate(offset);
860 
861  if (r.width() == 0 || r.height() == 0) {
862  if (d->has_pen) {
863  const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
864  XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
865  }
866  continue;
867  }
868 
869  r = r.intersected(clip);
870  if (r.isEmpty())
871  continue;
872  if (d->has_texture || d->has_pattern) {
873  XRenderComposite(d->dpy, d->composition_mode, d->current_brush, 0, pict,
874  qRound(r.x() - d->bg_origin.x()), qRound(r.y() - d->bg_origin.y()),
875  0, 0, r.x(), r.y(), r.width(), r.height());
876  } else {
877  XRenderFillRectangle(d->dpy, d->composition_mode, pict, &xc, r.x(), r.y(), r.width(), r.height());
878  }
879  if (d->has_pen)
880  XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height());
881  }
882  } else
883 #endif // !QT_NO_XRENDER
884  {
885  if (d->has_brush && d->has_pen) {
886  for (int i = 0; i < rectCount; ++i) {
887  QRect r(rects[i]);
888  if (d->txop == QTransform::TxTranslate)
889  r.translate(offset);
890 
891  if (r.width() == 0 || r.height() == 0) {
892  const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
893  XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
894  continue;
895  }
896 
897  r = r.intersected(clip);
898  if (r.isEmpty())
899  continue;
900  d->setupAdaptedOrigin(r.topLeft());
901  XFillRectangle(d->dpy, d->hd, d->gc_brush, r.x(), r.y(), r.width(), r.height());
902  XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height());
903  }
904  d->resetAdaptedOrigin();
905  } else {
906  QVarLengthArray<XRectangle> xrects(rectCount);
907  int numClipped = rectCount;
908  for (int i = 0; i < rectCount; ++i) {
909  QRect r(rects[i]);
910  if (d->txop == QTransform::TxTranslate)
911  r.translate(offset);
912 
913  if (r.width() == 0 || r.height() == 0) {
914  --numClipped;
915  if (d->has_pen) {
916  const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
917  XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
918  }
919  continue;
920  }
921 
922  r = r.intersected(clip);
923  if (r.isEmpty()) {
924  --numClipped;
925  continue;
926  }
927  xrects[i].x = short(r.x());
928  xrects[i].y = short(r.y());
929  xrects[i].width = ushort(r.width());
930  xrects[i].height = ushort(r.height());
931  }
932  if (numClipped) {
933  d->setupAdaptedOrigin(rects[0].topLeft());
934  if (d->has_brush)
935  XFillRectangles(d->dpy, d->hd, d->gc_brush, xrects.data(), numClipped);
936  else if (d->has_pen)
937  XDrawRectangles(d->dpy, d->hd, d->gc, xrects.data(), numClipped);
938  d->resetAdaptedOrigin();
939  }
940  }
941  }
942 }
943 
944 static inline void setCapStyle(int cap_style, GC gc)
945 {
946  ulong mask = GCCapStyle;
947  XGCValues vals;
948  vals.cap_style = cap_style;
949  XChangeGC(X11->display, gc, mask, &vals);
950 }
951 
952 void QX11PaintEngine::drawPoints(const QPoint *points, int pointCount)
953 {
954  Q_ASSERT(points);
955  Q_ASSERT(pointCount);
957 
958  if (!d->has_pen)
959  return;
960 
961  // use the same test here as in drawPath to ensure that we don't use the path fallback
962  // and end up in XDrawLines for pens with width <= 1
963  if (d->cpen.widthF() > 1.0f
964  || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
965  || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate))
966  {
967  Qt::PenCapStyle capStyle = d->cpen.capStyle();
968  if (capStyle == Qt::FlatCap) {
969  setCapStyle(CapProjecting, d->gc);
970  d->cpen.setCapStyle(Qt::SquareCap);
971  }
972  const QPoint *end = points + pointCount;
973  while (points < end) {
974  QPainterPath path;
975  path.moveTo(*points);
976  path.lineTo(points->x()+.005, points->y());
977  drawPath(path);
978  ++points;
979  }
980 
981  if (capStyle == Qt::FlatCap) {
982  setCapStyle(CapButt, d->gc);
983  d->cpen.setCapStyle(capStyle);
984  }
985  return;
986  }
987 
988  static const int BUF_SIZE = 1024;
989  XPoint xPoints[BUF_SIZE];
990  int i = 0, j = 0;
991  while (i < pointCount) {
992  while (i < pointCount && j < BUF_SIZE) {
993  const QPoint &xformed = d->matrix.map(points[i]);
994  int x = xformed.x();
995  int y = xformed.y();
996  if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) {
997  xPoints[j].x = x;
998  xPoints[j].y = y;
999  ++j;
1000  }
1001  ++i;
1002  }
1003  if (j)
1004  XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin);
1005 
1006  j = 0;
1007  }
1008 }
1009 
1010 void QX11PaintEngine::drawPoints(const QPointF *points, int pointCount)
1011 {
1012  Q_ASSERT(points);
1013  Q_ASSERT(pointCount);
1015 
1016  if (!d->has_pen)
1017  return;
1018 
1019  // use the same test here as in drawPath to ensure that we don't use the path fallback
1020  // and end up in XDrawLines for pens with width <= 1
1021  if (d->cpen.widthF() > 1.0f
1022  || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
1023  || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate))
1024  {
1025  Qt::PenCapStyle capStyle = d->cpen.capStyle();
1026  if (capStyle == Qt::FlatCap) {
1027  setCapStyle(CapProjecting, d->gc);
1028  d->cpen.setCapStyle(Qt::SquareCap);
1029  }
1030 
1031  const QPointF *end = points + pointCount;
1032  while (points < end) {
1033  QPainterPath path;
1034  path.moveTo(*points);
1035  path.lineTo(points->x() + 0.005, points->y());
1036  drawPath(path);
1037  ++points;
1038  }
1039  if (capStyle == Qt::FlatCap) {
1040  setCapStyle(CapButt, d->gc);
1041  d->cpen.setCapStyle(capStyle);
1042  }
1043  return;
1044  }
1045 
1046  static const int BUF_SIZE = 1024;
1047  XPoint xPoints[BUF_SIZE];
1048  int i = 0, j = 0;
1049  while (i < pointCount) {
1050  while (i < pointCount && j < BUF_SIZE) {
1051  const QPointF &xformed = d->matrix.map(points[i]);
1052  int x = qFloor(xformed.x());
1053  int y = qFloor(xformed.y());
1054 
1055  if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) {
1056  xPoints[j].x = x;
1057  xPoints[j].y = y;
1058  ++j;
1059  }
1060  ++i;
1061  }
1062  if (j)
1063  XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin);
1064 
1065  j = 0;
1066  }
1067 }
1068 
1069 QPainter::RenderHints QX11PaintEngine::supportedRenderHints() const
1070 {
1071 #if !defined(QT_NO_XRENDER)
1072  if (X11->use_xrender)
1073  return QPainter::Antialiasing;
1074 #endif
1075  return QFlag(0);
1076 }
1077 
1079 {
1081  QPaintEngine::DirtyFlags flags = state.state();
1082 
1083 
1084  if (flags & DirtyOpacity) {
1085  d->opacity = state.opacity();
1086  // Force update pen/brush as to get proper alpha colors propagated
1087  flags |= DirtyPen;
1088  flags |= DirtyBrush;
1089  }
1090 
1091  if (flags & DirtyTransform) updateMatrix(state.transform());
1092  if (flags & DirtyPen) updatePen(state.pen());
1093  if (flags & (DirtyBrush | DirtyBrushOrigin)) updateBrush(state.brush(), state.brushOrigin());
1094  if (flags & DirtyFont) updateFont(state.font());
1095 
1096  if (state.state() & DirtyClipEnabled) {
1097  if (state.isClipEnabled()) {
1098  QPolygonF clip_poly_dev(d->matrix.map(painter()->clipPath().toFillPolygon()));
1099  QPolygonF clipped_poly_dev;
1100  d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
1101  updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip);
1102  } else {
1104  }
1105  }
1106 
1107  if (flags & DirtyClipPath) {
1108  QPolygonF clip_poly_dev(d->matrix.map(state.clipPath().toFillPolygon()));
1109  QPolygonF clipped_poly_dev;
1110  d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
1111  updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon(), state.clipPath().fillRule()),
1112  state.clipOperation());
1113  } else if (flags & DirtyClipRegion) {
1114  extern QPainterPath qt_regionToPath(const QRegion &region);
1115  QPainterPath clip_path = qt_regionToPath(state.clipRegion());
1116  QPolygonF clip_poly_dev(d->matrix.map(clip_path.toFillPolygon()));
1117  QPolygonF clipped_poly_dev;
1118  d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
1119  updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), state.clipOperation());
1120  }
1121  if (flags & DirtyHints) updateRenderHints(state.renderHints());
1122  if (flags & DirtyCompositionMode) {
1123  int function = GXcopy;
1125  switch (state.compositionMode()) {
1127  function = GXor;
1128  break;
1130  function = GXand;
1131  break;
1133  function = GXxor;
1134  break;
1136  function = GXnor;
1137  break;
1139  function = GXnand;
1140  break;
1142  function = GXequiv;
1143  break;
1145  function = GXcopyInverted;
1146  break;
1148  function = GXandReverse;
1149  break;
1151  function = GXandInverted;
1152  break;
1153  default:
1154  function = GXcopy;
1155  }
1156  }
1157 #if !defined(QT_NO_XRENDER)
1158  else {
1159  d->composition_mode =
1161  }
1162 #endif
1163  XSetFunction(X11->display, d->gc, function);
1164  XSetFunction(X11->display, d->gc_brush, function);
1165  }
1166  d->decidePathFallback();
1167  d->decideCoordAdjust();
1168 }
1169 
1170 void QX11PaintEngine::updateRenderHints(QPainter::RenderHints hints)
1171 {
1173  d->render_hints = hints;
1174 
1175 #if !defined(QT_NO_XRENDER)
1176  if (X11->use_xrender && d->picture) {
1177  XRenderPictureAttributes attrs;
1178  attrs.poly_edge = (hints & QPainter::Antialiasing) ? PolyEdgeSmooth : PolyEdgeSharp;
1179  XRenderChangePicture(d->dpy, d->picture, CPPolyEdge, &attrs);
1180  }
1181 #endif
1182 }
1183 
1185 {
1187  d->cpen = pen;
1188  int cp = CapButt;
1189  int jn = JoinMiter;
1190  int ps = pen.style();
1191 
1192  if (d->opacity < 1.0) {
1193  QColor c = d->cpen.color();
1194  c.setAlpha(qRound(c.alpha()*d->opacity));
1195  d->cpen.setColor(c);
1196  }
1197 
1198  d->has_pen = (ps != Qt::NoPen);
1199  d->has_alpha_pen = (pen.color().alpha() != 255);
1200 
1201  switch (pen.capStyle()) {
1202  case Qt::SquareCap:
1203  cp = CapProjecting;
1204  break;
1205  case Qt::RoundCap:
1206  cp = CapRound;
1207  break;
1208  case Qt::FlatCap:
1209  default:
1210  cp = CapButt;
1211  break;
1212  }
1213  switch (pen.joinStyle()) {
1214  case Qt::BevelJoin:
1215  jn = JoinBevel;
1216  break;
1217  case Qt::RoundJoin:
1218  jn = JoinRound;
1219  break;
1220  case Qt::MiterJoin:
1221  default:
1222  jn = JoinMiter;
1223  break;
1224  }
1225 
1226  d->adapted_pen_origin = false;
1227 
1228  char dashes[10]; // custom pen dashes
1229  int dash_len = 0; // length of dash list
1230  int xStyle = LineSolid;
1231 
1232  /*
1233  We are emulating Windows here. Windows treats cpen.width() == 1
1234  (or 0) as a very special case. The fudge variable unifies this
1235  case with the general case.
1236  */
1237  qreal pen_width = pen.widthF();
1238  int scale = qRound(pen_width < 1 ? 1 : pen_width);
1239  int space = (pen_width < 1 && pen_width > 0 ? 1 : (2 * scale));
1240  int dot = 1 * scale;
1241  int dash = 4 * scale;
1242 
1243  d->has_custom_pen = false;
1244 
1245  switch (ps) {
1246  case Qt::NoPen:
1247  case Qt::SolidLine:
1248  xStyle = LineSolid;
1249  break;
1250  case Qt::DashLine:
1251  dashes[0] = dash;
1252  dashes[1] = space;
1253  dash_len = 2;
1254  xStyle = LineOnOffDash;
1255  break;
1256  case Qt::DotLine:
1257  dashes[0] = dot;
1258  dashes[1] = space;
1259  dash_len = 2;
1260  xStyle = LineOnOffDash;
1261  break;
1262  case Qt::DashDotLine:
1263  dashes[0] = dash;
1264  dashes[1] = space;
1265  dashes[2] = dot;
1266  dashes[3] = space;
1267  dash_len = 4;
1268  xStyle = LineOnOffDash;
1269  break;
1270  case Qt::DashDotDotLine:
1271  dashes[0] = dash;
1272  dashes[1] = space;
1273  dashes[2] = dot;
1274  dashes[3] = space;
1275  dashes[4] = dot;
1276  dashes[5] = space;
1277  dash_len = 6;
1278  xStyle = LineOnOffDash;
1279  break;
1280  case Qt::CustomDashLine:
1281  d->has_custom_pen = true;
1282  break;
1283  }
1284 
1285  ulong mask = GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth
1286  | GCCapStyle | GCJoinStyle | GCLineStyle;
1287  XGCValues vals;
1288  vals.graphics_exposures = false;
1289  if (d->pdev_depth == 1) {
1290  vals.foreground = qGray(pen.color().rgb()) > 127 ? 0 : 1;
1291  vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1;
1292  } else if (d->pdev->devType() == QInternal::Pixmap && d->pdev_depth == 32
1293  && X11->use_xrender) {
1294  vals.foreground = pen.color().rgba();
1295  vals.background = QColor(Qt::transparent).rgba();
1296  } else {
1298  vals.foreground = cmap.pixel(pen.color());
1299  vals.background = cmap.pixel(QColor(Qt::transparent));
1300  }
1301 
1302 
1303  vals.line_width = qRound(pen.widthF());
1304  vals.cap_style = cp;
1305  vals.join_style = jn;
1306  vals.line_style = xStyle;
1307 
1308  XChangeGC(d->dpy, d->gc, mask, &vals);
1309 
1310  if (dash_len) { // make dash list
1311  XSetDashes(d->dpy, d->gc, 0, dashes, dash_len);
1312  }
1313 
1314  if (!d->has_clipping) { // if clipping is set the paintevent clip region is merged with the clip region
1315  QRegion sysClip = systemClip();
1316  if (!sysClip.isEmpty())
1317  x11SetClipRegion(d->dpy, d->gc, 0, d->picture, sysClip);
1318  else
1319  x11ClearClipRegion(d->dpy, d->gc, 0, d->picture);
1320  }
1321 }
1322 
1323 void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
1324 {
1326  d->cbrush = brush;
1327  d->bg_origin = origin;
1328  d->adapted_brush_origin = false;
1329 #if !defined(QT_NO_XRENDER)
1330  d->current_brush = 0;
1331 #endif
1332  if (d->opacity < 1.0) {
1333  QColor c = d->cbrush.color();
1334  c.setAlpha(qRound(c.alpha()*d->opacity));
1335  d->cbrush.setColor(c);
1336  }
1337 
1338  int s = FillSolid;
1339  int bs = d->cbrush.style();
1340  d->has_brush = (bs != Qt::NoBrush);
1341  d->has_pattern = bs >= Qt::Dense1Pattern && bs <= Qt::DiagCrossPattern;
1342  d->has_texture = bs == Qt::TexturePattern;
1343  d->has_alpha_brush = brush.color().alpha() != 255;
1344  d->has_alpha_texture = d->has_texture && d->cbrush.texture().hasAlphaChannel();
1345 
1346  ulong mask = GCForeground | GCBackground | GCGraphicsExposures
1347  | GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle;
1348  XGCValues vals;
1349  vals.graphics_exposures = false;
1350  if (d->pdev_depth == 1) {
1351  vals.foreground = qGray(d->cbrush.color().rgb()) > 127 ? 0 : 1;
1352  vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1;
1353  } else if (X11->use_xrender && d->pdev->devType() == QInternal::Pixmap
1354  && d->pdev_depth == 32) {
1355  vals.foreground = d->cbrush.color().rgba();
1356  vals.background = QColor(Qt::transparent).rgba();
1357  } else {
1359  vals.foreground = cmap.pixel(d->cbrush.color());
1360  vals.background = cmap.pixel(QColor(Qt::transparent));
1361 
1362  if (!X11->use_xrender && d->has_brush && !d->has_pattern && !brush.isOpaque()) {
1363  QPixmap pattern = qt_patternForAlpha(brush.color().alpha(), d->scrn);
1364  mask |= GCStipple;
1365  vals.stipple = pattern.handle();
1366  s = FillStippled;
1367  d->adapted_brush_origin = true;
1368  }
1369  }
1370  vals.cap_style = CapButt;
1371  vals.join_style = JoinMiter;
1372  vals.line_style = LineSolid;
1373 
1374  if (d->has_pattern || d->has_texture) {
1375  if (bs == Qt::TexturePattern) {
1376  d->brush_pm = qt_toX11Pixmap(d->cbrush.texture());
1377 #if !defined(QT_NO_XRENDER)
1378  if (X11->use_xrender) {
1379  XRenderPictureAttributes attrs;
1380  attrs.repeat = true;
1381  XRenderChangePicture(d->dpy, d->brush_pm.x11PictureHandle(), CPRepeat, &attrs);
1382  QX11PixmapData *data = static_cast<QX11PixmapData*>(d->brush_pm.data.data());
1383  if (data->mask_picture)
1384  XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs);
1385  }
1386 #endif
1387  } else {
1388  d->brush_pm = qt_toX11Pixmap(qt_pixmapForBrush(bs, true));
1389  }
1390  d->brush_pm.x11SetScreen(d->scrn);
1391  if (d->brush_pm.depth() == 1) {
1392  mask |= GCStipple;
1393  vals.stipple = d->brush_pm.handle();
1394  s = FillStippled;
1395 #if !defined(QT_NO_XRENDER)
1396  if (X11->use_xrender) {
1397  d->bitmap_texture = QPixmap(d->brush_pm.size());
1398  d->bitmap_texture.fill(Qt::transparent);
1399  d->bitmap_texture = qt_toX11Pixmap(d->bitmap_texture);
1400  d->bitmap_texture.x11SetScreen(d->scrn);
1401 
1402  ::Picture src = X11->getSolidFill(d->scrn, d->cbrush.color());
1403  XRenderComposite(d->dpy, PictOpSrc, src, d->brush_pm.x11PictureHandle(),
1404  d->bitmap_texture.x11PictureHandle(),
1405  0, 0, d->brush_pm.width(), d->brush_pm.height(),
1406  0, 0, d->brush_pm.width(), d->brush_pm.height());
1407 
1408  XRenderPictureAttributes attrs;
1409  attrs.repeat = true;
1410  XRenderChangePicture(d->dpy, d->bitmap_texture.x11PictureHandle(), CPRepeat, &attrs);
1411 
1412  d->current_brush = d->bitmap_texture.x11PictureHandle();
1413  }
1414 #endif
1415  } else {
1416  mask |= GCTile;
1417 #ifndef QT_NO_XRENDER
1418  if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) {
1419  d->brush_pm.detach();
1420  QX11PixmapData *brushData = static_cast<QX11PixmapData*>(d->brush_pm.data.data());
1421  brushData->convertToARGB32();
1422  }
1423 #endif
1424  vals.tile = (d->brush_pm.depth() == d->pdev_depth
1425  ? d->brush_pm.handle()
1426  : static_cast<QX11PixmapData*>(d->brush_pm.data.data())->x11ConvertToDefaultDepth());
1427  s = FillTiled;
1428 #if !defined(QT_NO_XRENDER)
1429  d->current_brush = d->cbrush.texture().x11PictureHandle();
1430 #endif
1431  }
1432 
1433  mask |= GCTileStipXOrigin | GCTileStipYOrigin;
1434  vals.ts_x_origin = qRound(origin.x());
1435  vals.ts_y_origin = qRound(origin.y());
1436  }
1437 #if !defined(QT_NO_XRENDER)
1438  else if (d->has_alpha_brush) {
1439  d->current_brush = X11->getSolidFill(d->scrn, d->cbrush.color());
1440  }
1441 #endif
1442 
1443  vals.fill_style = s;
1444  XChangeGC(d->dpy, d->gc_brush, mask, &vals);
1445  if (!d->has_clipping) {
1446  QRegion sysClip = systemClip();
1447  if (!sysClip.isEmpty())
1448  x11SetClipRegion(d->dpy, d->gc_brush, 0, d->picture, sysClip);
1449  else
1450  x11ClearClipRegion(d->dpy, d->gc_brush, 0, d->picture);
1451  }
1452 }
1453 
1455 {
1456  QRect aligned = rect.toAlignedRect();
1457  if (aligned == rect)
1458  drawEllipse(aligned);
1459  else
1461 }
1462 
1464 {
1465  if (rect.isEmpty()) {
1466  drawRects(&rect, 1);
1467  return;
1468  }
1469 
1471  QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1);
1472  QRect r(rect);
1473  if (d->txop < QTransform::TxRotate) {
1474  r = d->matrix.mapRect(rect);
1475  } else if (d->txop == QTransform::TxRotate && rect.width() == rect.height()) {
1476  QPainterPath path;
1477  path.addEllipse(rect);
1478  r = d->matrix.map(path).boundingRect().toRect();
1479  }
1480 
1481  if (d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->render_hints & QPainter::Antialiasing)
1482  || d->has_alpha_texture || devclip.intersected(r) != r
1483  || (d->has_complex_xform
1484  && !(d->has_non_scaling_xform && rect.width() == rect.height())))
1485  {
1486  QPainterPath path;
1487  path.addEllipse(rect);
1488  drawPath(path);
1489  return;
1490  }
1491 
1492  int x = r.x();
1493  int y = r.y();
1494  int w = r.width();
1495  int h = r.height();
1496  if (w < 1 || h < 1)
1497  return;
1498  if (w == 1 && h == 1) {
1499  XDrawPoint(d->dpy, d->hd, d->has_pen ? d->gc : d->gc_brush, x, y);
1500  return;
1501  }
1502  d->setupAdaptedOrigin(rect.topLeft());
1503  if (d->has_brush) { // draw filled ellipse
1504  XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64);
1505  if (!d->has_pen) // make smoother outline
1506  XDrawArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64);
1507  }
1508  if (d->has_pen) // draw outline
1509  XDrawArc(d->dpy, d->hd, d->gc, x, y, w, h, 0, 360*64);
1510  d->resetAdaptedOrigin();
1511 }
1512 
1513 
1514 
1515 void QX11PaintEnginePrivate::fillPolygon_translated(const QPointF *polygonPoints, int pointCount,
1518 {
1519 
1520  QVarLengthArray<QPointF> translated_points(pointCount);
1521  QPointF offset(matrix.dx(), matrix.dy());
1522 
1523  qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0;
1524  if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing))
1526 
1527  for (int i = 0; i < pointCount; ++i) {
1528  translated_points[i] = polygonPoints[i] + offset;
1529 
1530  translated_points[i].rx() = qRound(translated_points[i].x()) + offs;
1531  translated_points[i].ry() = qRound(translated_points[i].y()) + offs;
1532  }
1533 
1534  fillPolygon_dev(translated_points.data(), pointCount, gcMode, mode);
1535 }
1536 
1537 #ifndef QT_NO_XRENDER
1539  int op,
1540  Picture src,
1541  Picture dst,
1542  _Xconst XRenderPictFormat *maskFormat,
1543  int xSrc,
1544  int ySrc,
1545  const XTrapezoid *traps, int size)
1546 {
1547  const int MAX_TRAPS = 50000;
1548  while (size) {
1549  int to_draw = size;
1550  if (to_draw > MAX_TRAPS)
1551  to_draw = MAX_TRAPS;
1552  XRenderCompositeTrapezoids(dpy, op, src, dst,
1553  maskFormat,
1554  xSrc, ySrc,
1555  traps, to_draw);
1556  size -= to_draw;
1557  traps += to_draw;
1558  }
1559 }
1560 #endif
1561 
1562 void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
1565 {
1567 
1568  int clippedCount = 0;
1569  qt_float_point *clippedPoints = 0;
1570 
1571 #ifndef QT_NO_XRENDER
1572  //can change if we switch to pen if gcMode != BrushGC
1573  bool has_fill_texture = has_texture;
1574  bool has_fill_pattern = has_pattern;
1575  ::Picture src;
1576 #endif
1577  QBrush fill;
1578  GC fill_gc;
1579  if (gcMode == BrushGC) {
1580  fill = cbrush;
1581  fill_gc = gc_brush;
1582 #ifndef QT_NO_XRENDER
1583  if (current_brush)
1584  src = current_brush;
1585  else
1586  src = X11->getSolidFill(scrn, fill.color());
1587 #endif
1588  } else {
1589  fill = QBrush(cpen.brush());
1590  fill_gc = gc;
1591 #ifndef QT_NO_XRENDER
1592  //we use the pens brush
1593  has_fill_texture = (fill.style() == Qt::TexturePattern);
1594  has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern);
1595  if (has_fill_texture)
1596  src = fill.texture().x11PictureHandle();
1597  else if (has_fill_pattern)
1598  src = getPatternFill(scrn, fill);
1599  else
1600  src = X11->getSolidFill(scrn, fill.color());
1601 #endif
1602  }
1603 
1604  polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount,
1605  &clippedPoints, &clippedCount);
1606 
1607 #ifndef QT_NO_XRENDER
1608  bool solid_fill = fill.color().alpha() == 255;
1609  if (has_fill_texture && fill.texture().depth() == 1 && solid_fill) {
1610  has_fill_texture = false;
1611  has_fill_pattern = true;
1612  }
1613 
1614  bool antialias = render_hints & QPainter::Antialiasing;
1615 
1616  if (X11->use_xrender
1617  && picture
1618  && !has_fill_pattern
1619  && (clippedCount > 0)
1620  && (fill.style() != Qt::NoBrush)
1621  && ((has_fill_texture && fill.texture().hasAlpha()) || antialias || !solid_fill || has_alpha_pen != has_alpha_brush))
1622  {
1623  tessellator->tessellate((QPointF *)clippedPoints, clippedCount,
1624  mode == QPaintEngine::WindingMode);
1625  if (tessellator->size > 0) {
1626  XRenderPictureAttributes attrs;
1627  attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp;
1628  XRenderChangePicture(dpy, picture, CPPolyEdge, &attrs);
1629  int x_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.x) - bg_origin.x());
1630  int y_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.y) - bg_origin.y());
1631  qt_XRenderCompositeTrapezoids(dpy, composition_mode, src, picture,
1632  antialias
1633  ? XRenderFindStandardFormat(dpy, PictStandardA8)
1634  : XRenderFindStandardFormat(dpy, PictStandardA1),
1635  x_offset, y_offset,
1636  tessellator->traps, tessellator->size);
1637  tessellator->done();
1638  }
1639  } else
1640 #endif
1641  if (fill.style() != Qt::NoBrush) {
1642  if (clippedCount > 200000) {
1643  QPolygon poly;
1644  for (int i = 0; i < clippedCount; ++i)
1645  poly << QPoint(qFloor(clippedPoints[i].x), qFloor(clippedPoints[i].y));
1646 
1647  const QRect bounds = poly.boundingRect();
1648  const QRect aligned = bounds
1649  & QRect(QPoint(), QSize(pdev->width(), pdev->height()));
1650 
1652  img.fill(0);
1653 
1654  QPainter painter(&img);
1655  painter.translate(-aligned.x(), -aligned.y());
1656  painter.setPen(Qt::NoPen);
1657  painter.setBrush(fill);
1658  if (gcMode == BrushGC)
1659  painter.setBrushOrigin(q->painter()->brushOrigin());
1660  painter.drawPolygon(poly);
1661  painter.end();
1662 
1663  q->drawImage(aligned, img, img.rect(), Qt::AutoColor);
1664  } else if (clippedCount > 0) {
1665  QVarLengthArray<XPoint> xpoints(clippedCount);
1666  for (int i = 0; i < clippedCount; ++i) {
1667  xpoints[i].x = qFloor(clippedPoints[i].x);
1668  xpoints[i].y = qFloor(clippedPoints[i].y);
1669  }
1670  if (mode == QPaintEngine::WindingMode)
1671  XSetFillRule(dpy, fill_gc, WindingRule);
1672  setupAdaptedOrigin(QPoint(xpoints[0].x, xpoints[0].y));
1673  XFillPolygon(dpy, hd, fill_gc,
1674  xpoints.data(), clippedCount,
1675  mode == QPaintEngine::ConvexMode ? Convex : Complex, CoordModeOrigin);
1676  resetAdaptedOrigin();
1677  if (mode == QPaintEngine::WindingMode)
1678  XSetFillRule(dpy, fill_gc, EvenOddRule);
1679  }
1680  }
1681 }
1682 
1683 void QX11PaintEnginePrivate::strokePolygon_translated(const QPointF *polygonPoints, int pointCount, bool close)
1684 {
1685  QVarLengthArray<QPointF> translated_points(pointCount);
1686  QPointF offset(matrix.dx(), matrix.dy());
1687  for (int i = 0; i < pointCount; ++i)
1688  translated_points[i] = polygonPoints[i] + offset;
1689  strokePolygon_dev(translated_points.data(), pointCount, close);
1690 }
1691 
1692 void QX11PaintEnginePrivate::strokePolygon_dev(const QPointF *polygonPoints, int pointCount, bool close)
1693 {
1694  int clippedCount = 0;
1695  qt_float_point *clippedPoints = 0;
1696  polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount,
1697  &clippedPoints, &clippedCount, close);
1698 
1699  if (clippedCount > 0) {
1700  QVarLengthArray<XPoint> xpoints(clippedCount);
1701  for (int i = 0; i < clippedCount; ++i) {
1702  xpoints[i].x = qRound(clippedPoints[i].x + aliasedCoordinateDelta);
1703  xpoints[i].y = qRound(clippedPoints[i].y + aliasedCoordinateDelta);
1704  }
1705  uint numberPoints = qMin(clippedCount, xlibMaxLinePoints);
1706  XPoint *pts = xpoints.data();
1707  XDrawLines(dpy, hd, gc, pts, numberPoints, CoordModeOrigin);
1708  pts += numberPoints;
1709  clippedCount -= numberPoints;
1710  numberPoints = qMin(clippedCount, xlibMaxLinePoints-1);
1711  while (clippedCount) {
1712  XDrawLines(dpy, hd, gc, pts-1, numberPoints+1, CoordModeOrigin);
1713  pts += numberPoints;
1714  clippedCount -= numberPoints;
1715  numberPoints = qMin(clippedCount, xlibMaxLinePoints-1);
1716  }
1717  }
1718 }
1719 
1720 void QX11PaintEngine::drawPolygon(const QPointF *polygonPoints, int pointCount, PolygonDrawMode mode)
1721 {
1723  if (d->use_path_fallback) {
1724  QPainterPath path(polygonPoints[0]);
1725  for (int i = 1; i < pointCount; ++i)
1726  path.lineTo(polygonPoints[i]);
1727  if (mode == PolylineMode) {
1728  QBrush oldBrush = d->cbrush;
1729  d->cbrush = QBrush(Qt::NoBrush);
1731  drawPath(path);
1732  d->cbrush = oldBrush;
1733  } else {
1735  path.closeSubpath();
1736  drawPath(path);
1737  }
1738  return;
1739  }
1740  if (mode != PolylineMode && d->has_brush)
1741  d->fillPolygon_translated(polygonPoints, pointCount, QX11PaintEnginePrivate::BrushGC, mode);
1742 
1743  if (d->has_pen)
1744  d->strokePolygon_translated(polygonPoints, pointCount, mode != PolylineMode);
1745 }
1746 
1747 
1749 {
1750  qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0;
1751 
1752  QPainterPath clippedPath;
1753  QPainterPath clipPath;
1754  clipPath.addRect(polygonClipper.boundingRect());
1755 
1756  if (transform)
1757  clippedPath = (path*matrix).intersected(clipPath);
1758  else
1759  clippedPath = path.intersected(clipPath);
1760 
1761  QList<QPolygonF> polys = clippedPath.toFillPolygons();
1762  for (int i = 0; i < polys.size(); ++i) {
1763  QVarLengthArray<QPointF> translated_points(polys.at(i).size());
1764 
1765  for (int j = 0; j < polys.at(i).size(); ++j) {
1766  translated_points[j] = polys.at(i).at(j);
1767  if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing)) {
1768  translated_points[j].rx() = qRound(translated_points[j].rx() + aliasedCoordinateDelta) + offs;
1769  translated_points[j].ry() = qRound(translated_points[j].ry() + aliasedCoordinateDelta) + offs;
1770  }
1771  }
1772 
1773  fillPolygon_dev(translated_points.data(), polys.at(i).size(), gc_mode,
1775  }
1776 }
1777 
1779 {
1781  if (path.isEmpty())
1782  return;
1783 
1784  if (d->has_brush)
1785  d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true);
1786  if (d->has_pen
1787  && ((X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
1788  || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate
1789  && !d->has_non_scaling_xform)
1790  || (d->cpen.style() == Qt::CustomDashLine))) {
1791  QPainterPathStroker stroker;
1792  if (d->cpen.style() == Qt::CustomDashLine) {
1793  stroker.setDashPattern(d->cpen.dashPattern());
1794  stroker.setDashOffset(d->cpen.dashOffset());
1795  } else {
1796  stroker.setDashPattern(d->cpen.style());
1797  }
1798  stroker.setCapStyle(d->cpen.capStyle());
1799  stroker.setJoinStyle(d->cpen.joinStyle());
1800  QPainterPath stroke;
1801  qreal width = d->cpen.widthF();
1802  QPolygonF poly;
1803  QRectF deviceRect(0, 0, d->pdev->width(), d->pdev->height());
1804  // necessary to get aliased alphablended primitives to be drawn correctly
1805  if (d->cpen.isCosmetic() || d->has_scaling_xform) {
1806  if (d->cpen.isCosmetic())
1807  stroker.setWidth(width == 0 ? 1 : width);
1808  else
1809  stroker.setWidth(width * d->xform_scale);
1810  stroker.d_ptr->stroker.setClipRect(deviceRect);
1811  stroke = stroker.createStroke(path * d->matrix);
1812  if (stroke.isEmpty())
1813  return;
1814  stroke.setFillRule(Qt::WindingFill);
1815  d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, false);
1816  } else {
1817  stroker.setWidth(width);
1818  stroker.d_ptr->stroker.setClipRect(d->matrix.inverted().mapRect(deviceRect));
1819  stroke = stroker.createStroke(path);
1820  if (stroke.isEmpty())
1821  return;
1822  stroke.setFillRule(Qt::WindingFill);
1823  d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, true);
1824  }
1825  } else if (d->has_pen) {
1826  // if we have a cosmetic pen - use XDrawLine() for speed
1827  QList<QPolygonF> polys = path.toSubpathPolygons(d->matrix);
1828  for (int i = 0; i < polys.size(); ++i)
1829  d->strokePolygon_dev(polys.at(i).data(), polys.at(i).size(), false);
1830  }
1831 }
1832 
1833 Q_GUI_EXPORT void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image,
1834  Drawable hd, GC gc, Display *dpy, Visual *visual, int depth)
1835 {
1836  Q_ASSERT(image.format() == QImage::Format_RGB32);
1837  Q_ASSERT(image.depth() == 32);
1838 
1839  XImage *xi;
1840  // Note: this code assumes either RGB or BGR, 8 bpc server layouts
1841  const uint red_mask = (uint) visual->red_mask;
1842  bool bgr_layout = (red_mask == 0xff);
1843 
1844  const int w = rect.width();
1845  const int h = rect.height();
1846 
1847  QImage im;
1848  int image_byte_order = ImageByteOrder(X11->display);
1849  if ((QSysInfo::ByteOrder == QSysInfo::BigEndian && ((image_byte_order == LSBFirst) || bgr_layout))
1850  || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)
1851  || (image_byte_order == LSBFirst && bgr_layout))
1852  {
1853  im = image.copy(rect);
1854  const int iw = im.bytesPerLine() / 4;
1855  uint *data = (uint *)im.bits();
1856  for (int i=0; i < h; i++) {
1857  uint *p = data;
1858  uint *end = p + w;
1859  if (bgr_layout && image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
1860  while (p < end) {
1861  *p = ((*p << 8) & 0xffffff00) | ((*p >> 24) & 0x000000ff);
1862  p++;
1863  }
1864  } else if ((image_byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
1865  || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
1866  while (p < end) {
1867  *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
1868  | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
1869  p++;
1870  }
1871  } else if ((image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
1872  || (image_byte_order == LSBFirst && bgr_layout))
1873  {
1874  while (p < end) {
1875  *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
1876  | ((*p ) & 0xff00ff00);
1877  p++;
1878  }
1879  }
1880  data += iw;
1881  }
1882  xi = XCreateImage(dpy, visual, depth, ZPixmap,
1883  0, (char *) im.bits(), w, h, 32, im.bytesPerLine());
1884  } else {
1885  xi = XCreateImage(dpy, visual, depth, ZPixmap,
1886  0, (char *) image.scanLine(rect.y())+rect.x()*sizeof(uint), w, h, 32, image.bytesPerLine());
1887  }
1888  XPutImage(dpy, hd, gc, xi, 0, 0, pos.x(), pos.y(), w, h);
1889  xi->data = 0; // QImage owns these bits
1890  XDestroyImage(xi);
1891 }
1892 
1893 void QX11PaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags)
1894 {
1896 
1897  if (image.format() == QImage::Format_RGB32
1898  && d->pdev_depth >= 24 && image.depth() == 32
1899  && r.size() == sr.size())
1900  {
1901  int sx = qRound(sr.x());
1902  int sy = qRound(sr.y());
1903  int x = qRound(r.x());
1904  int y = qRound(r.y());
1905  int w = qRound(r.width());
1906  int h = qRound(r.height());
1907 
1908  qt_x11_drawImage(QRect(sx, sy, w, h), QPoint(x, y), image, d->hd, d->gc, d->dpy,
1909  (Visual *)d->xinfo->visual(), d->pdev_depth);
1910  } else {
1911  QPaintEngine::drawImage(r, image, sr, flags);
1912  }
1913 }
1914 
1915 void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRectF &_sr)
1916 {
1918  QRectF sr = _sr;
1919  int x = qRound(r.x());
1920  int y = qRound(r.y());
1921  int sx = qRound(sr.x());
1922  int sy = qRound(sr.y());
1923  int sw = qRound(sr.width());
1924  int sh = qRound(sr.height());
1925 
1926  QPixmap pixmap = qt_toX11Pixmap(px);
1927  if(pixmap.isNull())
1928  return;
1929 
1930  if ((d->xinfo && d->xinfo->screen() != pixmap.x11Info().screen())
1931  || (pixmap.x11Info().screen() != DefaultScreen(X11->display))) {
1932  QPixmap* p = const_cast<QPixmap *>(&pixmap);
1933  p->x11SetScreen(d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display));
1934  }
1935 
1936  QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen());
1937 
1938 #ifndef QT_NO_XRENDER
1939  ::Picture src_pict = static_cast<QX11PixmapData*>(pixmap.data.data())->picture;
1940  if (src_pict && d->picture) {
1941  const int pDepth = pixmap.depth();
1942  if (pDepth == 1 && (d->has_alpha_pen)) {
1943  qt_render_bitmap(d->dpy, d->scrn, src_pict, d->picture,
1944  sx, sy, x, y, sw, sh, d->cpen);
1945  return;
1946  } else if (pDepth != 1 && (pDepth == 32 || pDepth != d->pdev_depth)) {
1947  XRenderComposite(d->dpy, d->composition_mode,
1948  src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
1949  return;
1950  }
1951  }
1952 #endif
1953 
1954  bool mono_src = pixmap.depth() == 1;
1955  bool mono_dst = d->pdev_depth == 1;
1956  bool restore_clip = false;
1957 
1958  if (static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask) { // pixmap has a mask
1959  QBitmap comb(sw, sh);
1960  GC cgc = XCreateGC(d->dpy, comb.handle(), 0, 0);
1961  XSetForeground(d->dpy, cgc, 0);
1962  XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh);
1963  XSetBackground(d->dpy, cgc, 0);
1964  XSetForeground(d->dpy, cgc, 1);
1965  if (!d->crgn.isEmpty()) {
1966  int num;
1967  XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num);
1968  XSetClipRectangles(d->dpy, cgc, -x, -y, rects, num, Unsorted);
1969  } else if (d->has_clipping) {
1970  XSetClipRectangles(d->dpy, cgc, 0, 0, 0, 0, Unsorted);
1971  }
1972  XSetFillStyle(d->dpy, cgc, FillOpaqueStippled);
1973  XSetTSOrigin(d->dpy, cgc, -sx, -sy);
1974  XSetStipple(d->dpy, cgc,
1975  static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask);
1976  XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh);
1977  XFreeGC(d->dpy, cgc);
1978 
1979  XSetClipOrigin(d->dpy, d->gc, x, y);
1980  XSetClipMask(d->dpy, d->gc, comb.handle());
1981  restore_clip = true;
1982  }
1983 
1984  if (mono_src) {
1985  if (!d->crgn.isEmpty()) {
1986  Pixmap comb = XCreatePixmap(d->dpy, d->hd, sw, sh, 1);
1987  GC cgc = XCreateGC(d->dpy, comb, 0, 0);
1988  XSetForeground(d->dpy, cgc, 0);
1989  XFillRectangle(d->dpy, comb, cgc, 0, 0, sw, sh);
1990  int num;
1991  XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num);
1992  XSetClipRectangles(d->dpy, cgc, -x, -y, rects, num, Unsorted);
1993  XCopyArea(d->dpy, pixmap.handle(), comb, cgc, sx, sy, sw, sh, 0, 0);
1994  XFreeGC(d->dpy, cgc);
1995 
1996  XSetClipMask(d->dpy, d->gc, comb);
1997  XSetClipOrigin(d->dpy, d->gc, x, y);
1998  XFreePixmap(d->dpy, comb);
1999  } else {
2000  XSetClipMask(d->dpy, d->gc, pixmap.handle());
2001  XSetClipOrigin(d->dpy, d->gc, x - sx, y - sy);
2002  }
2003 
2004  if (mono_dst) {
2005  XSetForeground(d->dpy, d->gc, qGray(d->cpen.color().rgb()) > 127 ? 0 : 1);
2006  } else {
2008  XSetForeground(d->dpy, d->gc, cmap.pixel(d->cpen.color()));
2009  }
2010  XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh);
2011  restore_clip = true;
2012  } else if (mono_dst && !mono_src) {
2013  QBitmap bitmap(pixmap);
2014  XCopyArea(d->dpy, bitmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y);
2015  } else {
2016  XCopyArea(d->dpy, pixmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y);
2017  }
2018 
2019  if (d->pdev->devType() == QInternal::Pixmap) {
2020  const QPixmap *px = static_cast<const QPixmap*>(d->pdev);
2021  Pixmap src_mask = static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask;
2022  Pixmap dst_mask = static_cast<QX11PixmapData*>(px->data.data())->x11_mask;
2023  if (dst_mask) {
2024  GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0);
2025  if (src_mask) { // copy src mask into dst mask
2026  XCopyArea(d->dpy, src_mask, dst_mask, cgc, sx, sy, sw, sh, x, y);
2027  } else { // no src mask, but make sure the area copied is opaque in dest
2028  XSetBackground(d->dpy, cgc, 0);
2029  XSetForeground(d->dpy, cgc, 1);
2030  XFillRectangle(d->dpy, dst_mask, cgc, x, y, sw, sh);
2031  }
2032  XFreeGC(d->dpy, cgc);
2033  }
2034  }
2035 
2036  if (restore_clip) {
2037  XSetClipOrigin(d->dpy, d->gc, 0, 0);
2038  int num;
2039  XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num);
2040  if (num == 0)
2041  XSetClipMask(d->dpy, d->gc, XNone);
2042  else
2043  XSetClipRectangles(d->dpy, d->gc, 0, 0, rects, num, Unsorted);
2044  }
2045 }
2046 
2048 {
2050  d->txop = mtx.type();
2051  d->matrix = mtx;
2052 
2053  d->has_complex_xform = (d->txop > QTransform::TxTranslate);
2054 
2055  extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
2056  bool scaling = qt_scaleForTransform(d->matrix, &d->xform_scale);
2057  d->has_scaling_xform = scaling && d->xform_scale != 1.0;
2058  d->has_non_scaling_xform = scaling && d->xform_scale == 1.0;
2059 }
2060 
2061 /*
2062  NB! the clip region is expected to be in dev coordinates
2063 */
2065 {
2067  QRegion sysClip = systemClip();
2068  if (op == Qt::NoClip) {
2069  d->has_clipping = false;
2070  d->crgn = sysClip;
2071  if (!sysClip.isEmpty()) {
2072  x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, sysClip);
2073  } else {
2074  x11ClearClipRegion(d->dpy, d->gc, d->gc_brush, d->picture);
2075  }
2076  return;
2077  }
2078 
2079  switch (op) {
2080  case Qt::IntersectClip:
2081  if (d->has_clipping) {
2082  d->crgn &= clipRegion;
2083  break;
2084  }
2085  // fall through
2086  case Qt::ReplaceClip:
2087  if (!sysClip.isEmpty())
2088  d->crgn = clipRegion.intersected(sysClip);
2089  else
2090  d->crgn = clipRegion;
2091  break;
2092  case Qt::UniteClip:
2093  d->crgn |= clipRegion;
2094  if (!sysClip.isEmpty())
2095  d->crgn = d->crgn.intersected(sysClip);
2096  break;
2097  default:
2098  break;
2099  }
2100  d->has_clipping = true;
2101  x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, d->crgn);
2102 }
2103 
2105 {
2106 }
2107 
2109 {
2110  Q_D(const QX11PaintEngine);
2111  Q_ASSERT(isActive());
2112  Q_ASSERT(d->hd);
2113  return d->hd;
2114 }
2115 
2116 extern void qt_draw_tile(QPaintEngine *, qreal, qreal, qreal, qreal, const QPixmap &,
2117  qreal, qreal);
2118 
2119 void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &p)
2120 {
2121  int x = qRound(r.x());
2122  int y = qRound(r.y());
2123  int w = qRound(r.width());
2124  int h = qRound(r.height());
2125  int sx = qRound(p.x());
2126  int sy = qRound(p.y());
2127 
2128  bool mono_src = pixmap.depth() == 1;
2130 
2131  if ((d->xinfo && d->xinfo->screen() != pixmap.x11Info().screen())
2132  || (pixmap.x11Info().screen() != DefaultScreen(X11->display))) {
2133  QPixmap* p = const_cast<QPixmap *>(&pixmap);
2134  p->x11SetScreen(d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display));
2135  }
2136 
2137  QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen());
2138 
2139 #ifndef QT_NO_XRENDER
2140  if (X11->use_xrender && d->picture && pixmap.x11PictureHandle()) {
2141 #if 0
2142  // ### Qt 5: enable this
2143  XRenderPictureAttributes attrs;
2144  attrs.repeat = true;
2145  XRenderChangePicture(d->dpy, pixmap.x11PictureHandle(), CPRepeat, &attrs);
2146 
2147  if (mono_src) {
2148  qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture,
2149  sx, sy, x, y, w, h, d->cpen);
2150  } else {
2151  XRenderComposite(d->dpy, d->composition_mode,
2152  pixmap.x11PictureHandle(), XNone, d->picture,
2153  sx, sy, 0, 0, x, y, w, h);
2154  }
2155 #else
2156  const int numTiles = (w / pixmap.width()) * (h / pixmap.height());
2157  if (numTiles < 100) {
2158  // this is essentially qt_draw_tile(), inlined for
2159  // the XRenderComposite call
2160  int yPos, xPos, drawH, drawW, yOff, xOff;
2161  yPos = y;
2162  yOff = sy;
2163  while(yPos < y + h) {
2164  drawH = pixmap.height() - yOff; // Cropping first row
2165  if (yPos + drawH > y + h) // Cropping last row
2166  drawH = y + h - yPos;
2167  xPos = x;
2168  xOff = sx;
2169  while(xPos < x + w) {
2170  drawW = pixmap.width() - xOff; // Cropping first column
2171  if (xPos + drawW > x + w) // Cropping last column
2172  drawW = x + w - xPos;
2173  if (mono_src) {
2174  qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture,
2175  xOff, yOff, xPos, yPos, drawW, drawH, d->cpen);
2176  } else {
2177  XRenderComposite(d->dpy, d->composition_mode,
2178  pixmap.x11PictureHandle(), XNone, d->picture,
2179  xOff, yOff, 0, 0, xPos, yPos, drawW, drawH);
2180  }
2181  xPos += drawW;
2182  xOff = 0;
2183  }
2184  yPos += drawH;
2185  yOff = 0;
2186  }
2187  } else {
2188  w = qMin(w, d->pdev->width() - x);
2189  h = qMin(h, d->pdev->height() - y);
2190  if (w <= 0 || h <= 0)
2191  return;
2192 
2193  const int pw = w + sx;
2194  const int ph = h + sy;
2195  QPixmap pm(pw, ph);
2196  if (pixmap.hasAlpha() || mono_src)
2197  pm.fill(Qt::transparent);
2198 
2199  const int mode = pixmap.hasAlpha() ? PictOpOver : PictOpSrc;
2200  const ::Picture pmPicture = pm.x11PictureHandle();
2201 
2202  // first tile
2203  XRenderComposite(d->dpy, mode,
2204  pixmap.x11PictureHandle(), XNone, pmPicture,
2205  0, 0, 0, 0, 0, 0, qMin(pw, pixmap.width()), qMin(ph, pixmap.height()));
2206 
2207  // first row of tiles
2208  int xPos = pixmap.width();
2209  const int sh = qMin(ph, pixmap.height());
2210  while (xPos < pw) {
2211  const int sw = qMin(xPos, pw - xPos);
2212  XRenderComposite(d->dpy, mode,
2213  pmPicture, XNone, pmPicture,
2214  0, 0, 0, 0, xPos, 0, sw, sh);
2215  xPos *= 2;
2216  }
2217 
2218  // remaining rows
2219  int yPos = pixmap.height();
2220  const int sw = pw;
2221  while (yPos < ph) {
2222  const int sh = qMin(yPos, ph - yPos);
2223  XRenderComposite(d->dpy, mode,
2224  pmPicture, XNone, pmPicture,
2225  0, 0, 0, 0, 0, yPos, sw, sh);
2226  yPos *= 2;
2227  }
2228 
2229  // composite
2230  if (mono_src)
2231  qt_render_bitmap(d->dpy, d->scrn, pmPicture, d->picture,
2232  sx, sy, x, y, w, h, d->cpen);
2233  else
2234  XRenderComposite(d->dpy, d->composition_mode,
2235  pmPicture, XNone, d->picture,
2236  sx, sy, 0, 0, x, y, w, h);
2237  }
2238 #endif
2239  } else
2240 #endif // !QT_NO_XRENDER
2241  if (pixmap.depth() > 1 && !static_cast<QX11PixmapData*>(pixmap.data.data())->x11_mask) {
2242  XSetTile(d->dpy, d->gc, pixmap.handle());
2243  XSetFillStyle(d->dpy, d->gc, FillTiled);
2244  XSetTSOrigin(d->dpy, d->gc, x-sx, y-sy);
2245  XFillRectangle(d->dpy, d->hd, d->gc, x, y, w, h);
2246  XSetTSOrigin(d->dpy, d->gc, 0, 0);
2247  XSetFillStyle(d->dpy, d->gc, FillSolid);
2248  } else {
2249  qt_draw_tile(this, x, y, w, h, pixmap, sx, sy);
2250  }
2251 }
2252 
2253 void QX11PaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
2254 {
2255  const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
2256 
2257  switch(ti.fontEngine->type()) {
2259  case QFontEngine::Box:
2260  d_func()->drawBoxTextItem(p, ti);
2261  break;
2262  case QFontEngine::XLFD:
2263  drawXLFD(p, ti);
2264  break;
2265 #ifndef QT_NO_FONTCONFIG
2266  case QFontEngine::Freetype:
2267  drawFreetype(p, ti);
2268  break;
2269 #endif
2270  default:
2271  Q_ASSERT(false);
2272  }
2273 }
2274 
2276 {
2278 
2279  if (d->txop > QTransform::TxTranslate) {
2280  // XServer or font don't support server side transformations, need to do it by hand
2282  return;
2283  }
2284 
2285  if (!ti.glyphs.numGlyphs)
2286  return;
2287 
2289  QVarLengthArray<glyph_t> glyphs;
2290  QTransform matrix = d->matrix;
2291  matrix.translate(p.x(), p.y());
2292  ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
2293  if (glyphs.size() == 0)
2294  return;
2295 
2296  QFontEngineXLFD *xlfd = static_cast<QFontEngineXLFD *>(ti.fontEngine);
2297  Qt::HANDLE font_id = xlfd->fontStruct()->fid;
2298 
2299  XSetFont(d->dpy, d->gc, font_id);
2300 
2302  for (int i = 0; i < glyphs.size(); i++) {
2303  int xp = qRound(positions[i].x + offs);
2304  int yp = qRound(positions[i].y + offs);
2305  if (xp < SHRT_MAX && xp > SHRT_MIN && yp > SHRT_MIN && yp < SHRT_MAX) {
2306  XChar2b ch;
2307  ch.byte1 = glyphs[i] >> 8;
2308  ch.byte2 = glyphs[i] & 0xff;
2309  XDrawString16(d->dpy, d->hd, d->gc, xp, yp, &ch, 1);
2310  }
2311  }
2312 }
2313 
2314 #ifndef QT_NO_FONTCONFIG
2317  const QFontEngineFT *ft)
2318 {
2319  QPainterPath path;
2321  ft->lockFace();
2322  int i = 0;
2323  while (i < glyphs.size()) {
2324  QFontEngineFT::Glyph *glyph = ft->loadGlyph(glyphs[i], 0, QFontEngineFT::Format_Mono);
2325  // #### fix case where we don't get a glyph
2326  if (!glyph)
2327  break;
2328 
2330  int n = 0;
2331  int h = glyph->height;
2332  int xp = qRound(positions[i].x);
2333  int yp = qRound(positions[i].y);
2334 
2335  xp += glyph->x;
2336  yp += -glyph->y + glyph->height;
2337  int pitch = ((glyph->width + 31) & ~31) >> 3;
2338 
2339  uchar *src = glyph->data;
2340  while (h--) {
2341  for (int x = 0; x < glyph->width; ++x) {
2342  bool set = src[x >> 3] & (0x80 >> (x & 7));
2343  if (set) {
2344  QRect r(xp + x, yp - h, 1, 1);
2345  while (x+1 < glyph->width && src[(x+1) >> 3] & (0x80 >> ((x+1) & 7))) {
2346  ++x;
2347  r.setRight(r.right()+1);
2348  }
2349 
2350  path.addRect(r);
2351  ++n;
2352  }
2353  }
2354  src += pitch;
2355  }
2356  ++i;
2357  }
2358  ft->unlockFace();
2359  return path;
2360 }
2361 
2363 {
2365  if (!ti.glyphs.numGlyphs)
2366  return;
2367 
2368  QFontEngineX11FT *ft = static_cast<QFontEngineX11FT *>(ti.fontEngine);
2369 
2370  if (!d->cpen.isSolid()) {
2372  return;
2373  }
2374 
2375  const bool xrenderPath = (X11->use_xrender
2376  && !(d->pdev->devType() == QInternal::Pixmap
2377  && static_cast<const QPixmap *>(d->pdev)->data->pixelType() == QPixmapData::BitmapType));
2378 
2380  QVarLengthArray<glyph_t> glyphs;
2381  QTransform matrix;
2382 
2383  if (xrenderPath)
2384  matrix = d->matrix;
2385  matrix.translate(p.x(), p.y());
2386  ft->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
2387  if (glyphs.count() == 0)
2388  return;
2389 
2390 #ifndef QT_NO_XRENDER
2392  if (d->txop >= QTransform::TxScale && xrenderPath)
2393  set = ft->loadTransformedGlyphSet(d->matrix);
2394 
2395  if (!set || set->outline_drawing
2396  || !ft->loadGlyphs(set, glyphs.constData(), glyphs.size(), positions.constData(), QFontEngineFT::Format_Render))
2397  {
2399  return;
2400  }
2401 
2402  if (xrenderPath) {
2403  GlyphSet glyphSet = set->id;
2404  const QColor &pen = d->cpen.color();
2405  ::Picture src = X11->getSolidFill(d->scrn, pen);
2406  XRenderPictFormat *maskFormat = 0;
2407  if (ft->xglyph_format != PictStandardA1)
2408  maskFormat = XRenderFindStandardFormat(X11->display, ft->xglyph_format);
2409 
2410  enum { t_min = SHRT_MIN, t_max = SHRT_MAX };
2411 
2412  int i = 0;
2413  for (; i < glyphs.size()
2414  && (positions[i].x < t_min || positions[i].x > t_max
2415  || positions[i].y < t_min || positions[i].y > t_max);
2416  ++i)
2417  ;
2418 
2419  if (i >= glyphs.size())
2420  return;
2421  ++i;
2422 
2423  QFixed xp = positions[i - 1].x;
2424  QFixed yp = positions[i - 1].y;
2426 
2427  XGlyphElt32 elt;
2428  elt.glyphset = glyphSet;
2429  elt.chars = &glyphs[i - 1];
2430  elt.nchars = 1;
2431  elt.xOff = qRound(xp + offs);
2432  elt.yOff = qRound(yp + offs);
2433  for (; i < glyphs.size(); ++i) {
2434  if (positions[i].x < t_min || positions[i].x > t_max
2435  || positions[i].y < t_min || positions[i].y > t_max) {
2436  break;
2437  }
2438  QFontEngineFT::Glyph *g = ft->cachedGlyph(glyphs[i - 1]);
2439  if (g
2440  && positions[i].x == xp + g->advance
2441  && positions[i].y == yp
2442  && elt.nchars < 253 // don't draw more than 253 characters as some X servers
2443  // hang with it
2444  ) {
2445  elt.nchars++;
2446  xp += g->advance;
2447  } else {
2448  xp = positions[i].x;
2449  yp = positions[i].y;
2450 
2451  XRenderCompositeText32(X11->display, PictOpOver, src, d->picture,
2452  maskFormat, 0, 0, 0, 0,
2453  &elt, 1);
2454  elt.chars = &glyphs[i];
2455  elt.nchars = 1;
2456  elt.xOff = qRound(xp + offs);
2457  elt.yOff = qRound(yp + offs);
2458  }
2459  }
2460  XRenderCompositeText32(X11->display, PictOpOver, src, d->picture,
2461  maskFormat, 0, 0, 0, 0,
2462  &elt, 1);
2463 
2464  return;
2465 
2466  }
2467 #endif
2468 
2469  QPainterPath path = path_for_glyphs(glyphs, positions, ft);
2470  if (path.elementCount() <= 1)
2471  return;
2472  Q_ASSERT((path.elementCount() % 5) == 0);
2473  if (d->txop >= QTransform::TxScale) {
2474  painter()->save();
2475  painter()->setBrush(d->cpen.brush());
2476  painter()->setPen(Qt::NoPen);
2477  painter()->drawPath(path);
2478  painter()->restore();
2479  return;
2480  }
2481 
2482  const int rectcount = 256;
2483  XRectangle rects[rectcount];
2484  int num_rects = 0;
2485 
2486  QPoint delta(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
2487  QRect clip(d->polygonClipper.boundingRect());
2488  for (int i=0; i < path.elementCount(); i+=5) {
2489  int x = qRound(path.elementAt(i).x);
2490  int y = qRound(path.elementAt(i).y);
2491  int w = qRound(path.elementAt(i+1).x) - x;
2492  int h = qRound(path.elementAt(i+2).y) - y;
2493 
2494  QRect rect = QRect(x + delta.x(), y + delta.y(), w, h);
2495  rect = rect.intersected(clip);
2496  if (rect.isEmpty())
2497  continue;
2498 
2499  rects[num_rects].x = short(rect.x());
2500  rects[num_rects].y = short(rect.y());
2501  rects[num_rects].width = ushort(rect.width());
2502  rects[num_rects].height = ushort(rect.height());
2503  ++num_rects;
2504  if (num_rects == rectcount) {
2505  XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
2506  num_rects = 0;
2507  }
2508  }
2509  if (num_rects > 0)
2510  XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
2511 
2512 }
2513 #endif // !QT_NO_XRENDER
2514 
QPainterPath clipPath() const
Returns the currently clip as a path.
Definition: qpainter.cpp:2690
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
#define BUF_SIZE
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
void setDashOffset(qreal offset)
Sets the dash offset for the generated outlines to offset.
double d
Definition: qnumeric_p.h:62
QRect toAlignedRect() const
Returns a QRect based on the values of this rectangle that is the smallest possible integer rectangle...
Definition: qrect.cpp:2817
void clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly)
T * q_check_ptr(T *p)
Definition: qglobal.h:1857
static Picture getPatternFill(int screen, const QBrush &b)
void updateMatrix(const QTransform &matrix)
#define Q27Dot5ToXFixed(i)
QFontEngine * fontEngine
const T * constData() const
const Vertex * topRight
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
Definition: qpainterpath.h:392
QPaintEngine::DirtyFlags state() const
Returns a combination of flags identifying the set of properties that need to be updated when updatin...
Definition: qpaintengine.h:292
void setClipRect(const QRectF &clip)
Definition: qstroker_p.h:165
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
static QColormap instance(int screen=-1)
void drawPath(const QPainterPath &path)
Draws the given painter path using the current pen for outline and the current brush for filling...
Definition: qpainter.cpp:3502
void drawImage(const QRectF &r, const QImage &img, const QRectF &sr, Qt::ImageConversionFlags flags=Qt::AutoColor)
Reimplement this function to draw the part of the image specified by the sr rectangle in the given re...
The QLatin1Literal class provides a thin wrapper around string literals used in source code...
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
QRegion intersected(const QRegion &r) const
Returns a region which is the intersection of this region and r.
Definition: qregion.h:112
virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
Reimplement this virtual function to draw the polygon defined by the pointCount first points in point...
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
qreal opacity() const
Returns the opacity in the current paint engine state.
Definition: qpainter.cpp:9529
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
const QColor & color() const
Returns the brush color.
Definition: qbrush.h:183
int width() const
Returns the width of the pixmap.
Definition: qpixmap.cpp:630
CompositionMode
Defines the modes supported for digital image compositing.
Definition: qpainter.h:138
The QLine class provides a two-dimensional vector using integer precision.
Definition: qline.h:57
static int qpainterOpToXrender(QPainter::CompositionMode mode)
QPoint mapTo(QWidget *, const QPoint &) const
Translates the widget coordinate pos to the coordinate system of parent.
Definition: qwidget.cpp:4409
The QFlag class is a helper data type for QFlags.
Definition: qglobal.h:2289
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
QPoint p1() const
Returns the line&#39;s start point.
Definition: qline.h:132
QRect tessellate(const QPointF *points, int nPoints, bool winding)
static void qt_XRenderCompositeTrapezoids(Display *dpy, int op, Picture src, Picture dst, _Xconst XRenderPictFormat *maskFormat, int xSrc, int ySrc, const XTrapezoid *traps, int size)
QPaintEngineState * state
Definition: qpaintengine.h:239
qreal x2() const
Returns the x-coordinate of the line&#39;s end point.
Definition: qline.h:304
Qt::PenStyle style() const
Returns the pen style.
Definition: qpen.cpp:428
QExplicitlySharedDataPointer< QPixmapData > data
Definition: qpixmap.h:252
int qFloor(qreal v)
Definition: qmath.h:73
virtual void drawRects(const QRect *rects, int rectCount)
The default implementation converts the first rectCount rectangles in the buffer rects to a QRectF an...
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
#define EvenOddRule
Definition: qregion.cpp:1782
QPoint p2() const
Returns the line&#39;s end point.
Definition: qline.h:137
int height() const
Definition: qpaintdevice.h:92
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition: qimage.cpp:2032
RenderFlags flags
QTransform transform() const
Returns the matrix in the current paint engine state.
Definition: qpainter.cpp:9377
qreal y2() const
Returns the y-coordinate of the line&#39;s end point.
Definition: qline.h:309
void qt_draw_tile(QPaintEngine *, qreal, qreal, qreal, qreal, const QPixmap &, qreal, qreal)
void setCapStyle(Qt::PenCapStyle style)
Sets the cap style of the generated outlines to style.
QRect clipRect() const
Definition: qwidget.cpp:1997
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
void closeSubpath()
Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting ...
void updateRenderHints(QPainter::RenderHints hints)
const Vertex * bottomLeft
void fillPolygon_dev(const QPointF *points, int pointCount, GCMode gcMode, QPaintEngine::PolygonDrawMode mode)
void restore()
Restores the current painter state (pops a saved state off the stack).
Definition: qpainter.cpp:1620
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QPainterPath intersected(const QPainterPath &r) const
Returns a path which is the intersection of this path&#39;s fill area and p&#39;s fill area.
QRectF tessellate(const QPointF *points, int nPoints)
static QColor cmap[256]
Definition: qgl_mac.mm:760
static bool complexPictOp(int op)
void drawRects(const QRect *rects, int rectCount)
The default implementation converts the first rectCount rectangles in the buffer rects to a QRectF an...
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
QColor color() const
Returns the color of this pen&#39;s brush.
Definition: qpen.cpp:771
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
static const qreal aliasedCoordinateDelta
Q_GUI_EXPORT void * qt_getClipRects(const QRegion &r, int &num)
static bool clipLine(QLineF *line, const QRect &rect)
Q_GUI_EXPORT GC qt_x11_get_brush_gc(QPainter *p)
Returns the X11 specific brush GC for the painter p.
Qt::HANDLE handle() const
Returns the pixmap&#39;s handle to the device context.
Definition: qpixmap.cpp:1299
void drawPoints(const QPoint *points, int pointCount)
Draws the first pointCount points in the buffer points.
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
QRect intersected(const QRect &other) const
Returns the intersection of this rectangle and the given rectangle.
Definition: qrect.h:481
The QPolygon class provides a vector of points using integer precision.
Definition: qpolygon.h:60
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
Definition: qtransform.cpp:417
int depth() const
Returns the depth of the pixmap.
Definition: qpixmap.cpp:695
void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
void updateClipRegion_dev(const QRegion &region, Qt::ClipOperation op)
qreal y
the y coordinate of the element&#39;s position.
Definition: qpainterpath.h:80
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
bool isClipEnabled() const
Returns whether clipping is enabled or not in the current paint engine state.
Definition: qpainter.cpp:9473
The QString class provides a Unicode character string.
Definition: qstring.h:83
Q_CORE_EXPORT int qrand()
static QFixed fromReal(qreal r)
Definition: qfixed_p.h:70
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
TransformationType type() const
Returns the transformation type of this matrix.
#define Q_D(Class)
Definition: qglobal.h:2482
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
void setBrushOrigin(int x, int y)
Sets the brush&#39;s origin to point (x, y).
Definition: qpainter.h:825
virtual Type type() const =0
QPolygon toPolygon() const
Creates and returns a QPolygon by converting each QPointF to a QPoint.
Definition: qpolygon.cpp:772
virtual int devType() const
Definition: qpaintdevice.h:167
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
void strokePolygon_translated(const QPointF *points, int pointCount, bool close)
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
Q_GUI_EXPORT GC qt_x11_get_pen_gc(QPainter *p)
Returns the X11 specific pen GC for the painter p.
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
#define WindingRule
Definition: qregion.cpp:1783
QList< QPolygonF > toFillPolygons(const QMatrix &matrix=QMatrix()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void save()
Saves the current painter state (pushes the state onto a stack).
Definition: qpainter.cpp:1590
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
static QPixmap * find(const QString &key)
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
PenCapStyle
Definition: qnamespace.h:1147
#define Q_Q(Class)
Definition: qglobal.h:2483
void updatePen(const QPen &pen)
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
void setDashPattern(Qt::PenStyle)
Sets the dash pattern for the generated outlines to style.
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
Reimplement this function to draw the part of the pm specified by the sr rectangle in the given r...
QGlyphLayout glyphs
void strokePolygon_dev(const QPointF *points, int pointCount, bool close)
unsigned char uchar
Definition: qglobal.h:994
The QBitmap class provides monochrome (1-bit depth) pixmaps.
Definition: qbitmap.h:55
T * data() const
Returns a pointer to the shared data object.
Definition: qshareddata.h:145
QPainter * painter() const
Returns the paint engine&#39;s painter.
const Q_GUI_EXPORT QX11Info * qt_x11Info(const QPaintDevice *pd)
Returns the QX11Info structure for the pd paint device.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QPixmap qt_toX11Pixmap(const QPixmap &pixmap)
Definition: qpixmap_x11.cpp:93
QBrush brush() const
Returns the brush in the current paint engine state.
Definition: qpainter.cpp:9273
qreal & rx()
Returns a reference to the x coordinate of this point.
Definition: qpoint.h:302
QWidget * nativeParentWidget() const
Returns the native parent for this widget, i.
Definition: qwidget.cpp:4514
int width() const
Definition: qpaintdevice.h:91
bool isActive() const
Returns true if the paint engine is actively drawing; otherwise returns false.
Definition: qpaintengine.h:154
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
void fillPolygon_translated(const QPointF *points, int pointCount, GCMode gcMode, QPaintEngine::PolygonDrawMode mode)
QPainterPath createStroke(const QPainterPath &path) const
Generates a new path that is a fillable area representing the outline of the given path...
QPolygonF toFillPolygon(const QMatrix &matrix=QMatrix()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Qt::ClipOperation clipOperation() const
Returns the clip operation in the current paint engine state.
Definition: qpainter.cpp:9396
QPointF brushOrigin() const
Returns the brush origin in the current paint engine state.
Definition: qpainter.cpp:9287
bool hasClipping() const
Returns true if clipping has been set; otherwise returns false.
Definition: qpainter.cpp:2499
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition: qwidget.h:1041
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
Definition: qregion.cpp:4098
static const QCssKnownValue positions[NumKnownPositionModes - 1]
Definition: qcssparser.cpp:329
Qt::PenJoinStyle joinStyle() const
Returns the pen&#39;s join style.
Definition: qpen.cpp:736
void unlockFace() const
QFont font() const
Returns the font in the current paint engine state.
Definition: qpainter.cpp:9331
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
virtual Qt::HANDLE handle() const
Drawable qt_x11Handle(const QPaintDevice *pd)
Returns the X11 Drawable of the paint device.
virtual Type type() const =0
Reimplement this function to return the paint engine Type.
qreal y1() const
Returns the y-coordinate of the line&#39;s start point.
Definition: qline.h:299
void setRight(int pos)
Sets the right edge of the rectangle to the given x coordinate.
Definition: qrect.h:264
The QPolygonF class provides a vector of points using floating point precision.
Definition: qpolygon.h:134
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
QGlyphSet * defaultGlyphs()
Internal QTextItem.
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
QPainter::CompositionMode compositionMode() const
Returns the composition mode in the current paint engine state.
Definition: qpainter.cpp:9503
void convertToARGB32(bool preserveContents=true)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
QScopedPointer< QPainterPathStrokerPrivate > d_ptr
Definition: qpainterpath.h:300
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
QPaintEngine * paintEngine() const
Returns the paint engine that the painter is currently operating on if the painter is active; otherwi...
Definition: qpainter.cpp:1991
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule=Qt::OddEvenFill)
Draws the polygon defined by the first pointCount points in the array points using the current pen an...
Definition: qpainter.cpp:5205
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
void setDirty(DirtyFlags df)
Definition: qpaintengine.h:349
The QPainterPathStroker class is used to generate fillable outlines for a given painter path...
Definition: qpainterpath.h:264
QPainterPath clipPath() const
Returns the clip path in the current paint engine state.
Definition: qpainter.cpp:9457
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
Qt::FillRule fillRule() const
Returns the painter path&#39;s currently set fill rule.
void * HANDLE
Definition: qnamespace.h:1671
Qt::BrushStyle style() const
Returns the brush style.
Definition: qbrush.h:182
static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE]
unsigned long ulong
Definition: qglobal.h:997
const Vertex * bottomRight
QPixmap texture() const
Returns the custom brush pattern, or a null pixmap if no custom brush pattern has been set...
Definition: qbrush.cpp:785
bool isOpaque() const
Returns true if the brush is fully opaque otherwise false.
Definition: qbrush.cpp:910
int count() const
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
void drawXLFD(const QPointF &p, const QTextItemInt &si)
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs, const QFixedPoint *positions, GlyphFormat format=Format_Render)
void updateState(const QPaintEngineState &state)
Reimplement this function to update the state of a paint engine.
void setSystemClip(const QRegion &baseClip)
Sets the system clip for this engine.
static QLine clipStraightLine(const QRect &clip, const QLine &l)
uint pixel(const QColor &color) const
QRect toRect() const
Returns a QRect based on the values of this rectangle.
Definition: qrect.h:845
void setWinding(bool w)
void fillPath(const QPainterPath &path, GCMode gcmode, bool transform)
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
Definition: qbrush.cpp:99
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition: qpixmap.cpp:1080
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
Q_GUI_EXPORT void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image, Drawable hd, GC gc, Display *dpy, Visual *visual, int depth)
unsigned long Picture
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
static void qt_render_bitmap(Display *dpy, int scrn, Picture src, Picture dst, int sx, int sy, int x, int y, int sw, int sh, const QPen &pen)
const Vertex * topLeft
Q_GUI_EXPORT_INLINE int qGray(int r, int g, int b)
Definition: qrgb.h:75
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
bool end()
Reimplement this function to finish painting on the current paint device.
bool begin(QPaintDevice *pdev)
Reimplement this function to initialise your paint engine when painting is to start on the paint devi...
void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
Reimplement this function to draw the pixmap in the given rect, starting at the given p...
void setPixel(int x, int y, uint index_or_rgb)
Sets the pixel index or color at (x, y) to index_or_rgb.
Definition: qimage.cpp:4311
struct _XDisplay Display
Definition: qwindowdefs.h:115
void setupAdaptedOrigin(const QPoint &p)
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
The QX11Info class provides information about the X display configuration.
Definition: qx11info_x11.h:63
int depth() const
QPainter::RenderHints renderHints() const
Returns the render hints in the current paint engine state.
Definition: qpainter.cpp:9488
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
Qt::HANDLE x11_mask
static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph, QFontEngine *fe)
virtual void drawEllipse(const QRectF &r)
Reimplement this function to draw the largest ellipse that can be contained within rectangle rect...
void drawFreetype(const QPointF &p, const QTextItemInt &si)
void updateFont(const QFont &font)
ushort alpha
Returns the alpha color component of this color.
Definition: qcolor.h:242
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
static void x11SetClipRegion(Display *dpy, GC gc, GC gc2, Picture picture, const QRegion &r)
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
bool hasAlpha() const
Returns true if this pixmap has an alpha channel, or has a mask, otherwise returns false...
Definition: qpixmap.cpp:1938
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
unsigned short ushort
Definition: qglobal.h:995
Glyph * cachedGlyph(glyph_t g) const
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags=Qt::AutoColor)
Reimplement this function to draw the part of the image specified by the sr rectangle in the given re...
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
XFontStruct * fontStruct() const
const QX11Info * qt_x11Info(const QPaintDevice *pd)
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style of the generated outlines to style.
Q_DECL_CONSTEXPR const T & qBound(const T &min, const T &val, const T &max)
Definition: qglobal.h:1219
void setBrush(const QBrush &brush)
Sets the painter&#39;s brush to the given brush.
Definition: qpainter.cpp:4171
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
void setAlpha(int alpha)
Sets the alpha of this color to alpha.
Definition: qcolor.cpp:1094
void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
FT_Face lockFace(Scaling scale=Scaled) const
void setPen(const QColor &color)
Sets the painter&#39;s pen to have style Qt::SolidLine, width 0 and the specified color.
Definition: qpainter.cpp:4047
qreal widthF() const
Returns the pen width with floating point precision.
Definition: qpen.cpp:645
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void drawEllipse(const QRect &r)
The default implementation of this function calls the floating point version of this function...
QFactoryLoader * l
QRect boundingRect() const
Returns the bounding rectangle of the polygon, or QRect(0, 0, 0, 0) if the polygon is empty...
Definition: qpolygon.cpp:492
static QPixmap qt_patternForAlpha(uchar alpha, int screen)
WId internalWinId() const
Returns the window system identifier of the widget, or 0 if the widget is not created yet...
Definition: qwidget.h:244
QSizeF size() const
Returns the size of the rectangle.
Definition: qrect.h:713
qreal x
the x coordinate of the element&#39;s position.
Definition: qpainterpath.h:79
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
void addTrap(const Trapezoid &trap)
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
QList< QPolygonF > toSubpathPolygons(const QMatrix &matrix=QMatrix()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
Definition: qregion.cpp:1160
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
Definition: qpainter.cpp:9443
struct _XGC * GC
Definition: qwindowdefs.h:117
int height() const
Returns the height of the pixmap.
Definition: qpixmap.cpp:645
static QBitmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Returns a copy of the given image converted to a bitmap using the specified image conversion flags...
Definition: qbitmap.cpp:281
QGlyphSet * loadTransformedGlyphSet(const QTransform &matrix)
The QPaintEngineState class provides information about the active paint engine&#39;s current state...
Definition: qpaintengine.h:289
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove=0, bool alsoNonOpaque=false) const
Definition: qwidget.cpp:2139
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
T * data()
Returns a pointer to the data stored in the vector.
Definition: qvector.h:152
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
static void setCapStyle(int cap_style, GC gc)
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
QPen pen() const
Returns the pen in the current paint engine state.
Definition: qpainter.cpp:9259
static const int compositionModeToRenderOp[QPainter::CompositionMode_Xor+1]
QRgb rgba() const
Returns the RGB value of the color, including its alpha.
Definition: qcolor.cpp:1019
void drawLines(const QLine *lines, int lineCount)
The default implementation converts the first lineCount lines in lines to a QLineF and calls the floa...
static QPainterPath path_for_glyphs(const QVarLengthArray< glyph_t > &glyphs, const QVarLengthArray< QFixedPoint > &positions, const QFontEngineFT *ft)
void updateBrush(const QBrush &brush, const QPointF &pt)
The QTextItem class provides all the information required to draw text in a custom paint engine...
Definition: qpaintengine.h:68
Qt::PenCapStyle capStyle() const
Returns the pen&#39;s cap style.
Definition: qpen.cpp:706
void translate(int dx, int dy)
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position...
Definition: qrect.h:312
qreal x1() const
Returns the x-coordinate of the line&#39;s start point.
Definition: qline.h:294
static qreal dot(const QPointF &a, const QPointF &b)
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
void clipToEffectiveMask(QRegion &region) const
Definition: qwidget.cpp:2230
QRegion systemClip() const
Returns the system clip.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
Glyph * loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format=Format_None, bool fetchMetricsOnly=false) const
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
#define X11
QRgb rgb() const
Returns the RGB value of the color.
Definition: qcolor.cpp:1051
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
Qt::HANDLE x11PictureHandle() const
Returns the X11 Picture handle of the widget for XRender support.
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
bool end()
Ends painting.
Definition: qpainter.cpp:1929
#define DITHER_SIZE
void addEllipse(const QRectF &rect)
Creates an ellipse within the specified boundingRectangle and adds it to the painter path as a closed...
int size() const
static void x11ClearClipRegion(Display *dpy, GC gc, GC gc2, Picture picture)
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
void setWidth(qreal width)
Sets the width of the generated outline painter path to width.
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
ClipOperation
Definition: qnamespace.h:1495
static QPaintEngine::PaintEngineFeatures qt_decide_features()
friend class QPixmap
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
Definition: qpainter.cpp:3311
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
QPainter::RenderHints supportedRenderHints() const