Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qpaintengine_mac.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <AppKit/AppKit.h>
5#include <CoreGraphics/CoreGraphics.h>
6
9
10#include <qbitmap.h>
11#include <qpaintdevice.h>
12#include <qpainterpath.h>
13#include <qpixmapcache.h>
14#include <private/qpaintengine_raster_p.h>
15#include <qprinter.h>
16#include <qstack.h>
17#include <qwidget.h>
18#include <qvarlengtharray.h>
19#include <qdebug.h>
20#include <qcoreapplication.h>
21#include <qmath.h>
22
23#include <qpa/qplatformpixmap.h>
24
25#include <private/qfont_p.h>
26#include <private/qfontengine_p.h>
27#include <private/qfontengine_coretext_p.h>
28#include <private/qnumeric_p.h>
29#include <private/qpainter_p.h>
30#include <private/qpainterpath_p.h>
31#include <private/qtextengine_p.h>
32#include <private/qcoregraphics_p.h>
33
34#include <string.h>
35
37
38/*****************************************************************************
39 QCoreGraphicsPaintEngine utility functions
40 *****************************************************************************/
41
42void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t)
43{
44 free(const_cast<void *>(memoryToFree));
45}
46
47CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr)
48{
49 QImage image = pixmap.toImage();
51 image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
52
53 const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height());
54 const qsizetype sbpr = image.bytesPerLine();
55 const uint nbytes = sw * sh;
56 // alpha is always 255 for bitmaps, ignore it in this case.
57 const quint32 mask = pixmap.depth() == 1 ? 0x00ffffff : 0xffffffff;
58 quint8 *dptr = static_cast<quint8 *>(malloc(nbytes));
59 quint32 *sptr = reinterpret_cast<quint32 *>(image.scanLine(0)), *srow;
60 for (int y = sy, offset=0; y < sh; ++y) {
61 srow = sptr + (y * (sbpr / 4));
62 for (int x = sx; x < sw; ++x)
63 *(dptr+(offset++)) = (*(srow+x) & mask) ? 255 : 0;
64 }
65 QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(nullptr, dptr, nbytes, qt_mac_cgimage_data_free);
66 return CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, nullptr, false);
67}
68
69//conversion
70inline static float qt_mac_convert_color_to_cg(int c) { return ((float)c * 1000 / 255) / 1000; }
71CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) {
72 return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy());
73}
74
75inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col)
76{
82 };
83 QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
84 return CGColorCreate(colorSpace, components);
85}
86
87// There's architectural problems with using native gradients
88// on the Mac at the moment, so disable them.
89// #define QT_MAC_USE_NATIVE_GRADIENTS
90
91#ifdef QT_MAC_USE_NATIVE_GRADIENTS
92static bool drawGradientNatively(const QGradient *gradient)
93{
94 return gradient->spread() == QGradient::PadSpread;
95}
96
97// gradiant callback
98static void qt_mac_color_gradient_function(void *info, const CGFloat *in, CGFloat *out)
99{
100 QBrush *brush = static_cast<QBrush *>(info);
101 Q_ASSERT(brush && brush->gradient());
102
103 const QGradientStops stops = brush->gradient()->stops();
104 const int n = stops.count();
105 Q_ASSERT(n >= 1);
106 const QGradientStop *begin = stops.constBegin();
107 const QGradientStop *end = begin + n;
108
109 qreal p = in[0];
110 const QGradientStop *i = begin;
111 while (i != end && i->first < p)
112 ++i;
113
114 QRgb c;
115 if (i == begin) {
116 c = begin->second.rgba();
117 } else if (i == end) {
118 c = (end - 1)->second.rgba();
119 } else {
120 const QGradientStop &s1 = *(i - 1);
121 const QGradientStop &s2 = *i;
122 qreal p1 = s1.first;
123 qreal p2 = s2.first;
124 QRgb c1 = s1.second.rgba();
125 QRgb c2 = s2.second.rgba();
126 int idist = 256 * (p - p1) / (p2 - p1);
127 int dist = 256 - idist;
128 c = qRgba(INTERPOLATE_PIXEL_256(qRed(c1), dist, qRed(c2), idist),
130 INTERPOLATE_PIXEL_256(qBlue(c1), dist, qBlue(c2), idist),
131 INTERPOLATE_PIXEL_256(qAlpha(c1), dist, qAlpha(c2), idist));
132 }
133
138}
139#endif
140
141//clipping handling
143{
144 static bool inReset = false;
145 if (inReset)
146 return;
147 inReset = true;
148
149 CGAffineTransform old_xform = CGContextGetCTM(hd);
150
151 //setup xforms
152 CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform));
153 while (stackCount > 0) {
155 }
157 inReset = false;
158 //reset xforms
159 CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd)));
160 CGContextConcatCTM(hd, old_xform);
161}
162
163static CGRect qt_mac_compose_rect(const QRectF &r, float off=0)
164{
165 return CGRectMake(r.x()+off, r.y()+off, r.width(), r.height());
166}
167
168static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0)
169{
170 CGMutablePathRef ret = CGPathCreateMutable();
171 QPointF startPt;
172 for (int i=0; i<p.elementCount(); ++i) {
173 const QPainterPath::Element &elm = p.elementAt(i);
174 switch (elm.type) {
176 if (i > 0
177 && p.elementAt(i - 1).x == startPt.x()
178 && p.elementAt(i - 1).y == startPt.y())
179 CGPathCloseSubpath(ret);
180 startPt = QPointF(elm.x, elm.y);
181 CGPathMoveToPoint(ret, 0, elm.x+off, elm.y+off);
182 break;
184 CGPathAddLineToPoint(ret, 0, elm.x+off, elm.y+off);
185 break;
187 Q_ASSERT(p.elementAt(i+1).type == QPainterPath::CurveToDataElement);
188 Q_ASSERT(p.elementAt(i+2).type == QPainterPath::CurveToDataElement);
189 CGPathAddCurveToPoint(ret, 0,
190 elm.x+off, elm.y+off,
191 p.elementAt(i+1).x+off, p.elementAt(i+1).y+off,
192 p.elementAt(i+2).x+off, p.elementAt(i+2).y+off);
193 i+=2;
194 break;
195 default:
196 qFatal("QCoreGraphicsPaintEngine::drawPath(), unhandled type: %d", elm.type);
197 break;
198 }
199 }
200 if (!p.isEmpty()
201 && p.elementAt(p.elementCount() - 1).x == startPt.x()
202 && p.elementAt(p.elementCount() - 1).y == startPt.y())
203 CGPathCloseSubpath(ret);
204 return ret;
205}
206
207//pattern handling (tiling)
208#if 1
209# define QMACPATTERN_MASK_MULTIPLIER 32
210#else
211# define QMACPATTERN_MASK_MULTIPLIER 1
212#endif
214{
215public:
216 QMacPattern() : as_mask(false), pdev(0), image(0) { data.bytes = 0; }
217 ~QMacPattern() { CGImageRelease(image); }
218 int width() {
219 if (image)
220 return CGImageGetWidth(image);
221 if (data.bytes)
223 return data.pixmap.width();
224 }
225 int height() {
226 if (image)
227 return CGImageGetHeight(image);
228 if (data.bytes)
230 return data.pixmap.height();
231 }
232
233 //input
236 struct {
238 const uchar *bytes;
241 //output
242 CGImageRef image;
243};
245{
247 int w = 0, h = 0;
248 bool isBitmap = (pat->data.pixmap.depth() == 1);
249 if (!pat->image) { //lazy cache
250 if (pat->as_mask) {
251 Q_ASSERT(pat->data.bytes);
252 w = h = 8;
253#if (QMACPATTERN_MASK_MULTIPLIER == 1)
254 CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, pat->data.bytes, w*h, nullptr);
255 pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, nullptr, false);
256 CGDataProviderRelease(provider);
257#else
258 const int numBytes = (w*h)/sizeof(uchar);
259 uchar xor_bytes[numBytes];
260 for (int i = 0; i < numBytes; ++i)
261 xor_bytes[i] = pat->data.bytes[i] ^ 0xFF;
262 CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, xor_bytes, w*h, nullptr);
263 CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, nullptr, false);
264 CGDataProviderRelease(provider);
265
266 const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255);
268 pm.fill(c0);
269 QMacCGContext pm_ctx(&pm);
270 CGContextSetFillColorWithColor(c, cgColorForQColor(c1));
271 CGRect rect = CGRectMake(0, 0, w, h);
272 for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) {
273 rect.origin.x = x * w;
274 for (int y = 0; y < QMACPATTERN_MASK_MULTIPLIER; ++y) {
275 rect.origin.y = y * h;
276 qt_mac_drawCGImage(pm_ctx, &rect, swatch);
277 }
278 }
279 pat->image = qt_mac_create_imagemask(pm, pm.rect());
280 CGImageRelease(swatch);
283#endif
284 } else {
285 w = pat->data.pixmap.width();
286 h = pat->data.pixmap.height();
287 if (isBitmap)
288 pat->image = qt_mac_create_imagemask(pat->data.pixmap, pat->data.pixmap.rect());
289 else
290 pat->image = qt_mac_toCGImage(pat->data.pixmap.toImage());
291 }
292 } else {
293 w = CGImageGetWidth(pat->image);
294 h = CGImageGetHeight(pat->image);
295 }
296
297 //draw
298 bool needRestore = false;
299 if (CGImageIsMask(pat->image)) {
300 CGContextSaveGState(c);
301 CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground));
302 }
303 CGRect rect = CGRectMake(0, 0, w, h);
304 qt_mac_drawCGImage(c, &rect, pat->image);
305 if (needRestore)
306 CGContextRestoreGState(c);
307}
308static void qt_mac_dispose_pattern(void *info)
309{
311 delete pat;
312}
313
314/*****************************************************************************
315 QCoreGraphicsPaintEngine member functions
316 *****************************************************************************/
317
327
332
337
341
342bool
344{
346 if (isActive()) { // already active painting
347 qWarning("QCoreGraphicsPaintEngine::begin: Painter already active");
348 return false;
349 }
350
351 //initialization
352 d->pdev = pdev;
353 d->complexXForm = false;
355 d->cosmeticPenSize = 1;
356 d->current.clipEnabled = false;
357 d->pixelSize = QPoint(1,1);
358
359 if (pdev->devType() != QInternal::Printer) {
360 QMacCGContext ctx(pdev);
361 d->hd = CGContextRetain(ctx);
362 if (d->hd) {
363 d->saveGraphicsState();
364 d->orig_xform = CGContextGetCTM(d->hd);
365 if (d->shading) {
366 CGShadingRelease(d->shading);
367 d->shading = nullptr;
368 }
369 d->setClip(nullptr); //clear the context's clipping
370 }
371 }
372
373 setActive(true);
374
375 if (d->pdev->devType() == QInternal::Widget) { // device is a widget
376 QWidget *w = (QWidget*)d->pdev;
377 bool unclipped = w->testAttribute(Qt::WA_PaintUnclipped);
378
379 if ((w->windowType() == Qt::Desktop)) {
380 if (!unclipped)
381 qWarning("QCoreGraphicsPaintEngine::begin: Does not support clipped desktop on OS X");
382 // ## need to do [qt_mac_window_for(w) makeKeyAndOrderFront]; (need to rename the file)
383 } else if (unclipped) {
384 qWarning("QCoreGraphicsPaintEngine::begin: Does not support unclipped painting");
385 }
386 } else if (d->pdev->devType() == QInternal::Pixmap) { // device is a pixmap
387 QPixmap *pm = (QPixmap*)d->pdev;
388 if (pm->isNull()) {
389 qWarning("QCoreGraphicsPaintEngine::begin: Cannot paint null pixmap");
390 end();
391 return false;
392 }
393 }
394
399 return true;
400}
401
402bool
404{
406 setActive(false);
407 if (d->pdev->devType() == QInternal::Widget && static_cast<QWidget*>(d->pdev)->windowType() == Qt::Desktop) {
408 // ### need to do [qt_mac_window_for(static_cast<QWidget *>(d->pdev)) orderOut]; (need to rename)
409 }
410 if (d->shading) {
411 CGShadingRelease(d->shading);
412 d->shading = 0;
413 }
414 d->pdev = nullptr;
415 if (d->hd) {
416 d->restoreGraphicsState();
417 CGContextSynchronize(d->hd);
418 CGContextRelease(d->hd);
419 d->hd = nullptr;
420 }
421 return true;
422}
423
424void
426{
428 QPaintEngine::DirtyFlags flags = state.state();
429
430 if (flags & DirtyTransform)
432
433 if (flags & DirtyClipEnabled) {
434 if (state.isClipEnabled())
435 updateClipPath(painter()->clipPath(), Qt::ReplaceClip);
436 else
438 }
439
440 if (flags & DirtyClipPath) {
442 } else if (flags & DirtyClipRegion) {
444 }
445
446 // If the clip has changed we need to update all other states
447 // too, since they are included in the system context on OSX,
448 // and changing the clip resets that context back to scratch.
450 flags |= AllDirty;
451
452 if (flags & DirtyPen)
456 if (flags & DirtyFont)
458 if (flags & DirtyOpacity)
460 if (flags & DirtyHints)
464
466 if (!d->current.pen.isCosmetic()) {
468 } else if (d->current.transform.m11() < d->current.transform.m22()-1.0 ||
469 d->current.transform.m11() > d->current.transform.m22()+1.0) {
471 d->cosmeticPenSize = d->adjustPenWidth(d->current.pen.widthF());
472 if (!d->cosmeticPenSize)
473 d->cosmeticPenSize = 1.0;
474 } else {
476 static const float sqrt2 = std::sqrt(2.0f);
477 qreal width = d->current.pen.widthF();
478 if (!width)
479 width = 1;
480 d->cosmeticPenSize = std::sqrt(std::pow(d->pixelSize.y(), 2) + std::pow(d->pixelSize.x(), 2)) / sqrt2 * width;
481 }
482 }
483}
484
485void
487{
490 d->current.pen = pen;
491 d->setStrokePen(pen);
492}
493
494void
496{
499 d->current.brush = brush;
500
501#ifdef QT_MAC_USE_NATIVE_GRADIENTS
502 // Quartz supports only pad spread
503 if (const QGradient *gradient = brush.gradient()) {
504 if (drawGradientNatively(gradient)) {
506 } else {
508 }
509 }
510#endif
511
512 if (d->shading) {
513 CGShadingRelease(d->shading);
514 d->shading = nullptr;
515 }
516 d->setFillBrush(brushOrigin);
517}
518
519void
521{
523 CGContextSetAlpha(d->hd, opacity);
524}
525
526void
533
534void
536{
539
540 if (qt_is_nan(transform.m11()) || qt_is_nan(transform.m12()) || qt_is_nan(transform.m13())
541 || qt_is_nan(transform.m21()) || qt_is_nan(transform.m22()) || qt_is_nan(transform.m23())
542 || qt_is_nan(transform.m31()) || qt_is_nan(transform.m32()) || qt_is_nan(transform.m33()))
543 return;
544
545 d->current.transform = transform;
546 d->setTransform(transform.isIdentity() ? 0 : &transform);
547 d->complexXForm = (transform.m11() != 1 || transform.m22() != 1
548 || transform.m12() != 0 || transform.m21() != 0);
549 d->pixelSize = d->devicePixelSize(d->hd);
550}
551
552void
554{
557 if (op == Qt::NoClip) {
558 if (d->current.clipEnabled) {
559 d->current.clipEnabled = false;
560 d->current.clip = QRegion();
561 d->setClip(nullptr);
562 }
563 } else {
564 if (!d->current.clipEnabled)
565 op = Qt::ReplaceClip;
566 d->current.clipEnabled = true;
567 QRegion clipRegion(p.toFillPolygon().toPolygon(), p.fillRule());
568 if (op == Qt::ReplaceClip) {
569 d->current.clip = clipRegion;
570 d->setClip(nullptr);
571 if (p.isEmpty()) {
572 CGRect rect = CGRectMake(0, 0, 0, 0);
573 CGContextClipToRect(d->hd, rect);
574 } else {
575 CGMutablePathRef path = qt_mac_compose_path(p);
576 CGContextBeginPath(d->hd);
577 CGContextAddPath(d->hd, path);
578 if (p.fillRule() == Qt::WindingFill)
579 CGContextClip(d->hd);
580 else
581 CGContextEOClip(d->hd);
582 CGPathRelease(path);
583 }
584 } else if (op == Qt::IntersectClip) {
585 d->current.clip = d->current.clip.intersected(clipRegion);
586 d->setClip(&d->current.clip);
587 }
588 }
589}
590
591void
593{
596 if (op == Qt::NoClip) {
597 d->current.clipEnabled = false;
598 d->current.clip = QRegion();
599 d->setClip(nullptr);
600 } else {
601 if (!d->current.clipEnabled)
602 op = Qt::ReplaceClip;
603 d->current.clipEnabled = true;
604 if (op == Qt::IntersectClip)
605 d->current.clip = d->current.clip.intersected(clipRegion);
606 else if (op == Qt::ReplaceClip)
607 d->current.clip = clipRegion;
608 d->setClip(&d->current.clip);
609 }
610}
611
612void
614{
617
619 return;
620
621 CGMutablePathRef path = qt_mac_compose_path(p);
623 if (p.fillRule() == Qt::WindingFill)
625 else
627 CGContextBeginPath(d->hd);
628 d->drawPath(ops, path);
629 CGPathRelease(path);
630}
631
632void
633QCoreGraphicsPaintEngine::drawRects(const QRectF *rects, int rectCount)
634{
637
639 return;
640
641 for (int i=0; i<rectCount; ++i) {
642 QRectF r = rects[i];
643
644 CGMutablePathRef path = CGPathCreateMutable();
645 CGPathAddRect(path, nullptr, qt_mac_compose_rect(r));
647 path);
648 CGPathRelease(path);
649 }
650}
651
652void
654{
657
659 return;
660
661 if (d->current.pen.capStyle() == Qt::FlatCap)
662 CGContextSetLineCap(d->hd, kCGLineCapSquare);
663
664 CGMutablePathRef path = CGPathCreateMutable();
665 for (int i=0; i < pointCount; i++) {
666 float x = points[i].x(), y = points[i].y();
667 CGPathMoveToPoint(path, nullptr, x, y);
668 CGPathAddLineToPoint(path, nullptr, x+0.001, y);
669 }
670
671 bool doRestore = false;
673 //we don't want adjusted pens for point rendering
674 doRestore = true;
675 d->saveGraphicsState();
676 CGContextSetLineWidth(d->hd, d->current.pen.widthF());
677 }
679 if (doRestore)
680 d->restoreGraphicsState();
681 CGPathRelease(path);
682 if (d->current.pen.capStyle() == Qt::FlatCap)
683 CGContextSetLineCap(d->hd, kCGLineCapButt);
684}
685
686void
688{
691
693 return;
694
695 CGMutablePathRef path = CGPathCreateMutable();
696 CGAffineTransform transform = CGAffineTransformMakeScale(r.width() / r.height(), 1);
697 CGPathAddArc(path, &transform,(r.x() + (r.width() / 2)) / (r.width() / r.height()),
698 r.y() + (r.height() / 2), r.height() / 2, 0, (2 * M_PI), false);
700 path);
701 CGPathRelease(path);
702}
703
704void
706{
709
711 return;
712
713 CGMutablePathRef path = CGPathCreateMutable();
714 CGPathMoveToPoint(path, nullptr, points[0].x(), points[0].y());
715 for (int x = 1; x < pointCount; ++x)
716 CGPathAddLineToPoint(path, nullptr, points[x].x(), points[x].y());
717 if (mode != PolylineMode && points[0] != points[pointCount-1])
718 CGPathAddLineToPoint(path, nullptr, points[0].x(), points[0].y());
720 if (mode != PolylineMode)
723 d->drawPath(op, path);
724 CGPathRelease(path);
725}
726
727void
728QCoreGraphicsPaintEngine::drawLines(const QLineF *lines, int lineCount)
729{
732
734 return;
735
736 CGMutablePathRef path = CGPathCreateMutable();
737 for (int i = 0; i < lineCount; i++) {
738 const QPointF start = lines[i].p1(), end = lines[i].p2();
739 CGPathMoveToPoint(path, nullptr, start.x(), start.y());
740 CGPathAddLineToPoint(path, nullptr, end.x(), end.y());
741 }
743 CGPathRelease(path);
744}
745
747{
750
752 return;
753
754 if (pm.isNull())
755 return;
756
757 bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false;
758 CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
759 QCFType<CGImageRef> image;
760 bool isBitmap = (pm.depth() == 1);
761 if (isBitmap) {
762 doRestore = true;
763 d->saveGraphicsState();
764
765 const QColor &col = d->current.pen.color();
766 CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col));
768 } else if (differentSize) {
769 QCFType<CGImageRef> img = qt_mac_toCGImage(pm.toImage());
770 if (img)
771 image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height())));
772 } else {
774 }
776 if (doRestore)
777 d->restoreGraphicsState();
778}
779
781 Qt::ImageConversionFlags flags)
782{
786
788 return;
789
790 QCFType<CGImageRef> cgimage = qt_mac_toCGImage(img);
791 CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
792 if (QRectF(0, 0, img.width(), img.height()) != sr)
793 cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(),
794 sr.width(), sr.height()));
795 qt_mac_drawCGImage(d->hd, &rect, cgimage);
796}
797
801
805
808{
809 return d_func()->hd;
810}
811
812void
814 const QPointF &p)
815{
818
820 return;
821
822 //save the old state
823 d->saveGraphicsState();
824
825 //setup the pattern
826 QMacPattern *qpattern = new QMacPattern;
827 qpattern->data.pixmap = pixmap;
828 qpattern->foreground = d->current.pen.color();
829 qpattern->pdev = d->pdev;
830 CGPatternCallbacks callbks;
831 callbks.version = 0;
832 callbks.drawPattern = qt_mac_draw_pattern;
833 callbks.releaseInfo = qt_mac_dispose_pattern;
834 const int width = qpattern->width(), height = qpattern->height();
835 CGAffineTransform trans = CGContextGetCTM(d->hd);
836 CGPatternRef pat = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height),
837 trans, width, height,
838 kCGPatternTilingNoDistortion, true, &callbks);
839 CGColorSpaceRef cs = CGColorSpaceCreatePattern(nullptr);
840 CGContextSetFillColorSpace(d->hd, cs);
841 CGFloat component = 1.0; //just one
842 CGContextSetFillPattern(d->hd, pat, &component);
843 CGSize phase = CGSizeApplyAffineTransform(CGSizeMake(-(p.x()-r.x()), -(p.y()-r.y())), trans);
844 CGContextSetPatternPhase(d->hd, phase);
845
846 //fill the rectangle
847 CGRect mac_rect = CGRectMake(r.x(), r.y(), r.width(), r.height());
848 CGContextFillRect(d->hd, mac_rect);
849
850 //restore the state
851 d->restoreGraphicsState();
852 //cleanup
853 CGColorSpaceRelease(cs);
854 CGPatternRelease(pat);
855}
856
858{
860 if (d->current.transform.type() == QTransform::TxProject
861#ifndef QMAC_NATIVE_GRADIENTS
862 || painter()->pen().brush().gradient() //Just let the base engine "emulate" the gradient
863#endif
864 ) {
866 return;
867 }
868
870 return;
871
872 const QTextItemInt &ti = static_cast<const QTextItemInt &>(item);
873
874 QPen oldPen = painter()->pen();
875 QBrush oldBrush = painter()->brush();
876 QPointF oldBrushOrigin = painter()->brushOrigin();
878 updateBrush(oldPen.brush(), QPointF(0, 0));
879
881
882 QFontEngine *fe = ti.fontEngine;
883
884 const bool textAA = ((state->renderHints() & QPainter::TextAntialiasing)
885 && !(fe->fontDef.styleStrategy & QFont::NoAntialias));
886 const bool lineAA = state->renderHints() & QPainter::Antialiasing;
887 if (textAA != lineAA)
888 CGContextSetShouldAntialias(d->hd, textAA);
889
890 const bool smoothing = textAA && !(fe->fontDef.styleStrategy & QFont::NoSubpixelAntialias);
891 if (d->disabledSmoothFonts == smoothing)
892 CGContextSetShouldSmoothFonts(d->hd, smoothing);
893
894 if (ti.glyphs.numGlyphs) {
895 switch (fe->type()) {
896 case QFontEngine::Mac:
897 static_cast<QCoreTextFontEngine *>(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height());
898 break;
899 case QFontEngine::Box:
900 d->drawBoxTextItem(pos, ti);
901 break;
902 default:
903 break;
904 }
905 }
906
907 if (textAA != lineAA)
908 CGContextSetShouldAntialias(d->hd, !textAA);
909
910 if (smoothing == d->disabledSmoothFonts)
911 CGContextSetShouldSmoothFonts(d->hd, !d->disabledSmoothFonts);
912
913 updatePen(oldPen);
914 updateBrush(oldBrush, oldBrushOrigin);
915}
916
917QPainter::RenderHints
937extern "C" {
939} // private function, but is in all versions of OS X.
940void
942{
943 int cg_mode = kCGBlendModeNormal;
944 switch (mode) {
946 cg_mode = kCGBlendModeMultiply;
947 break;
949 cg_mode = kCGBlendModeScreen;
950 break;
952 cg_mode = kCGBlendModeOverlay;
953 break;
955 cg_mode = kCGBlendModeDarken;
956 break;
958 cg_mode = kCGBlendModeLighten;
959 break;
961 cg_mode = kCGBlendModeColorDodge;
962 break;
964 cg_mode = kCGBlendModeColorBurn;
965 break;
967 cg_mode = kCGBlendModeHardLight;
968 break;
970 cg_mode = kCGBlendModeSoftLight;
971 break;
973 cg_mode = kCGBlendModeDifference;
974 break;
976 cg_mode = kCGBlendModeExclusion;
977 break;
979 cg_mode = kCGBlendModePlusLighter;
980 break;
982 cg_mode = kCGBlendModeNormal;
983 break;
985 cg_mode = kCGBlendModeDestinationOver;
986 break;
988 cg_mode = kCGBlendModeClear;
989 break;
991 cg_mode = kCGBlendModeCopy;
992 break;
994 cg_mode = -1;
995 break;
997 cg_mode = kCGBlendModeSourceIn;
998 break;
1001 break;
1003 cg_mode = kCGBlendModeSourceOut;
1004 break;
1006 cg_mode = kCGBlendModeDestinationOver;
1007 break;
1009 cg_mode = kCGBlendModeSourceAtop;
1010 break;
1012 cg_mode = kCGBlendModeDestinationAtop;
1013 break;
1015 cg_mode = kCGBlendModeXOR;
1016 break;
1017 default:
1018 break;
1019 }
1020 if (cg_mode > -1) {
1021 CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode));
1022 }
1023}
1024
1025void
1027{
1029 CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing);
1030 CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ?
1031 kCGInterpolationHigh : kCGInterpolationNone);
1032 bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing;
1033 if (!textAntialiasing || d->disabledSmoothFonts) {
1034 d->disabledSmoothFonts = !textAntialiasing;
1035 CGContextSetShouldSmoothFonts(d->hd, textAntialiasing);
1036 }
1037}
1038
1039/*
1040 Returns the size of one device pixel in user-space coordinates.
1041*/
1043{
1044 QPointF p1 = current.transform.inverted().map(QPointF(0, 0));
1045 QPointF p2 = current.transform.inverted().map(QPointF(1, 1));
1046 return QPointF(qAbs(p2.x() - p1.x()), qAbs(p2.y() - p1.y()));
1047}
1048
1049/*
1050 Adjusts the pen width so we get correct line widths in the
1051 non-transformed, aliased case.
1052*/
1054{
1056 float ret = penWidth;
1057 if (!complexXForm && !(q->state->renderHints() & QPainter::Antialiasing)) {
1058 if (penWidth < 2)
1059 ret = 1;
1060 else if (penWidth < 3)
1061 ret = 1.5;
1062 else
1063 ret = penWidth -1;
1064 }
1065 return ret;
1066}
1067
1068void
1070{
1071 //pencap
1072 CGLineCap cglinecap = kCGLineCapButt;
1073 if (pen.capStyle() == Qt::SquareCap)
1074 cglinecap = kCGLineCapSquare;
1075 else if (pen.capStyle() == Qt::RoundCap)
1076 cglinecap = kCGLineCapRound;
1077 CGContextSetLineCap(hd, cglinecap);
1078 CGContextSetLineWidth(hd, adjustPenWidth(pen.widthF()));
1079
1080 //join
1081 CGLineJoin cglinejoin = kCGLineJoinMiter;
1082 if (pen.joinStyle() == Qt::BevelJoin)
1083 cglinejoin = kCGLineJoinBevel;
1084 else if (pen.joinStyle() == Qt::RoundJoin)
1085 cglinejoin = kCGLineJoinRound;
1086 CGContextSetLineJoin(hd, cglinejoin);
1087// CGContextSetMiterLimit(hd, pen.miterLimit());
1088
1089 //pen style
1090 QVector<CGFloat> linedashes;
1091 if (pen.style() == Qt::CustomDashLine) {
1092 QVector<qreal> customs = pen.dashPattern();
1093 for (int i = 0; i < customs.size(); ++i)
1094 linedashes.append(customs.at(i));
1095 } else if (pen.style() == Qt::DashLine) {
1096 linedashes.append(4);
1097 linedashes.append(2);
1098 } else if (pen.style() == Qt::DotLine) {
1099 linedashes.append(1);
1100 linedashes.append(2);
1101 } else if (pen.style() == Qt::DashDotLine) {
1102 linedashes.append(4);
1103 linedashes.append(2);
1104 linedashes.append(1);
1105 linedashes.append(2);
1106 } else if (pen.style() == Qt::DashDotDotLine) {
1107 linedashes.append(4);
1108 linedashes.append(2);
1109 linedashes.append(1);
1110 linedashes.append(2);
1111 linedashes.append(1);
1112 linedashes.append(2);
1113 }
1114 const CGFloat cglinewidth = pen.widthF() <= 0.0f ? 1.0f : float(pen.widthF());
1115 for (int i = 0; i < linedashes.size(); ++i) {
1116 linedashes[i] *= cglinewidth;
1117 if (cglinewidth < 3 && (cglinecap == kCGLineCapSquare || cglinecap == kCGLineCapRound)) {
1118 if ((i%2))
1119 linedashes[i] += cglinewidth/2;
1120 else
1121 linedashes[i] -= cglinewidth/2;
1122 }
1123 }
1124 CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size());
1125
1126 // color
1127 CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color()));
1128}
1129
1130// Add our own patterns here to deal with the fact that the coordinate system
1131// is flipped vertically with Quartz2D.
1132static const uchar *qt_mac_patternForBrush(int brushStyle)
1133{
1134 Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern);
1135 static const uchar dense1_pat[] = { 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00 };
1136 static const uchar dense2_pat[] = { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 };
1137 static const uchar dense3_pat[] = { 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa };
1138 static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
1139 static const uchar dense5_pat[] = { 0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55 };
1140 static const uchar dense6_pat[] = { 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 };
1141 static const uchar dense7_pat[] = { 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff };
1142 static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff };
1143 static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef };
1144 static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef };
1145 static const uchar fdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
1146 static const uchar bdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
1147 static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e };
1148 static const uchar *const pat_tbl[] = {
1149 dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
1150 dense6_pat, dense7_pat,
1151 hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
1152 return pat_tbl[brushStyle - Qt::Dense1Pattern];
1153}
1154
1156{
1157 // pattern
1158 Qt::BrushStyle bs = current.brush.style();
1159#ifdef QT_MAC_USE_NATIVE_GRADIENTS
1161 const QGradient *grad = static_cast<const QGradient*>(current.brush.gradient());
1162 if (drawGradientNatively(grad)) {
1164
1165 static const CGFloat domain[] = { 0.0f, +1.0f };
1166 static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, nullptr };
1167 CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(&current.brush),
1168 1, domain, 4, nullptr, &callbacks);
1169
1170 CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)
1171 if (bs == Qt::LinearGradientPattern) {
1172 const QLinearGradient *linearGrad = static_cast<const QLinearGradient *>(grad);
1173 const QPointF start(linearGrad->start());
1174 const QPointF stop(linearGrad->finalStop());
1175 shading = CGShadingCreateAxial(colorspace, CGPointMake(start.x(), start.y()),
1176 CGPointMake(stop.x(), stop.y()), fill_func, true, true);
1177 } else {
1179 const QRadialGradient *radialGrad = static_cast<const QRadialGradient *>(grad);
1180 QPointF center(radialGrad->center());
1181 QPointF focal(radialGrad->focalPoint());
1182 qreal radius = radialGrad->radius();
1183 qreal focalRadius = radialGrad->focalRadius();
1184 shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()),
1185 focalRadius, CGPointMake(center.x(), center.y()), radius, fill_func, false, true);
1186 }
1187
1188 CGFunctionRelease(fill_func);
1189 }
1190 } else
1191#endif
1192 if (bs != Qt::SolidPattern && bs != Qt::NoBrush
1193#ifndef QT_MAC_USE_NATIVE_GRADIENTS
1194 && (bs < Qt::LinearGradientPattern || bs > Qt::ConicalGradientPattern)
1195#endif
1196 )
1197 {
1198 QMacPattern *qpattern = new QMacPattern;
1199 qpattern->pdev = pdev;
1200 CGFloat components[4] = { 1.0, 1.0, 1.0, 1.0 };
1201 CGColorSpaceRef base_colorspace = nullptr;
1202 if (bs == Qt::TexturePattern) {
1203 qpattern->data.pixmap = current.brush.texture();
1204 if (qpattern->data.pixmap.isQBitmap()) {
1205 const QColor &col = current.brush.color();
1209 base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
1210 }
1211 } else {
1212 qpattern->as_mask = true;
1213
1214 qpattern->data.bytes = qt_mac_patternForBrush(bs);
1215 const QColor &col = current.brush.color();
1219 base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
1220 }
1221 int width = qpattern->width(), height = qpattern->height();
1222 qpattern->foreground = current.brush.color();
1223
1224 CGColorSpaceRef fill_colorspace = CGColorSpaceCreatePattern(base_colorspace);
1225 CGContextSetFillColorSpace(hd, fill_colorspace);
1226
1227 CGAffineTransform xform = CGContextGetCTM(hd);
1228 xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(current.brush.transform()), xform);
1229 xform = CGAffineTransformTranslate(xform, offset.x(), offset.y());
1230
1231 CGPatternCallbacks callbks;
1232 callbks.version = 0;
1233 callbks.drawPattern = qt_mac_draw_pattern;
1234 callbks.releaseInfo = qt_mac_dispose_pattern;
1235 CGPatternRef fill_pattern = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height),
1236 xform, width, height, kCGPatternTilingNoDistortion,
1237 !base_colorspace, &callbks);
1238 CGContextSetFillPattern(hd, fill_pattern, components);
1239
1240
1241 CGPatternRelease(fill_pattern);
1242 CGColorSpaceRelease(base_colorspace);
1243 CGColorSpaceRelease(fill_colorspace);
1244 } else if (bs != Qt::NoBrush) {
1245 CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color()));
1246 }
1247}
1248
1249void
1251{
1253 if (hd) {
1254 resetClip();
1255 QRegion sysClip = q->systemClip();
1256 if (!sysClip.isEmpty())
1257 qt_mac_clip_cg(hd, sysClip, &orig_xform);
1258 if (rgn)
1259 qt_mac_clip_cg(hd, *rgn, nullptr);
1260 }
1261}
1262
1264 CGMutablePathRef path;
1265 CGAffineTransform transform;
1266};
1267
1268void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element)
1269{
1270 Q_ASSERT(info && element);
1272 switch (element->type) {
1273 case kCGPathElementMoveToPoint:
1274 CGPathMoveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y);
1275 break;
1276 case kCGPathElementAddLineToPoint:
1277 CGPathAddLineToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y);
1278 break;
1279 case kCGPathElementAddQuadCurveToPoint:
1280 CGPathAddQuadCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y,
1281 element->points[1].x, element->points[1].y);
1282 break;
1283 case kCGPathElementAddCurveToPoint:
1284 CGPathAddCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y,
1285 element->points[1].x, element->points[1].y,
1286 element->points[2].x, element->points[2].y);
1287 break;
1288 case kCGPathElementCloseSubpath:
1289 CGPathCloseSubpath(t->path);
1290 break;
1291 default:
1292 qDebug() << "Unhandled path transform type: " << element->type;
1293 }
1294}
1295
1297{
1299 Q_ASSERT((ops & (CGFill | CGEOFill)) != (CGFill | CGEOFill)); //can't really happen
1300 if ((ops & (CGFill | CGEOFill))) {
1301 if (shading) {
1302 Q_ASSERT(path);
1303 CGContextBeginPath(hd);
1304 CGContextAddPath(hd, path);
1306 if (ops & CGFill)
1307 CGContextClip(hd);
1308 else if (ops & CGEOFill)
1309 CGContextEOClip(hd);
1310 if (current.brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) {
1311 CGRect boundingBox = CGPathGetBoundingBox(path);
1312 CGContextConcatCTM(hd,
1313 CGAffineTransformMake(boundingBox.size.width, 0,
1314 0, boundingBox.size.height,
1315 boundingBox.origin.x, boundingBox.origin.y));
1316 }
1317 CGContextDrawShading(hd, shading);
1319 ops &= ~CGFill;
1320 ops &= ~CGEOFill;
1321 } else if (current.brush.style() == Qt::NoBrush) {
1322 ops &= ~CGFill;
1323 ops &= ~CGEOFill;
1324 }
1325 }
1326 if ((ops & CGStroke) && current.pen.style() == Qt::NoPen)
1327 ops &= ~CGStroke;
1328
1329 if (ops & (CGEOFill | CGFill)) {
1330 CGContextBeginPath(hd);
1331 CGContextAddPath(hd, path);
1332 if (ops & CGEOFill) {
1333 CGContextEOFillPath(hd);
1334 } else {
1335 CGContextFillPath(hd);
1336 }
1337 }
1338
1339 // Avoid saving and restoring the context if we can.
1340 const bool needContextSave = (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone ||
1341 !(q->state->renderHints() & QPainter::Antialiasing));
1342 if (ops & CGStroke) {
1343 if (needContextSave)
1345 CGContextBeginPath(hd);
1346
1347 // Translate a fraction of a pixel size in the y direction
1348 // to make sure that primitives painted at pixel borders
1349 // fills the right pixel. This is needed since the y xais
1350 // in the Quartz coordinate system is inverted compared to Qt.
1351 if (!(q->state->renderHints() & QPainter::Antialiasing)) {
1352 if (current.pen.style() == Qt::SolidLine || current.pen.width() >= 3)
1353 CGContextTranslateCTM(hd, double(pixelSize.x()) * 0.25, double(pixelSize.y()) * 0.25);
1354 else
1355 CGContextTranslateCTM(hd, 0, double(pixelSize.y()) * 0.1);
1356 }
1357
1359 // If antialiazing is enabled, use the cosmetic pen size directly.
1360 if (q->state->renderHints() & QPainter::Antialiasing)
1361 CGContextSetLineWidth(hd, cosmeticPenSize);
1362 else if (current.pen.widthF() <= 1)
1363 CGContextSetLineWidth(hd, cosmeticPenSize * 0.9f);
1364 else
1365 CGContextSetLineWidth(hd, cosmeticPenSize);
1366 }
1370 t.path = CGPathCreateMutable();
1371 CGPathApply(path, &t, qt_mac_cg_transform_path_apply); //transform the path
1372 setTransform(nullptr); //unset the context transform
1373 CGContextSetLineWidth(hd, cosmeticPenSize);
1374 CGContextAddPath(hd, t.path);
1375 CGPathRelease(t.path);
1376 } else {
1377 CGContextAddPath(hd, path);
1378 }
1379
1380 CGContextStrokePath(hd);
1381 if (needContextSave)
1383 }
1384}
1385
\inmodule QtGui
Definition qbrush.h:30
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
int alpha() const noexcept
Returns the alpha color component of this color.
Definition qcolor.cpp:1466
int red() const noexcept
Returns the red color component of this color.
Definition qcolor.cpp:1528
int blue() const noexcept
Returns the blue color component of this color.
Definition qcolor.cpp:1583
int green() const noexcept
Returns the green color component of this color.
Definition qcolor.cpp:1555
enum QCoreGraphicsPaintEnginePrivate::@472 cosmeticPen
void setTransform(const QTransform *matrix=nullptr)
void setFillBrush(const QPointF &origin=QPoint())
QPointF devicePixelSize(CGContextRef context)
struct QCoreGraphicsPaintEnginePrivate::@471 current
void drawPath(uchar ops, CGMutablePathRef path=nullptr)
void setClip(const QRegion *rgn=nullptr)
void updateState(const QPaintEngineState &state)
Reimplement this function to update the state of a paint engine.
void updateRenderHints(QPainter::RenderHints hints)
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...
Type type() const
Reimplement this function to return the paint engine \l{Type}.
void drawPoints(const QPointF *p, int pointCount)
Draws the first pointCount points in the buffer points.
void drawRects(const QRectF *rects, int rectCount)
Draws the first rectCount rectangles in the buffer rects.
void drawTextItem(const QPointF &pos, const QTextItem &item)
This function draws the text item textItem at position p.
void updateMatrix(const QTransform &matrix)
void updateBrush(const QBrush &brush, const QPointF &pt)
QPainter::RenderHints supportedRenderHints() const
void updateClipPath(const QPainterPath &path, Qt::ClipOperation op)
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 updateCompositionMode(QPainter::CompositionMode mode)
CGContextRef handle() const
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...
void updateClipRegion(const QRegion &region, Qt::ClipOperation op)
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 drawEllipse(const QRectF &r)
Reimplement this function to draw the largest ellipse that can be contained within rectangle rect.
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...
void updatePen(const QPen &pen)
void updateOpacity(qreal opacity)
void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
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.
\reentrant
Definition qfont.h:22
@ NoSubpixelAntialias
Definition qfont.h:48
@ NoAntialias
Definition qfont.h:47
\inmodule QtGui
Definition qbrush.h:135
Spread spread() const
Returns the spread method use by this gradient.
Definition qbrush.h:347
@ ObjectBoundingMode
Definition qbrush.h:156
@ PadSpread
Definition qbrush.h:147
\inmodule QtGui
Definition qimage.h:37
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
\inmodule QtCore\compares equality \compareswith equality QLine \endcompareswith
Definition qline.h:192
constexpr QPointF p1() const
Returns the line's start point.
Definition qline.h:317
constexpr QPointF p2() const
Returns the line's end point.
Definition qline.h:322
\inmodule QtGui
Definition qbrush.h:394
const_iterator constBegin() const noexcept
Definition qlist.h:632
qsizetype count() const noexcept
Definition qlist.h:398
void append(parameter_type t)
Definition qlist.h:458
QPaintDevice * pdev
struct QMacPattern::@474 data
const uchar * bytes
virtual int devType() const
int height() const
QPaintDevice * pdev
The QPaintEngineState class provides information about the active paint engine's current state....
QTransform transform() const
QPainterPath clipPath() const
Returns the clip path in the current paint engine state.
Qt::ClipOperation clipOperation() const
Returns the clip operation in the current paint engine state.
QPointF brushOrigin() const
Returns the brush origin in the current paint engine state.
qreal opacity() const
bool isClipEnabled() const
Returns whether clipping is enabled or not in the current paint engine state.
QBrush brush() const
Returns the brush in the current paint engine state.
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
QPainter::RenderHints renderHints() const
Returns the render hints in the current paint engine state.
QFont font() const
Returns the font in the current paint engine state.
QPen pen() const
Returns the pen in the current paint engine state.
QPaintEngine::DirtyFlags state() const
Returns a combination of flags identifying the set of properties that need to be updated when updatin...
QPainter::CompositionMode compositionMode() const
Returns the composition mode in the current paint engine state.
\inmodule QtGui
void setActive(bool newState)
Sets the active state of the paint engine to state.
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
PolygonDrawMode
\value OddEvenMode The polygon should be drawn using OddEven fill rule.
QPainter * painter() const
Returns the paint engine's painter.
void setDirty(DirtyFlags df)
QPaintEngineState * state
PaintEngineFeatures gccaps
bool isActive() const
Returns true if the paint engine is actively drawing; otherwise returns false.
QPaintDevice * paintDevice() const
Returns the device that this engine is painting on, if painting is active; otherwise returns \nullptr...
\inmodule QtGui
\inmodule QtGui
const QPen & pen() const
Returns the painter's current pen.
const QBrush & brush() const
Returns the painter's current brush.
QPoint brushOrigin() const
Returns the currently set brush origin.
@ SmoothPixmapTransform
Definition qpainter.h:54
@ Antialiasing
Definition qpainter.h:52
@ TextAntialiasing
Definition qpainter.h:53
CompositionMode
Defines the modes supported for digital image compositing.
Definition qpainter.h:97
@ CompositionMode_Xor
Definition qpainter.h:109
@ CompositionMode_Destination
Definition qpainter.h:102
@ CompositionMode_Lighten
Definition qpainter.h:117
@ CompositionMode_ColorDodge
Definition qpainter.h:118
@ CompositionMode_DestinationAtop
Definition qpainter.h:108
@ CompositionMode_SourceOver
Definition qpainter.h:98
@ CompositionMode_DestinationOut
Definition qpainter.h:106
@ CompositionMode_Clear
Definition qpainter.h:100
@ CompositionMode_SourceAtop
Definition qpainter.h:107
@ CompositionMode_Plus
Definition qpainter.h:112
@ CompositionMode_Overlay
Definition qpainter.h:115
@ CompositionMode_Multiply
Definition qpainter.h:113
@ CompositionMode_Darken
Definition qpainter.h:116
@ CompositionMode_DestinationOver
Definition qpainter.h:99
@ CompositionMode_HardLight
Definition qpainter.h:120
@ CompositionMode_Exclusion
Definition qpainter.h:123
@ CompositionMode_Source
Definition qpainter.h:101
@ CompositionMode_ColorBurn
Definition qpainter.h:119
@ CompositionMode_Difference
Definition qpainter.h:122
@ CompositionMode_SoftLight
Definition qpainter.h:121
@ CompositionMode_DestinationIn
Definition qpainter.h:104
@ CompositionMode_Screen
Definition qpainter.h:114
@ CompositionMode_SourceOut
Definition qpainter.h:105
@ CompositionMode_SourceIn
Definition qpainter.h:103
\inmodule QtGui
Definition qpen.h:28
qreal widthF() const
Returns the pen width with floating point precision.
Definition qpen.cpp:572
QList< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition qpen.cpp:400
QColor color() const
Returns the color of this pen's brush.
Definition qpen.cpp:692
Qt::PenCapStyle capStyle() const
Returns the pen's cap style.
Definition qpen.cpp:636
Qt::PenJoinStyle joinStyle() const
Returns the pen's join style.
Definition qpen.cpp:663
qreal dashOffset() const
Returns the dash offset for the pen.
Definition qpen.cpp:484
Qt::PenStyle style() const
Returns the pen style.
Definition qpen.cpp:366
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
int height() const
Returns the height of the pixmap.
Definition qpixmap.cpp:480
QImage toImage() const
Converts the pixmap to a QImage.
Definition qpixmap.cpp:408
int depth() const
Returns the depth of the pixmap.
Definition qpixmap.cpp:521
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:456
int width() const
Returns the width of the pixmap.
Definition qpixmap.cpp:468
QRect rect() const
Returns the pixmap's enclosing rectangle.
Definition qpixmap.cpp:505
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:850
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtGui
Definition qbrush.h:412
\inmodule QtCore\reentrant
Definition qrect.h:484
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
Internal QTextItem.
\inmodule QtGui
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
Qt::WindowType windowType() const
Returns the window type of this widget.
Definition qwidget.h:801
EGLContext ctx
QPixmap p2
QPixmap p1
[0]
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
@ WA_PaintUnclipped
Definition qnamespace.h:318
ClipOperation
@ ReplaceClip
@ IntersectClip
@ NoClip
@ CustomDashLine
@ DashDotDotLine
@ DotLine
@ SolidLine
@ DashDotLine
@ DashLine
@ NoPen
@ BevelJoin
@ RoundJoin
BrushStyle
@ SolidPattern
@ RadialGradientPattern
@ Dense1Pattern
@ TexturePattern
@ LinearGradientPattern
@ NoBrush
@ ConicalGradientPattern
@ WindingFill
@ Desktop
Definition qnamespace.h:215
@ SquareCap
@ RoundCap
@ FlatCap
Definition brush.cpp:5
Definition image.cpp:4
QPair< qreal, QColor > QGradientStop
Definition qbrush.h:131
float CGFloat
void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform)
CGImageRef qt_mac_toCGImage(const QImage &inImage)
static uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
return ret
#define M_PI
Definition qmath.h:209
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
static Q_DECL_CONST_FUNCTION bool qt_is_nan(double d)
Definition qnumeric_p.h:112
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLint GLenum GLint components
GLboolean r
[2]
GLuint GLuint end
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLbitfield flags
GLuint start
GLenum GLuint GLintptr offset
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLfloat n
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLuint GLenum GLenum transform
GLfixed GLfixed GLint GLint GLfixed points
const GLubyte * c
GLint void * img
Definition qopenglext.h:233
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint in
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
QT_BEGIN_NAMESPACE void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t)
static QCFType< CGColorRef > cgColorForQColor(const QColor &col)
static void qt_mac_draw_pattern(void *info, CGContextRef c)
static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0)
CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t)
static float qt_mac_convert_color_to_cg(int c)
static CGRect qt_mac_compose_rect(const QRectF &r, float off=0)
void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element)
void CGContextSetCompositeOperation(CGContextRef, int)
CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr)
static const uchar * qt_mac_patternForBrush(int brushStyle)
#define QMACPATTERN_MASK_MULTIPLIER
static QPaintEngine::PaintEngineFeatures qt_mac_cg_features()
static void qt_mac_dispose_pattern(void *info)
CGCompositeMode
@ kCGCompositeModeDestinationAtop
@ kCGCompositeModeSourceOut
@ kCGCompositeModeClear
@ kCGCompositeModeDestinationIn
@ kCGCompositeModeDestinationOver
@ kCGCompositeModeXOR
@ kCGCompositeModeSourceOver
@ kCGCompositeModePlusDarker
@ kCGCompositeModeDestinationOut
@ kCGCompositeModeCopy
@ kCGCompositeModePlusLighter
@ kCGCompositeModeSourceAtop
@ kCGCompositeModeSourceIn
struct CGContext * CGContextRef
struct CGColorSpace * CGColorSpaceRef
static qreal component(const QPointF &point, unsigned int i)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr QRgb qRgba(int r, int g, int b, int a)
Definition qrgb.h:33
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
PromiseCallbacks callbacks
Definition qstdweb.cpp:275
#define s2
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned char uchar
Definition qtypes.h:32
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
unsigned char quint8
Definition qtypes.h:46
std::uniform_real_distribution dist(1, 2.5)
[2]
QTextStream out(stdout)
[7]
MyCustomStruct c2
QGraphicsItem * item
myFilter draw(painter, QPoint(0, 0), originalPixmap)
widget render & pixmap
QHostInfo info
[0]