Qt 4.8
qpaintengine_mac.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 <qbitmap.h>
43 #include <qpaintdevice.h>
44 #include <private/qpaintengine_mac_p.h>
45 #include <qpainterpath.h>
46 #include <qpixmapcache.h>
47 #include <private/qpaintengine_raster_p.h>
48 #include <private/qprintengine_mac_p.h>
49 #include <qprinter.h>
50 #include <qstack.h>
51 #include <qtextcodec.h>
52 #include <qwidget.h>
53 #include <qvarlengtharray.h>
54 #include <qdebug.h>
55 #include <qcoreapplication.h>
56 #include <qmath.h>
57 
58 #include <private/qfont_p.h>
59 #include <private/qfontengine_p.h>
60 #include <private/qfontengine_coretext_p.h>
61 #include <private/qfontengine_mac_p.h>
62 #include <private/qnumeric_p.h>
63 #include <private/qpainter_p.h>
64 #include <private/qpainterpath_p.h>
65 #include <private/qpixmap_mac_p.h>
66 #include <private/qt_mac_p.h>
67 #include <private/qtextengine_p.h>
68 #include <private/qwidget_p.h>
69 #include <private/qt_cocoa_helpers_mac_p.h>
70 
71 #include <string.h>
72 
74 
75 extern int qt_antialiasing_threshold; // QApplication.cpp
76 
77 /*****************************************************************************
78  External functions
79  *****************************************************************************/
80 extern CGImageRef qt_mac_create_imagemask(const QPixmap &px, const QRectF &sr); //qpixmap_mac.cpp
81 extern QPoint qt_mac_posInWindow(const QWidget *w); //qwidget_mac.cpp
82 extern OSWindowRef qt_mac_window_for(const QWidget *); //qwidget_mac.cpp
83 extern CGContextRef qt_mac_cg_context(const QPaintDevice *); //qpaintdevice_mac.cpp
84 extern void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp
85 extern QPixmap qt_pixmapForBrush(int, bool); //qbrush.cpp
86 
87 void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform);
88 
89 
90 //Implemented for qt_mac_p.h
92 {
93  QPaintEngine *pe = p->paintEngine();
94  if (pe->type() == QPaintEngine::MacPrinter)
95  pe = static_cast<QMacPrintEngine*>(pe)->paintEngine();
96  pe->syncState();
97  context = 0;
98  if(pe->type() == QPaintEngine::CoreGraphics)
99  context = static_cast<QCoreGraphicsPaintEngine*>(pe)->handle();
100 
101  int devType = p->device()->devType();
102  if (pe->type() == QPaintEngine::Raster
103  && (devType == QInternal::Widget || devType == QInternal::Pixmap || devType == QInternal::Image)) {
104 
107  uint flags = kCGImageAlphaPremultipliedFirst;
108 #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
109  flags |= kCGBitmapByteOrder32Host;
110 #endif
111  const QImage *image = (const QImage *) pe->paintDevice();
112 
113  context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(),
114  8, image->bytesPerLine(), colorspace, flags);
115 
116  CGContextTranslateCTM(context, 0, image->height());
117  CGContextScaleCTM(context, 1, -1);
118 
119  if (devType == QInternal::Widget) {
120  QRegion clip = p->paintEngine()->systemClip();
121  QTransform native = p->deviceTransform();
122  QTransform logical = p->combinedTransform();
123 
124  if (p->hasClipping()) {
125  QRegion r = p->clipRegion();
126  r.translate(native.dx(), native.dy());
127  if (clip.isEmpty())
128  clip = r;
129  else
130  clip &= r;
131  }
132  qt_mac_clip_cg(context, clip, 0);
133 
134  CGContextTranslateCTM(context, native.dx(), native.dy());
135  }
136  } else {
137  CGContextRetain(context);
138  }
139 }
140 
141 
142 /*****************************************************************************
143  QCoreGraphicsPaintEngine utility functions
144  *****************************************************************************/
145 
146 //conversion
147 inline static float qt_mac_convert_color_to_cg(int c) { return ((float)c * 1000 / 255) / 1000; }
148 inline static int qt_mac_convert_color_from_cg(float c) { return qRound(c * 255); }
149 CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) {
150  return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy());
151 }
152 
154 {
155  bool isWidget = (paintDevice->devType() == QInternal::Widget);
156  return QCoreGraphicsPaintEngine::macDisplayColorSpace(isWidget ? static_cast<const QWidget *>(paintDevice)
157  : 0);
158 }
159 
160 inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevice *pdev)
161 {
162  CGFloat components[] = {
167  };
168  return CGColorCreate(qt_mac_colorSpaceForDeviceType(pdev), components);
169 }
170 
171 // There's architectural problems with using native gradients
172 // on the Mac at the moment, so disable them.
173 // #define QT_MAC_USE_NATIVE_GRADIENTS
174 
175 #ifdef QT_MAC_USE_NATIVE_GRADIENTS
176 static bool drawGradientNatively(const QGradient *gradient)
177 {
178  return gradient->spread() == QGradient::PadSpread;
179 }
180 
181 // gradiant callback
182 static void qt_mac_color_gradient_function(void *info, const CGFloat *in, CGFloat *out)
183 {
184  QBrush *brush = static_cast<QBrush *>(info);
185  Q_ASSERT(brush && brush->gradient());
186 
187  const QGradientStops stops = brush->gradient()->stops();
188  const int n = stops.count();
189  Q_ASSERT(n >= 1);
190  const QGradientStop *begin = stops.constBegin();
191  const QGradientStop *end = begin + n;
192 
193  qreal p = in[0];
194  const QGradientStop *i = begin;
195  while (i != end && i->first < p)
196  ++i;
197 
198  QRgb c;
199  if (i == begin) {
200  c = begin->second.rgba();
201  } else if (i == end) {
202  c = (end - 1)->second.rgba();
203  } else {
204  const QGradientStop &s1 = *(i - 1);
205  const QGradientStop &s2 = *i;
206  qreal p1 = s1.first;
207  qreal p2 = s2.first;
208  QRgb c1 = s1.second.rgba();
209  QRgb c2 = s2.second.rgba();
210  int idist = 256 * (p - p1) / (p2 - p1);
211  int dist = 256 - idist;
212  c = qRgba(INTERPOLATE_PIXEL_256(qRed(c1), dist, qRed(c2), idist),
213  INTERPOLATE_PIXEL_256(qGreen(c1), dist, qGreen(c2), idist),
214  INTERPOLATE_PIXEL_256(qBlue(c1), dist, qBlue(c2), idist),
215  INTERPOLATE_PIXEL_256(qAlpha(c1), dist, qAlpha(c2), idist));
216  }
217 
218  out[0] = qt_mac_convert_color_to_cg(qRed(c));
219  out[1] = qt_mac_convert_color_to_cg(qGreen(c));
220  out[2] = qt_mac_convert_color_to_cg(qBlue(c));
221  out[3] = qt_mac_convert_color_to_cg(qAlpha(c));
222 }
223 #endif
224 
225 //clipping handling
227 {
228  static bool inReset = false;
229  if (inReset)
230  return;
231  inReset = true;
232 
233  CGAffineTransform old_xform = CGContextGetCTM(hd);
234 
235  //setup xforms
236  CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform));
237  while (stackCount > 0) {
238  restoreGraphicsState();
239  }
240  saveGraphicsState();
241  inReset = false;
242  //reset xforms
243  CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd)));
244  CGContextConcatCTM(hd, old_xform);
245 }
246 
247 static CGRect qt_mac_compose_rect(const QRectF &r, float off=0)
248 {
249  return CGRectMake(r.x()+off, r.y()+off, r.width(), r.height());
250 }
251 
252 static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0)
253 {
254  CGMutablePathRef ret = CGPathCreateMutable();
255  QPointF startPt;
256  for (int i=0; i<p.elementCount(); ++i) {
257  const QPainterPath::Element &elm = p.elementAt(i);
258  switch (elm.type) {
260  if(i > 0
261  && p.elementAt(i - 1).x == startPt.x()
262  && p.elementAt(i - 1).y == startPt.y())
263  CGPathCloseSubpath(ret);
264  startPt = QPointF(elm.x, elm.y);
265  CGPathMoveToPoint(ret, 0, elm.x+off, elm.y+off);
266  break;
268  CGPathAddLineToPoint(ret, 0, elm.x+off, elm.y+off);
269  break;
273  CGPathAddCurveToPoint(ret, 0,
274  elm.x+off, elm.y+off,
275  p.elementAt(i+1).x+off, p.elementAt(i+1).y+off,
276  p.elementAt(i+2).x+off, p.elementAt(i+2).y+off);
277  i+=2;
278  break;
279  default:
280  qFatal("QCoreGraphicsPaintEngine::drawPath(), unhandled type: %d", elm.type);
281  break;
282  }
283  }
284  if(!p.isEmpty()
285  && p.elementAt(p.elementCount() - 1).x == startPt.x()
286  && p.elementAt(p.elementCount() - 1).y == startPt.y())
287  CGPathCloseSubpath(ret);
288  return ret;
289 }
290 
294 
296 {
297 #if 0
298  if (!m_genericColorSpace) {
299 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
301  m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
302  } else
303 #endif
304  {
305  m_genericColorSpace = CGColorSpaceCreateDeviceRGB();
306  }
307  if (!m_postRoutineRegistered) {
308  m_postRoutineRegistered = true;
310  }
311  }
312  return m_genericColorSpace;
313 #else
314  // Just return the main display colorspace for the moment.
315  return macDisplayColorSpace();
316 #endif
317 }
318 
320 {
321  // The color space depends on which screen the widget's window is on.
322  // widget == 0 is a spacial case where we use the main display.
323  QWidget *window = widget ? widget->window() : 0;
324 
325  // Check for cached color space and return if found.
326  if (m_displayColorSpaceHash.contains(window))
327  return m_displayColorSpaceHash.value(window);
328 
329  // Find which display the window is on.
330  CGDirectDisplayID displayID;
331  if (window == 0) {
332  displayID = CGMainDisplayID();
333  } else {
334  const QRect &qrect = window->geometry();
335  CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height());
336  CGDisplayCount throwAway;
337  CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway);
338  if (dErr != kCGErrorSuccess)
339  displayID = CGMainDisplayID();
340  }
341 
342  // Get the color space from the display profile.
343  CGColorSpaceRef colorSpace = 0;
344  CMProfileRef displayProfile = 0;
345  CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile);
346  if (err == noErr) {
347  colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile);
348  CMCloseProfile(displayProfile);
349  }
350 
351  // Fallback: use generic DeviceRGB
352  if (colorSpace == 0)
353  colorSpace = CGColorSpaceCreateDeviceRGB();
354 
355  // Install cleanup routines
356  if (!m_postRoutineRegistered) {
357  m_postRoutineRegistered = true;
359  }
360 
361  // Cache and return.
362  m_displayColorSpaceHash.insert(window, colorSpace);
363  return colorSpace;
364 }
365 
367 {
368  if (m_genericColorSpace) {
369  CFRelease(m_genericColorSpace);
370  m_genericColorSpace = 0;
371  }
372  QHash<QWidget*, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin();
373  while (it != m_displayColorSpaceHash.constEnd()) {
374  if (it.value())
375  CFRelease(it.value());
376  ++it;
377  }
378  m_displayColorSpaceHash.clear();
379 }
380 
381 void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform)
382 {
383  CGAffineTransform old_xform = CGAffineTransformIdentity;
384  if(orig_xform) { //setup xforms
385  old_xform = CGContextGetCTM(hd);
386  CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform));
387  CGContextConcatCTM(hd, *orig_xform);
388  }
389 
390  //do the clipping
391  CGContextBeginPath(hd);
392  if(rgn.isEmpty()) {
393  CGContextAddRect(hd, CGRectMake(0, 0, 0, 0));
394  } else {
395 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
397  QCFType<HIMutableShapeRef> shape = rgn.toHIMutableShape();
398  Q_ASSERT(!HIShapeIsEmpty(shape));
399  HIShapeReplacePathInCGContext(shape, hd);
400  } else
401 #endif
402  {
403  QVector<QRect> rects = rgn.rects();
404  const int count = rects.size();
405  for(int i = 0; i < count; i++) {
406  const QRect &r = rects[i];
407  CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height());
408  CGContextAddRect(hd, mac_r);
409  }
410  }
411 
412  }
413  CGContextClip(hd);
414 
415  if(orig_xform) {//reset xforms
416  CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd)));
417  CGContextConcatCTM(hd, old_xform);
418  }
419 }
420 
421 
422 //pattern handling (tiling)
423 #if 1
424 # define QMACPATTERN_MASK_MULTIPLIER 32
425 #else
426 # define QMACPATTERN_MASK_MULTIPLIER 1
427 #endif
429 {
430 public:
431  QMacPattern() : as_mask(false), pdev(0), image(0) { data.bytes = 0; }
432  ~QMacPattern() { CGImageRelease(image); }
433  int width() {
434  if(image)
435  return CGImageGetWidth(image);
436  if(data.bytes)
438  return data.pixmap.width();
439  }
440  int height() {
441  if(image)
442  return CGImageGetHeight(image);
443  if(data.bytes)
445  return data.pixmap.height();
446  }
447 
448  //input
450  bool as_mask;
451  struct {
453  const uchar *bytes;
454  } data;
456  //output
458 };
460 {
461  QMacPattern *pat = (QMacPattern*)info;
462  int w = 0, h = 0;
463  bool isBitmap = (pat->data.pixmap.depth() == 1);
464  if(!pat->image) { //lazy cache
465  if(pat->as_mask) {
466  Q_ASSERT(pat->data.bytes);
467  w = h = 8;
468 #if (QMACPATTERN_MASK_MULTIPLIER == 1)
469  CGDataProviderRef provider = CGDataProviderCreateWithData(0, pat->data.bytes, w*h, 0);
470  pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false);
471  CGDataProviderRelease(provider);
472 #else
473  const int numBytes = (w*h)/sizeof(uchar);
474  uchar xor_bytes[numBytes];
475  for(int i = 0; i < numBytes; ++i)
476  xor_bytes[i] = pat->data.bytes[i] ^ 0xFF;
477  CGDataProviderRef provider = CGDataProviderCreateWithData(0, xor_bytes, w*h, 0);
478  CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false);
479  CGDataProviderRelease(provider);
480 
481  const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255);
482  QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER);
483  pm.fill(c0);
484  CGContextRef pm_ctx = qt_mac_cg_context(&pm);
485  CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev));
486  CGRect rect = CGRectMake(0, 0, w, h);
487  for(int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) {
488  rect.origin.x = x * w;
489  for(int y = 0; y < QMACPATTERN_MASK_MULTIPLIER; ++y) {
490  rect.origin.y = y * h;
491  qt_mac_drawCGImage(pm_ctx, &rect, swatch);
492  }
493  }
494  pat->image = qt_mac_create_imagemask(pm, pm.rect());
495  CGImageRelease(swatch);
496  CGContextRelease(pm_ctx);
499 #endif
500  } else {
501  w = pat->data.pixmap.width();
502  h = pat->data.pixmap.height();
503  if (isBitmap)
504  pat->image = qt_mac_create_imagemask(pat->data.pixmap, pat->data.pixmap.rect());
505  else
506  pat->image = (CGImageRef)pat->data.pixmap.macCGHandle();
507  }
508  } else {
509  w = CGImageGetWidth(pat->image);
510  h = CGImageGetHeight(pat->image);
511  }
512 
513  //draw
514  bool needRestore = false;
515  if (CGImageIsMask(pat->image)) {
516  CGContextSaveGState(c);
517  CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground, pat->pdev));
518  }
519  CGRect rect = CGRectMake(0, 0, w, h);
520  qt_mac_drawCGImage(c, &rect, pat->image);
521  if(needRestore)
522  CGContextRestoreGState(c);
523 }
524 static void qt_mac_dispose_pattern(void *info)
525 {
526  QMacPattern *pat = (QMacPattern*)info;
527  delete pat;
528 }
529 
530 /*****************************************************************************
531  QCoreGraphicsPaintEngine member functions
532  *****************************************************************************/
533 
534 inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features()
535 {
536  return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent
542 }
543 
546 {
547 }
548 
551 {
552 }
553 
555 {
556 }
557 
558 bool
560 {
562  if(isActive()) { // already active painting
563  qWarning("QCoreGraphicsPaintEngine::begin: Painter already active");
564  return false;
565  }
566 
567  //initialization
568  d->pdev = pdev;
569  d->complexXForm = false;
571  d->cosmeticPenSize = 1;
572  d->current.clipEnabled = false;
573  d->pixelSize = QPoint(1,1);
574  d->hd = qt_mac_cg_context(pdev);
575  if(d->hd) {
576  d->saveGraphicsState();
577  d->orig_xform = CGContextGetCTM(d->hd);
578  if (d->shading) {
579  CGShadingRelease(d->shading);
580  d->shading = 0;
581  }
582  d->setClip(0); //clear the context's clipping
583  }
584 
585  setActive(true);
586 
587  if(d->pdev->devType() == QInternal::Widget) { // device is a widget
588  QWidget *w = (QWidget*)d->pdev;
589  bool unclipped = w->testAttribute(Qt::WA_PaintUnclipped);
590 
591  if((w->windowType() == Qt::Desktop)) {
592  if(!unclipped)
593  qWarning("QCoreGraphicsPaintEngine::begin: Does not support clipped desktop on Mac OS X");
594  // ## need to do [qt_mac_window_for(w) makeKeyAndOrderFront]; (need to rename the file)
595  } else if(unclipped) {
596  qWarning("QCoreGraphicsPaintEngine::begin: Does not support unclipped painting");
597  }
598  } else if(d->pdev->devType() == QInternal::Pixmap) { // device is a pixmap
599  QPixmap *pm = (QPixmap*)d->pdev;
600  if(pm->isNull()) {
601  qWarning("QCoreGraphicsPaintEngine::begin: Cannot paint null pixmap");
602  end();
603  return false;
604  }
605  }
606 
611  return true;
612 }
613 
614 bool
616 {
618  setActive(false);
619  if(d->pdev->devType() == QInternal::Widget && static_cast<QWidget*>(d->pdev)->windowType() == Qt::Desktop) {
620 #ifndef QT_MAC_USE_COCOA
621  HideWindow(qt_mac_window_for(static_cast<QWidget*>(d->pdev)));
622 #else
623 // // ### need to do [qt_mac_window_for(static_cast<QWidget *>(d->pdev)) orderOut]; (need to rename)
624 #endif
625 
626  }
627  if(d->shading) {
628  CGShadingRelease(d->shading);
629  d->shading = 0;
630  }
631  d->pdev = 0;
632  if(d->hd) {
633  d->restoreGraphicsState();
634  CGContextSynchronize(d->hd);
635  CGContextRelease(d->hd);
636  d->hd = 0;
637  }
638  return true;
639 }
640 
641 void
643 {
645  QPaintEngine::DirtyFlags flags = state.state();
646 
647  if (flags & DirtyTransform)
648  updateMatrix(state.transform());
649 
650  if (flags & DirtyClipEnabled) {
651  if (state.isClipEnabled())
653  else
655  }
656 
657  if (flags & DirtyClipPath) {
658  updateClipPath(state.clipPath(), state.clipOperation());
659  } else if (flags & DirtyClipRegion) {
660  updateClipRegion(state.clipRegion(), state.clipOperation());
661  }
662 
663  // If the clip has changed we need to update all other states
664  // too, since they are included in the system context on OSX,
665  // and changing the clip resets that context back to scratch.
666  if (flags & (DirtyClipPath | DirtyClipRegion | DirtyClipEnabled))
667  flags |= AllDirty;
668 
669  if (flags & DirtyPen)
670  updatePen(state.pen());
671  if (flags & (DirtyBrush|DirtyBrushOrigin))
672  updateBrush(state.brush(), state.brushOrigin());
673  if (flags & DirtyFont)
674  updateFont(state.font());
675  if (flags & DirtyOpacity)
676  updateOpacity(state.opacity());
677  if (flags & DirtyHints)
679  if (flags & DirtyCompositionMode)
681 
682  if (flags & (DirtyPen | DirtyTransform)) {
683  if (!d->current.pen.isCosmetic()) {
685  } else if (d->current.transform.m11() < d->current.transform.m22()-1.0 ||
686  d->current.transform.m11() > d->current.transform.m22()+1.0) {
688  d->cosmeticPenSize = d->adjustPenWidth(d->current.pen.widthF());
689  if (!d->cosmeticPenSize)
690  d->cosmeticPenSize = 1.0;
691  } else {
693  static const float sqrt2 = sqrt(2);
694  qreal width = d->current.pen.widthF();
695  if (!width)
696  width = 1;
697  d->cosmeticPenSize = sqrt(pow(d->pixelSize.y(), 2) + pow(d->pixelSize.x(), 2)) / sqrt2 * width;
698  }
699  }
700 }
701 
702 void
704 {
706  Q_ASSERT(isActive());
707  d->current.pen = pen;
708  d->setStrokePen(pen);
709 }
710 
711 void
712 QCoreGraphicsPaintEngine::updateBrush(const QBrush &brush, const QPointF &brushOrigin)
713 {
715  Q_ASSERT(isActive());
716  d->current.brush = brush;
717 
718 #ifdef QT_MAC_USE_NATIVE_GRADIENTS
719  // Quartz supports only pad spread
720  if (const QGradient *gradient = brush.gradient()) {
721  if (drawGradientNatively(gradient)) {
723  } else {
725  }
726  }
727 #endif
728 
729  if (d->shading) {
730  CGShadingRelease(d->shading);
731  d->shading = 0;
732  }
733  d->setFillBrush(brushOrigin);
734 }
735 
736 void
738 {
740  CGContextSetAlpha(d->hd, opacity);
741 }
742 
743 void
745 {
747  Q_ASSERT(isActive());
748  updatePen(d->current.pen);
749 }
750 
751 void
753 {
755  Q_ASSERT(isActive());
756 
757  if (qt_is_nan(transform.m11()) || qt_is_nan(transform.m12()) || qt_is_nan(transform.m13())
758  || qt_is_nan(transform.m21()) || qt_is_nan(transform.m22()) || qt_is_nan(transform.m23())
759  || qt_is_nan(transform.m31()) || qt_is_nan(transform.m32()) || qt_is_nan(transform.m33()))
760  return;
761 
762  d->current.transform = transform;
763  d->setTransform(transform.isIdentity() ? 0 : &transform);
764  d->complexXForm = (transform.m11() != 1 || transform.m22() != 1
765  || transform.m12() != 0 || transform.m21() != 0);
766  d->pixelSize = d->devicePixelSize(d->hd);
767 }
768 
769 void
771 {
773  Q_ASSERT(isActive());
774  if(op == Qt::NoClip) {
775  if(d->current.clipEnabled) {
776  d->current.clipEnabled = false;
777  d->current.clip = QRegion();
778  d->setClip(0);
779  }
780  } else {
781  if(!d->current.clipEnabled)
782  op = Qt::ReplaceClip;
783  d->current.clipEnabled = true;
784  QRegion clipRegion(p.toFillPolygon().toPolygon(), p.fillRule());
785  if(op == Qt::ReplaceClip) {
786  d->current.clip = clipRegion;
787  d->setClip(0);
788  if(p.isEmpty()) {
789  CGRect rect = CGRectMake(0, 0, 0, 0);
790  CGContextClipToRect(d->hd, rect);
791  } else {
792  CGMutablePathRef path = qt_mac_compose_path(p);
793  CGContextBeginPath(d->hd);
794  CGContextAddPath(d->hd, path);
795  if(p.fillRule() == Qt::WindingFill)
796  CGContextClip(d->hd);
797  else
798  CGContextEOClip(d->hd);
799  CGPathRelease(path);
800  }
801  } else if(op == Qt::IntersectClip) {
802  d->current.clip = d->current.clip.intersected(clipRegion);
803  d->setClip(&d->current.clip);
804  } else if(op == Qt::UniteClip) {
805  d->current.clip = d->current.clip.united(clipRegion);
806  d->setClip(&d->current.clip);
807  }
808  }
809 }
810 
811 void
813 {
815  Q_ASSERT(isActive());
816  if(op == Qt::NoClip) {
817  d->current.clipEnabled = false;
818  d->current.clip = QRegion();
819  d->setClip(0);
820  } else {
821  if(!d->current.clipEnabled)
822  op = Qt::ReplaceClip;
823  d->current.clipEnabled = true;
824  if(op == Qt::IntersectClip)
825  d->current.clip = d->current.clip.intersected(clipRegion);
826  else if(op == Qt::ReplaceClip)
827  d->current.clip = clipRegion;
828  else if(op == Qt::UniteClip)
829  d->current.clip = d->current.clip.united(clipRegion);
830  d->setClip(&d->current.clip);
831  }
832 }
833 
834 void
836 {
838  Q_ASSERT(isActive());
839 
841  return;
842 
843  CGMutablePathRef path = qt_mac_compose_path(p);
845  if(p.fillRule() == Qt::WindingFill)
847  else
849  CGContextBeginPath(d->hd);
850  d->drawPath(ops, path);
851  CGPathRelease(path);
852 }
853 
854 void
855 QCoreGraphicsPaintEngine::drawRects(const QRectF *rects, int rectCount)
856 {
858  Q_ASSERT(isActive());
859 
861  return;
862 
863  for (int i=0; i<rectCount; ++i) {
864  QRectF r = rects[i];
865 
866  CGMutablePathRef path = CGPathCreateMutable();
867  CGPathAddRect(path, 0, qt_mac_compose_rect(r));
869  path);
870  CGPathRelease(path);
871  }
872 }
873 
874 void
875 QCoreGraphicsPaintEngine::drawPoints(const QPointF *points, int pointCount)
876 {
878  Q_ASSERT(isActive());
879 
881  return;
882 
883  if (d->current.pen.capStyle() == Qt::FlatCap)
884  CGContextSetLineCap(d->hd, kCGLineCapSquare);
885 
886  CGMutablePathRef path = CGPathCreateMutable();
887  for(int i=0; i < pointCount; i++) {
888  float x = points[i].x(), y = points[i].y();
889  CGPathMoveToPoint(path, 0, x, y);
890  CGPathAddLineToPoint(path, 0, x+0.001, y);
891  }
892 
893  bool doRestore = false;
895  //we don't want adjusted pens for point rendering
896  doRestore = true;
897  d->saveGraphicsState();
898  CGContextSetLineWidth(d->hd, d->current.pen.widthF());
899  }
901  if (doRestore)
902  d->restoreGraphicsState();
903  CGPathRelease(path);
904  if (d->current.pen.capStyle() == Qt::FlatCap)
905  CGContextSetLineCap(d->hd, kCGLineCapButt);
906 }
907 
908 void
910 {
912  Q_ASSERT(isActive());
913 
915  return;
916 
917  CGMutablePathRef path = CGPathCreateMutable();
918  CGAffineTransform transform = CGAffineTransformMakeScale(r.width() / r.height(), 1);
919  CGPathAddArc(path, &transform,(r.x() + (r.width() / 2)) / (r.width() / r.height()),
920  r.y() + (r.height() / 2), r.height() / 2, 0, (2 * M_PI), false);
922  path);
923  CGPathRelease(path);
924 }
925 
926 void
928 {
930  Q_ASSERT(isActive());
931 
933  return;
934 
935  CGMutablePathRef path = CGPathCreateMutable();
936  CGPathMoveToPoint(path, 0, points[0].x(), points[0].y());
937  for(int x = 1; x < pointCount; ++x)
938  CGPathAddLineToPoint(path, 0, points[x].x(), points[x].y());
939  if(mode != PolylineMode && points[0] != points[pointCount-1])
940  CGPathAddLineToPoint(path, 0, points[0].x(), points[0].y());
942  if (mode != PolylineMode)
945  d->drawPath(op, path);
946  CGPathRelease(path);
947 }
948 
949 void
950 QCoreGraphicsPaintEngine::drawLines(const QLineF *lines, int lineCount)
951 {
953  Q_ASSERT(isActive());
954 
956  return;
957 
958  CGMutablePathRef path = CGPathCreateMutable();
959  for(int i = 0; i < lineCount; i++) {
960  const QPointF start = lines[i].p1(), end = lines[i].p2();
961  CGPathMoveToPoint(path, 0, start.x(), start.y());
962  CGPathAddLineToPoint(path, 0, end.x(), end.y());
963  }
965  CGPathRelease(path);
966 }
967 
968 void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
969 {
971  Q_ASSERT(isActive());
972 
974  return;
975 
976  if(pm.isNull())
977  return;
978 
979  bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false;
980  CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
981  QCFType<CGImageRef> image;
982  bool isBitmap = (pm.depth() == 1);
983  if (isBitmap) {
984  doRestore = true;
985  d->saveGraphicsState();
986 
987  const QColor &col = d->current.pen.color();
988  CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev));
989  image = qt_mac_create_imagemask(pm, sr);
990  } else if (differentSize) {
992  image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height())));
993  } else {
994  image = (CGImageRef)pm.macCGHandle();
995  }
996  qt_mac_drawCGImage(d->hd, &rect, image);
997  if (doRestore)
998  d->restoreGraphicsState();
999 }
1000 
1001 static void drawImageReleaseData (void *info, const void *, size_t)
1002 {
1003  delete static_cast<QImage *>(info);
1004 }
1005 
1006 CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0)
1007 {
1008  QImage *image;
1009  if (img.depth() != 32)
1011  else
1012  image = new QImage(img);
1013 
1014  uint cgflags = kCGImageAlphaNone;
1015  switch (image->format()) {
1017  cgflags = kCGImageAlphaPremultipliedFirst;
1018  break;
1019  case QImage::Format_ARGB32:
1020  cgflags = kCGImageAlphaFirst;
1021  break;
1022  case QImage::Format_RGB32:
1023  cgflags = kCGImageAlphaNoneSkipFirst;
1024  default:
1025  break;
1026  }
1027 #if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version
1028  cgflags |= kCGBitmapByteOrder32Host;
1029 #endif
1030  QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image,
1031  static_cast<const QImage *>(image)->bits(),
1032  image->byteCount(),
1034  if (imagePtr)
1035  *imagePtr = image;
1036  return CGImageCreate(image->width(), image->height(), 8, 32,
1037  image->bytesPerLine(),
1039  cgflags, dataProvider, 0, false, kCGRenderingIntentDefault);
1040 
1041 }
1042 
1043 void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
1044  Qt::ImageConversionFlags flags)
1045 {
1047  Q_UNUSED(flags);
1048  Q_ASSERT(isActive());
1049 
1051  return;
1052 
1053  const QImage *image;
1054  QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image);
1055  CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
1056  if (QRectF(0, 0, img.width(), img.height()) != sr)
1057  cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(),
1058  sr.width(), sr.height()));
1059  qt_mac_drawCGImage(d->hd, &rect, cgimage);
1060 }
1061 
1063 {
1064 }
1065 
1067 {
1068 }
1069 
1071 {
1073 }
1074 
1077 {
1078  return d_func()->hd;
1079 }
1080 
1081 void
1083  const QPointF &p)
1084 {
1086  Q_ASSERT(isActive());
1087 
1089  return;
1090 
1091  //save the old state
1092  d->saveGraphicsState();
1093 
1094  //setup the pattern
1095  QMacPattern *qpattern = new QMacPattern;
1096  qpattern->data.pixmap = pixmap;
1097  qpattern->foreground = d->current.pen.color();
1098  qpattern->pdev = d->pdev;
1099  CGPatternCallbacks callbks;
1100  callbks.version = 0;
1101  callbks.drawPattern = qt_mac_draw_pattern;
1102  callbks.releaseInfo = qt_mac_dispose_pattern;
1103  const int width = qpattern->width(), height = qpattern->height();
1104  CGAffineTransform trans = CGContextGetCTM(d->hd);
1105  CGPatternRef pat = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height),
1106  trans, width, height,
1107  kCGPatternTilingNoDistortion, true, &callbks);
1108  CGColorSpaceRef cs = CGColorSpaceCreatePattern(0);
1109  CGContextSetFillColorSpace(d->hd, cs);
1110  CGFloat component = 1.0; //just one
1111  CGContextSetFillPattern(d->hd, pat, &component);
1112  CGSize phase = CGSizeApplyAffineTransform(CGSizeMake(-(p.x()-r.x()), -(p.y()-r.y())), trans);
1113  CGContextSetPatternPhase(d->hd, phase);
1114 
1115  //fill the rectangle
1116  CGRect mac_rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
1117  CGContextFillRect(d->hd, mac_rect);
1118 
1119  //restore the state
1120  d->restoreGraphicsState();
1121  //cleanup
1122  CGColorSpaceRelease(cs);
1123  CGPatternRelease(pat);
1124 }
1125 
1127 {
1129  if (d->current.transform.type() == QTransform::TxProject
1130 #ifndef QMAC_NATIVE_GRADIENTS
1131  || painter()->pen().brush().gradient() //Just let the base engine "emulate" the gradient
1132 #endif
1133  ) {
1134  QPaintEngine::drawTextItem(pos, item);
1135  return;
1136  }
1137 
1139  return;
1140 
1141  const QTextItemInt &ti = static_cast<const QTextItemInt &>(item);
1142 
1143  QPen oldPen = painter()->pen();
1144  QBrush oldBrush = painter()->brush();
1145  QPointF oldBrushOrigin = painter()->brushOrigin();
1147  updateBrush(oldPen.brush(), QPointF(0, 0));
1148 
1150 
1151  QFontEngine *fe = ti.fontEngine;
1152 
1154  const bool lineAA = state->renderHints() & QPainter::Antialiasing;
1155  if(textAA != lineAA)
1156  CGContextSetShouldAntialias(d->hd, textAA);
1157 
1158  if (ti.glyphs.numGlyphs) {
1159  switch (fe->type()) {
1160  case QFontEngine::Mac:
1161 #ifdef QT_MAC_USE_COCOA
1162  static_cast<QCoreTextFontEngine *>(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height());
1163 #else
1164  static_cast<QFontEngineMac *>(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height());
1165 #endif
1166  break;
1167  case QFontEngine::Box:
1168  d->drawBoxTextItem(pos, ti);
1169  break;
1170  default:
1171  break;
1172  }
1173  }
1174 
1175  if(textAA != lineAA)
1176  CGContextSetShouldAntialias(d->hd, !textAA);
1177 
1178  updatePen(oldPen);
1179  updateBrush(oldBrush, oldBrushOrigin);
1180 }
1181 
1182 QPainter::RenderHints
1184 {
1186 }
1199  kCGCompositeModePlusDarker = 11, // (max (0, (1-d) + (1-s)))
1200  kCGCompositeModePlusLighter = 12, // (min (1, s + d))
1201  };
1202 extern "C" {
1203  extern void CGContextSetCompositeOperation(CGContextRef, int);
1204 } // private function, but is in all versions of OS X.
1205 void
1207 {
1208 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
1210  int cg_mode = kCGBlendModeNormal;
1211  switch(mode) {
1213  cg_mode = kCGBlendModeMultiply;
1214  break;
1216  cg_mode = kCGBlendModeScreen;
1217  break;
1219  cg_mode = kCGBlendModeOverlay;
1220  break;
1222  cg_mode = kCGBlendModeDarken;
1223  break;
1225  cg_mode = kCGBlendModeLighten;
1226  break;
1228  cg_mode = kCGBlendModeColorDodge;
1229  break;
1231  cg_mode = kCGBlendModeColorBurn;
1232  break;
1234  cg_mode = kCGBlendModeHardLight;
1235  break;
1237  cg_mode = kCGBlendModeSoftLight;
1238  break;
1240  cg_mode = kCGBlendModeDifference;
1241  break;
1243  cg_mode = kCGBlendModeExclusion;
1244  break;
1246  cg_mode = kCGBlendModePlusLighter;
1247  break;
1249  cg_mode = kCGBlendModeNormal;
1250  break;
1252  cg_mode = kCGBlendModeDestinationOver;
1253  break;
1255  cg_mode = kCGBlendModeClear;
1256  break;
1258  cg_mode = kCGBlendModeCopy;
1259  break;
1261  cg_mode = -1;
1262  break;
1264  cg_mode = kCGBlendModeSourceIn;
1265  break;
1268  break;
1270  cg_mode = kCGBlendModeSourceOut;
1271  break;
1273  cg_mode = kCGBlendModeDestinationOver;
1274  break;
1276  cg_mode = kCGBlendModeSourceAtop;
1277  break;
1279  cg_mode = kCGBlendModeDestinationAtop;
1280  break;
1282  cg_mode = kCGBlendModeXOR;
1283  break;
1284  default:
1285  break;
1286  }
1287  if (cg_mode > -1) {
1288  CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode));
1289  }
1290  } else
1291 #endif
1292  // The standard porter duff ops.
1294  && mode <= QPainter::CompositionMode_Xor) {
1295  int cg_mode = kCGCompositeModeCopy;
1296  switch (mode) {
1298  cg_mode = kCGCompositeModeSourceOver;
1299  break;
1302  break;
1304  cg_mode = kCGCompositeModeClear;
1305  break;
1306  default:
1307  qWarning("QCoreGraphicsPaintEngine: Unhandled composition mode %d", (int)mode);
1308  break;
1310  cg_mode = kCGCompositeModeCopy;
1311  break;
1313  cg_mode = CGCompositeMode(-1);
1314  break;
1316  cg_mode = kCGCompositeModeSourceIn;
1317  break;
1320  break;
1322  cg_mode = kCGCompositeModeSourceOut;
1323  break;
1326  break;
1328  cg_mode = kCGCompositeModeSourceAtop;
1329  break;
1332  break;
1334  cg_mode = kCGCompositeModeXOR;
1335  break;
1336  }
1337  if (cg_mode > -1)
1338  CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode));
1339  } else {
1340 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
1341  bool needPrivateAPI = false;
1343  int cg_mode = kCGBlendModeNormal;
1344  switch (mode) {
1346  cg_mode = kCGBlendModeMultiply;
1347  break;
1349  cg_mode = kCGBlendModeScreen;
1350  break;
1352  cg_mode = kCGBlendModeOverlay;
1353  break;
1355  cg_mode = kCGBlendModeDarken;
1356  break;
1358  cg_mode = kCGBlendModeLighten;
1359  break;
1361  cg_mode = kCGBlendModeColorDodge;
1362  break;
1364  cg_mode = kCGBlendModeColorBurn;
1365  break;
1367  cg_mode = kCGBlendModeHardLight;
1368  break;
1370  cg_mode = kCGBlendModeSoftLight;
1371  break;
1373  cg_mode = kCGBlendModeDifference;
1374  break;
1376  cg_mode = kCGBlendModeExclusion;
1377  break;
1379  needPrivateAPI = true;
1380  cg_mode = kCGCompositeModePlusLighter;
1381  break;
1382  default:
1383  break;
1384  }
1385  if (!needPrivateAPI)
1386  CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode));
1387  else
1388  CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode));
1389  }
1390 #endif
1391  }
1392 }
1393 
1394 void
1396 {
1398  CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing);
1399  static const CGFloat ScaleFactor = qt_mac_get_scalefactor();
1400  if (ScaleFactor > 1.) {
1401  CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh);
1402  } else {
1403  CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ?
1404  kCGInterpolationHigh : kCGInterpolationNone);
1405  }
1406  bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing;
1407  if (!textAntialiasing || d->disabledSmoothFonts) {
1408  d->disabledSmoothFonts = !textAntialiasing;
1409  CGContextSetShouldSmoothFonts(d->hd, textAntialiasing);
1410  }
1411 }
1412 
1413 /*
1414  Returns the size of one device pixel in user-space coordinates.
1415 */
1417 {
1418  QPointF p1 = current.transform.inverted().map(QPointF(0, 0));
1419  QPointF p2 = current.transform.inverted().map(QPointF(1, 1));
1420  return QPointF(qAbs(p2.x() - p1.x()), qAbs(p2.y() - p1.y()));
1421 }
1422 
1423 /*
1424  Adjusts the pen width so we get correct line widths in the
1425  non-transformed, aliased case.
1426 */
1428 {
1430  float ret = penWidth;
1431  if (!complexXForm && !(q->state->renderHints() & QPainter::Antialiasing)) {
1432  if (penWidth < 2)
1433  ret = 1;
1434  else if (penWidth < 3)
1435  ret = 1.5;
1436  else
1437  ret = penWidth -1;
1438  }
1439  return ret;
1440 }
1441 
1442 void
1444 {
1445  //pencap
1446  CGLineCap cglinecap = kCGLineCapButt;
1447  if(pen.capStyle() == Qt::SquareCap)
1448  cglinecap = kCGLineCapSquare;
1449  else if(pen.capStyle() == Qt::RoundCap)
1450  cglinecap = kCGLineCapRound;
1451  CGContextSetLineCap(hd, cglinecap);
1452  CGContextSetLineWidth(hd, adjustPenWidth(pen.widthF()));
1453 
1454  //join
1455  CGLineJoin cglinejoin = kCGLineJoinMiter;
1456  if(pen.joinStyle() == Qt::BevelJoin)
1457  cglinejoin = kCGLineJoinBevel;
1458  else if(pen.joinStyle() == Qt::RoundJoin)
1459  cglinejoin = kCGLineJoinRound;
1460  CGContextSetLineJoin(hd, cglinejoin);
1461 // CGContextSetMiterLimit(hd, pen.miterLimit());
1462 
1463  //pen style
1464  QVector<CGFloat> linedashes;
1465  if(pen.style() == Qt::CustomDashLine) {
1466  QVector<qreal> customs = pen.dashPattern();
1467  for(int i = 0; i < customs.size(); ++i)
1468  linedashes.append(customs.at(i));
1469  } else if(pen.style() == Qt::DashLine) {
1470  linedashes.append(4);
1471  linedashes.append(2);
1472  } else if(pen.style() == Qt::DotLine) {
1473  linedashes.append(1);
1474  linedashes.append(2);
1475  } else if(pen.style() == Qt::DashDotLine) {
1476  linedashes.append(4);
1477  linedashes.append(2);
1478  linedashes.append(1);
1479  linedashes.append(2);
1480  } else if(pen.style() == Qt::DashDotDotLine) {
1481  linedashes.append(4);
1482  linedashes.append(2);
1483  linedashes.append(1);
1484  linedashes.append(2);
1485  linedashes.append(1);
1486  linedashes.append(2);
1487  }
1488  const CGFloat cglinewidth = pen.widthF() <= 0.0f ? 1.0f : float(pen.widthF());
1489  for(int i = 0; i < linedashes.size(); ++i) {
1490  linedashes[i] *= cglinewidth;
1491  if(cglinewidth < 3 && (cglinecap == kCGLineCapSquare || cglinecap == kCGLineCapRound)) {
1492  if((i%2))
1493  linedashes[i] += cglinewidth/2;
1494  else
1495  linedashes[i] -= cglinewidth/2;
1496  }
1497  }
1498  CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size());
1499 
1500  // color
1501  CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color(), pdev));
1502 }
1503 
1504 // Add our own patterns here to deal with the fact that the coordinate system
1505 // is flipped vertically with Quartz2D.
1506 static const uchar *qt_mac_patternForBrush(int brushStyle)
1507 {
1508  Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern);
1509  static const uchar dense1_pat[] = { 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00 };
1510  static const uchar dense2_pat[] = { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 };
1511  static const uchar dense3_pat[] = { 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa };
1512  static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
1513  static const uchar dense5_pat[] = { 0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55 };
1514  static const uchar dense6_pat[] = { 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 };
1515  static const uchar dense7_pat[] = { 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff };
1516  static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff };
1517  static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef };
1518  static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef };
1519  static const uchar fdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
1520  static const uchar bdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
1521  static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e };
1522  static const uchar *const pat_tbl[] = {
1523  dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
1524  dense6_pat, dense7_pat,
1525  hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
1526  return pat_tbl[brushStyle - Qt::Dense1Pattern];
1527 }
1528 
1530 {
1531  // pattern
1532  Qt::BrushStyle bs = current.brush.style();
1533 #ifdef QT_MAC_USE_NATIVE_GRADIENTS
1535  const QGradient *grad = static_cast<const QGradient*>(current.brush.gradient());
1536  if (drawGradientNatively(grad)) {
1537  Q_ASSERT(grad->spread() == QGradient::PadSpread);
1538 
1539  static const CGFloat domain[] = { 0.0f, +1.0f };
1540  static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, 0 };
1541  CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(&current.brush),
1542  1, domain, 4, 0, &callbacks);
1543 
1545  if (bs == Qt::LinearGradientPattern) {
1546  const QLinearGradient *linearGrad = static_cast<const QLinearGradient *>(grad);
1547  const QPointF start(linearGrad->start());
1548  const QPointF stop(linearGrad->finalStop());
1549  shading = CGShadingCreateAxial(colorspace, CGPointMake(start.x(), start.y()),
1550  CGPointMake(stop.x(), stop.y()), fill_func, true, true);
1551  } else {
1553  const QRadialGradient *radialGrad = static_cast<const QRadialGradient *>(grad);
1554  QPointF center(radialGrad->center());
1555  QPointF focal(radialGrad->focalPoint());
1556  qreal radius = radialGrad->radius();
1557  qreal focalRadius = radialGrad->focalRadius();
1558  shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()),
1559  focalRadius, CGPointMake(center.x(), center.y()), radius, fill_func, false, true);
1560  }
1561 
1562  CGFunctionRelease(fill_func);
1563  }
1564  } else
1565 #endif
1566  if(bs != Qt::SolidPattern && bs != Qt::NoBrush
1567 #ifndef QT_MAC_USE_NATIVE_GRADIENTS
1568  && (bs < Qt::LinearGradientPattern || bs > Qt::ConicalGradientPattern)
1569 #endif
1570  )
1571  {
1572  QMacPattern *qpattern = new QMacPattern;
1573  qpattern->pdev = pdev;
1574  CGFloat components[4] = { 1.0, 1.0, 1.0, 1.0 };
1575  CGColorSpaceRef base_colorspace = 0;
1576  if(bs == Qt::TexturePattern) {
1577  qpattern->data.pixmap = current.brush.texture();
1578  if(qpattern->data.pixmap.isQBitmap()) {
1579  const QColor &col = current.brush.color();
1580  components[0] = qt_mac_convert_color_to_cg(col.red());
1581  components[1] = qt_mac_convert_color_to_cg(col.green());
1582  components[2] = qt_mac_convert_color_to_cg(col.blue());
1584  }
1585  } else {
1586  qpattern->as_mask = true;
1587 
1588  qpattern->data.bytes = qt_mac_patternForBrush(bs);
1589  const QColor &col = current.brush.color();
1590  components[0] = qt_mac_convert_color_to_cg(col.red());
1591  components[1] = qt_mac_convert_color_to_cg(col.green());
1592  components[2] = qt_mac_convert_color_to_cg(col.blue());
1594  }
1595  int width = qpattern->width(), height = qpattern->height();
1596  qpattern->foreground = current.brush.color();
1597 
1598  CGColorSpaceRef fill_colorspace = CGColorSpaceCreatePattern(base_colorspace);
1599  CGContextSetFillColorSpace(hd, fill_colorspace);
1600 
1601  CGAffineTransform xform = CGContextGetCTM(hd);
1602  xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(current.brush.transform()), xform);
1603  xform = CGAffineTransformTranslate(xform, offset.x(), offset.y());
1604 
1605  CGPatternCallbacks callbks;
1606  callbks.version = 0;
1607  callbks.drawPattern = qt_mac_draw_pattern;
1608  callbks.releaseInfo = qt_mac_dispose_pattern;
1609  CGPatternRef fill_pattern = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height),
1610  xform, width, height, kCGPatternTilingNoDistortion,
1611  !base_colorspace, &callbks);
1612  CGContextSetFillPattern(hd, fill_pattern, components);
1613 
1614  CGPatternRelease(fill_pattern);
1615  CGColorSpaceRelease(fill_colorspace);
1616  } else if(bs != Qt::NoBrush) {
1617  CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color(), pdev));
1618  }
1619 }
1620 
1621 void
1623 {
1625  if(hd) {
1626  resetClip();
1627  QRegion sysClip = q->systemClip();
1628  if(!sysClip.isEmpty())
1629  qt_mac_clip_cg(hd, sysClip, &orig_xform);
1630  if(rgn)
1631  qt_mac_clip_cg(hd, *rgn, 0);
1632  }
1633 }
1634 
1636  CGMutablePathRef path;
1637  CGAffineTransform transform;
1638 };
1639 
1640 void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element)
1641 {
1642  Q_ASSERT(info && element);
1644  switch(element->type) {
1645  case kCGPathElementMoveToPoint:
1646  CGPathMoveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y);
1647  break;
1648  case kCGPathElementAddLineToPoint:
1649  CGPathAddLineToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y);
1650  break;
1651  case kCGPathElementAddQuadCurveToPoint:
1652  CGPathAddQuadCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y,
1653  element->points[1].x, element->points[1].y);
1654  break;
1655  case kCGPathElementAddCurveToPoint:
1656  CGPathAddCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y,
1657  element->points[1].x, element->points[1].y,
1658  element->points[2].x, element->points[2].y);
1659  break;
1660  case kCGPathElementCloseSubpath:
1661  CGPathCloseSubpath(t->path);
1662  break;
1663  default:
1664  qDebug() << "Unhandled path transform type: " << element->type;
1665  }
1666 }
1667 
1668 void QCoreGraphicsPaintEnginePrivate::drawPath(uchar ops, CGMutablePathRef path)
1669 {
1671  Q_ASSERT((ops & (CGFill | CGEOFill)) != (CGFill | CGEOFill)); //can't really happen
1672  if((ops & (CGFill | CGEOFill))) {
1673  if (shading) {
1674  Q_ASSERT(path);
1675  CGContextBeginPath(hd);
1676  CGContextAddPath(hd, path);
1677  saveGraphicsState();
1678  if (ops & CGFill)
1679  CGContextClip(hd);
1680  else if (ops & CGEOFill)
1681  CGContextEOClip(hd);
1682  if (current.brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) {
1683  CGRect boundingBox = CGPathGetBoundingBox(path);
1684  CGContextConcatCTM(hd,
1685  CGAffineTransformMake(boundingBox.size.width, 0,
1686  0, boundingBox.size.height,
1687  boundingBox.origin.x, boundingBox.origin.y));
1688  }
1689  CGContextDrawShading(hd, shading);
1690  restoreGraphicsState();
1691  ops &= ~CGFill;
1692  ops &= ~CGEOFill;
1693  } else if (current.brush.style() == Qt::NoBrush) {
1694  ops &= ~CGFill;
1695  ops &= ~CGEOFill;
1696  }
1697  }
1698  if((ops & CGStroke) && current.pen.style() == Qt::NoPen)
1699  ops &= ~CGStroke;
1700 
1701  if(ops & (CGEOFill | CGFill)) {
1702  CGContextBeginPath(hd);
1703  CGContextAddPath(hd, path);
1704  if (ops & CGEOFill) {
1705  CGContextEOFillPath(hd);
1706  } else {
1707  CGContextFillPath(hd);
1708  }
1709  }
1710 
1711  // Avoid saving and restoring the context if we can.
1712  const bool needContextSave = (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone ||
1713  !(q->state->renderHints() & QPainter::Antialiasing));
1714  if(ops & CGStroke) {
1715  if (needContextSave)
1716  saveGraphicsState();
1717  CGContextBeginPath(hd);
1718 
1719  // Translate a fraction of a pixel size in the y direction
1720  // to make sure that primitives painted at pixel borders
1721  // fills the right pixel. This is needed since the y xais
1722  // in the Quartz coordinate system is inverted compared to Qt.
1723  if (!(q->state->renderHints() & QPainter::Antialiasing)) {
1724  if (current.pen.style() == Qt::SolidLine || current.pen.width() >= 3)
1725  CGContextTranslateCTM(hd, double(pixelSize.x()) * 0.25, double(pixelSize.y()) * 0.25);
1726  else if (current.pen.style() == Qt::DotLine && QSysInfo::MacintoshVersion == QSysInfo::MV_10_3)
1727  ; // Do nothing.
1728  else
1729  CGContextTranslateCTM(hd, 0, double(pixelSize.y()) * 0.1);
1730  }
1731 
1732  if (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone) {
1733  // If antialiazing is enabled, use the cosmetic pen size directly.
1734  if (q->state->renderHints() & QPainter::Antialiasing)
1735  CGContextSetLineWidth(hd, cosmeticPenSize);
1736  else if (current.pen.widthF() <= 1)
1737  CGContextSetLineWidth(hd, cosmeticPenSize * 0.9f);
1738  else
1739  CGContextSetLineWidth(hd, cosmeticPenSize);
1740  }
1743  t.transform = qt_mac_convert_transform_to_cg(current.transform);
1744  t.path = CGPathCreateMutable();
1745  CGPathApply(path, &t, qt_mac_cg_transform_path_apply); //transform the path
1746  setTransform(0); //unset the context transform
1747  CGContextSetLineWidth(hd, cosmeticPenSize);
1748  CGContextAddPath(hd, t.path);
1749  CGPathRelease(t.path);
1750  } else {
1751  CGContextAddPath(hd, path);
1752  }
1753 
1754  CGContextStrokePath(hd);
1755  if (needContextSave)
1756  restoreGraphicsState();
1757  }
1758 }
1759 
ElementType type
the type of element
Definition: qpainterpath.h:81
QPainterPath clipPath() const
Returns the currently clip as a path.
Definition: qpainter.cpp:2690
qreal focalRadius() const
Returns the focal radius of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2211
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
static const uchar * qt_mac_patternForBrush(int brushStyle)
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or 0 if the painter is not acti...
Definition: qpainter.cpp:1530
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
static QCFType< CGColorRef > cgColorForQColor(const QColor &col, QPaintDevice *pdev)
QPointF focalPoint() const
Returns the focal point of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2251
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
QFontEngine * fontEngine
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
static CGColorSpaceRef macDisplayColorSpace(const QWidget *widget=0)
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
QPixmap qt_pixmapForBrush(int, bool)
Definition: qbrush.cpp:99
static CGColorSpaceRef macGenericColorSpace()
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
unsigned int QRgb
Definition: qrgb.h:53
BrushStyle
Definition: qnamespace.h:1162
static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0)
double qreal
Definition: qglobal.h:1193
static mach_timebase_info_data_t info
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
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool end()
Reimplement this function to finish painting on the current paint device.
int width() const
Returns the width of the pixmap.
Definition: qpixmap.cpp:630
QPaintDevice * paintDevice() const
Returns the device that this engine is painting on, if painting is active; otherwise returns 0...
QPointer< QWidget > widget
void syncState()
Updates all dirty states in this engine.
qreal m32() const
Returns the vertical translation factor.
Definition: qtransform.h:265
int remove(const Key &key)
Removes all the items that have the key from the hash.
Definition: qhash.h:784
CompositionMode
Defines the modes supported for digital image compositing.
Definition: qpainter.h:138
void setFillBrush(const QPointF &origin=QPoint())
const QGradient * gradient() const
Returns the gradient describing this brush.
Definition: qbrush.cpp:871
qreal pointSize
Definition: qfont_p.h:89
#define it(className, varName)
void qAddPostRoutine(QtCleanUpFunction p)
void drawPoints(const QPointF *p, int pointCount)
Draws the first pointCount points in the buffer points.
PaintEngineFeatures gccaps
Definition: qpaintengine.h:240
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
Definition: qrgb.h:66
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
bool begin(QPaintDevice *pdev)
Reimplement this function to initialise your paint engine when painting is to start on the paint devi...
QPaintEngineState * state
Definition: qpaintengine.h:239
void updateRenderHints(QPainter::RenderHints hints)
int qt_antialiasing_threshold
Qt::PenStyle style() const
Returns the pen style.
Definition: qpen.cpp:428
QPointF p1() const
Returns the line&#39;s start point.
Definition: qline.h:314
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
int height() const
Definition: qpaintdevice.h:92
QTransform transform() const
Returns the matrix in the current paint engine state.
Definition: qpainter.cpp:9377
CGFloat qt_mac_get_scalefactor()
void updateClipPath(const QPainterPath &path, Qt::ClipOperation op)
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice)
T1 first
Definition: qpair.h:65
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
T2 second
Definition: qpair.h:66
void updatePen(const QPen &pen)
int byteCount() const
Returns the number of bytes occupied by the image data.
Definition: qimage.cpp:1800
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 bool qt_is_nan(double d)
Definition: qnumeric_p.h:183
static void drawImageReleaseData(void *info, const void *, size_t)
struct CGImage * CGImageRef
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...
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
#define QMACPATTERN_MASK_MULTIPLIER
void updateBrush(const QBrush &brush, const QPointF &pt)
int depth() const
Returns the depth of the pixmap.
Definition: qpixmap.cpp:695
ushort red
Returns the red color component of this color.
Definition: qcolor.h:243
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QRadialGradient class is used in combination with QBrush to specify a radial gradient brush...
Definition: qbrush.h:297
qreal y
the y coordinate of the element&#39;s position.
Definition: qpainterpath.h:80
bool isClipEnabled() const
Returns whether clipping is enabled or not in the current paint engine state.
Definition: qpainter.cpp:9473
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_D(Class)
Definition: qglobal.h:2482
CGContextRef handle() const
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
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
#define M_PI
Definition: qmath.h:261
CGCompositeMode
QVector< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition: qpen.cpp:466
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
struct QMacPattern::@240 data
CGImageRef qt_mac_create_imagemask(const QPixmap &px, const QRectF &sr)
void updateClipRegion(const QRegion &region, Qt::ClipOperation op)
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
#define Q_Q(Class)
Definition: qglobal.h:2483
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
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...
bool isIdentity() const
Returns true if the matrix is the identity matrix, otherwise returns false.
Definition: qtransform.h:204
CGContextRef context
Definition: qt_mac_p.h:172
void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
Q_CORE_EXPORT void qDebug(const char *,...)
QGradientStops stops() const
Returns the stop points for this gradient.
Definition: qbrush.cpp:1520
void drawEllipse(const QRectF &r)
Reimplement this function to draw the largest ellipse that can be contained within rectangle rect...
QGlyphLayout glyphs
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
unsigned char uchar
Definition: qglobal.h:994
NSWindow * window
QRegion clipRegion() const
Returns the currently set clip region.
Definition: qpainter.cpp:2562
static int qt_mac_convert_color_from_cg(float c)
QPainter * painter() const
Returns the paint engine&#39;s painter.
const QPen & pen() const
Returns the painter&#39;s current pen.
Definition: qpainter.cpp:4152
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QBrush brush() const
Returns the brush in the current paint engine state.
Definition: qpainter.cpp:9273
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
Definition: qrgb.h:72
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 updateCompositionMode(QPainter::CompositionMode mode)
void updateMatrix(const QTransform &matrix)
QPoint brushOrigin() const
Returns the currently set brush origin.
Definition: qpainter.cpp:2168
QPolygonF toFillPolygon(const QMatrix &matrix=QMatrix()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void drawTextItem(const QPointF &pos, const QTextItem &item)
This function draws the text item textItem at position p.
Qt::ClipOperation clipOperation() const
Returns the clip operation in the current paint engine state.
Definition: qpainter.cpp:9396
static float pixelSize(const QFontDef &request, int dpi)
Definition: qfont_win.cpp:80
QPointF brushOrigin() const
Returns the brush origin in the current paint engine state.
Definition: qpainter.cpp:9287
WindowRef OSWindowRef
void updateOpacity(qreal opacity)
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
Qt::PenJoinStyle joinStyle() const
Returns the pen&#39;s join style.
Definition: qpen.cpp:736
void setActive(bool newState)
Sets the active state of the paint engine to state.
Definition: qpaintengine.h:155
Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
QFont font() const
Returns the font in the current paint engine state.
Definition: qpainter.cpp:9331
OSWindowRef qt_mac_window_for(const QWidget *)
Definition: qwidget_mac.mm:484
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
QPainter::RenderHints supportedRenderHints() const
void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform)
virtual Type type() const =0
Reimplement this function to return the paint engine Type.
CGContextRef qt_mac_cg_context(const QPaintDevice *)
Returns the CoreGraphics CGContextRef of the paint device.
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
void setClip(const QRegion *rgn=0)
Q_CORE_EXPORT void qWarning(const char *,...)
Internal QTextItem.
static void clearColorSpace(QWidget *w)
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
static const char * data(const QByteArray &arr)
bool isQBitmap() const
Returns true if this is a QBitmap; otherwise returns false.
Definition: qpixmap.cpp:599
unsigned int uint
Definition: qglobal.h:996
const QTransform & deviceTransform() const
Returns the matrix that transforms from logical coordinates to device coordinates of the platform dep...
Definition: qpainter.cpp:9579
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
Type type() const
Reimplement this function to return the paint engine Type.
void qt_mac_dispose_rgn(RgnHandle r)
const uchar * bytes
QTransform combinedTransform() const
Returns the transformation matrix combining the current window/viewport and world transformation...
Definition: qpainter.cpp:9669
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
void setDirty(DirtyFlags df)
Definition: qpaintengine.h:349
QPainterPath clipPath() const
Returns the clip path in the current paint engine state.
Definition: qpainter.cpp:9457
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
Definition: qpen.cpp:797
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.
static qreal component(const QPointF &point, unsigned int i)
QPoint qt_mac_posInWindow(const QWidget *w)
Definition: qwidget_mac.mm:380
static void qt_mac_dispose_pattern(void *info)
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
Definition: qrgb.h:63
struct OpaqueRgnHandle * RgnHandle
QPointF start() const
Returns the start point of this linear gradient in logical coordinates.
Definition: qbrush.cpp:1796
void updateFont(const QFont &font)
void drawLines(const QLineF *lines, int lineCount)
The default implementation splits the list of lines in lines into lineCount separate calls to drawPat...
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
static void qt_mac_draw_pattern(void *info, CGContextRef c)
qreal m31() const
Returns the horizontal translation factor.
Definition: qtransform.h:261
Q_CORE_EXPORT QTextStream & center(QTextStream &s)
const QBrush & brush() const
Returns the painter&#39;s current brush.
Definition: qpainter.cpp:4232
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition: qpixmap.cpp:1080
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
QPaintDevice * pdev
struct CGRect CGRect
float adjustPenWidth(float penWidth)
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:469
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
Q_CORE_EXPORT void qFatal(const char *,...)
static QHash< QWidget *, CGColorSpaceRef > m_displayColorSpaceHash
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
void drawPath(uchar ops, CGMutablePathRef path=0)
struct CGColorSpace * CGColorSpaceRef
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
ushort blue
Returns the blue color component of this color.
Definition: qcolor.h:245
QPainter::RenderHints renderHints() const
Returns the render hints in the current paint engine state.
Definition: qpainter.cpp:9488
ushort alpha
Returns the alpha color component of this color.
Definition: qcolor.h:242
The QLinearGradient class is used in combination with QBrush to specify a linear gradient brush...
Definition: qbrush.h:280
static CGRect qt_mac_compose_rect(const QRectF &r, float off=0)
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
The QGradient class is used in combination with QBrush to specify gradient fills. ...
Definition: qbrush.h:201
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
static CGColorSpaceRef m_genericColorSpace
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
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...
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
void drawRects(const QRectF *rects, int rectCount)
Draws the first rectCount rectangles in the buffer rects.
qreal m23() const
Returns the vertical projection factor.
Definition: qtransform.h:257
OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
QPointF p2() const
Returns the line&#39;s end point.
Definition: qline.h:319
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
CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t)
qreal radius() const
Returns the radius of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2150
Spread spread() const
Returns the spread method use by this gradient.
Definition: qbrush.h:235
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
QRect rect() const
Returns the pixmap&#39;s enclosing rectangle.
Definition: qpixmap.cpp:676
qreal x
the x coordinate of the element&#39;s position.
Definition: qpainterpath.h:79
CGImageRef image
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
QPointF center() const
Returns the center of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2102
QWidget * window() const
Returns the window for this widget, i.e.
Definition: qwidget.cpp:4492
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
Definition: qrgb.h:60
void updateState(const QPaintEngineState &state)
Reimplement this function to update the state of a paint engine.
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
Definition: qpainter.cpp:9443
qreal dashOffset() const
Returns the dash offset for the pen.
Definition: qpen.cpp:547
void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element)
int height() const
Returns the height of the pixmap.
Definition: qpixmap.cpp:645
void CGContextSetCompositeOperation(CGContextRef, int)
The QPaintEngineState class provides information about the active paint engine&#39;s current state...
Definition: qpaintengine.h:289
static float qt_mac_convert_color_to_cg(int c)
static const MacVersion MacintoshVersion
the version of the Macintosh operating system on which the application is run (Mac only)...
Definition: qglobal.h:1646
void translate(int dx, int dy)
Translates (moves) the region dx along the X axis and dy along the Y axis.
Definition: qregion.cpp:4116
T * data()
Returns a pointer to the data stored in the vector.
Definition: qvector.h:152
Qt::WindowType windowType() const
Returns the window type of this widget.
Definition: qwidget.h:937
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
QPen pen() const
Returns the pen in the current paint engine state.
Definition: qpainter.cpp:9259
struct CGContext * CGContextRef
qreal m13() const
Returns the horizontal projection factor.
Definition: qtransform.h:245
static QPaintEngine::PaintEngineFeatures qt_mac_cg_features()
QFontDef fontDef
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
The QTextItem class provides all the information required to draw text in a custom paint engine...
Definition: qpaintengine.h:68
CGImageRef toMacCGImageRef() const
Creates a CGImageRef equivalent to the QPixmap.
Qt::PenCapStyle capStyle() const
Returns the pen&#39;s cap style.
Definition: qpen.cpp:706
static const KeyPair *const end
uint styleStrategy
Definition: qfont_p.h:92
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
ushort green
Returns the green color component of this color.
Definition: qcolor.h:244
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:158
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
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...
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
qreal m33() const
Returns the division factor.
Definition: qtransform.h:269
QPointF finalStop() const
Returns the final stop point of this linear gradient in logical coordinates.
Definition: qbrush.cpp:1856
QPointF devicePixelSize(CGContextRef context)
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
float CGFloat
ClipOperation
Definition: qnamespace.h:1495
CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr=0)
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.