Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpaintengine.cpp
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// Qt-Security score:significant reason:default
4#include "qpaintengine.h"
6#include "qpainter_p.h"
7#include "qpolygon.h"
8#include "qbitmap.h"
9#include <qdebug.h>
10#include <qmath.h>
11#include <qguiapplication.h>
12#include <qvarlengtharray.h>
13#include <qpa/qplatformintegration.h>
14#include <qpa/qplatformpixmap.h>
15#include <private/qfontengine_p.h>
16#include <private/qguiapplication_p.h>
17#include <private/qpaintengineex_p.h>
18#include <private/qtextengine_p.h>
19
20#include <memory>
21
23
24/*!
25 \class QTextItem
26 \inmodule QtGui
27
28 \brief The QTextItem class provides all the information required to draw
29 text in a custom paint engine.
30
31 When you reimplement your own paint engine, you must reimplement
32 QPaintEngine::drawTextItem(), a function that takes a QTextItem as
33 one of its arguments.
34*/
35
36/*!
37 \enum QTextItem::RenderFlag
38
39 \value RightToLeft Render the text from right to left.
40 \value Overline Paint a line above the text.
41 \value Underline Paint a line under the text.
42 \value StrikeOut Paint a line through the text.
43 \omitvalue Dummy
44*/
45
46
47/*!
48 \fn qreal QTextItem::descent() const
49
50 Corresponds to the \l{QFontMetrics::descent()}{descent} of the piece of text that is drawn.
51*/
52qreal QTextItem::descent() const
53{
54 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
55 return ti->descent.toReal();
56}
57
58/*!
59 \fn qreal QTextItem::ascent() const
60
61 Corresponds to the \l{QFontMetrics::ascent()}{ascent} of the piece of text that is drawn.
62*/
63qreal QTextItem::ascent() const
64{
65 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
66 return ti->ascent.toReal();
67}
68
69/*!
70 \fn qreal QTextItem::width() const
71
72 Specifies the total width of the text to be drawn.
73*/
74qreal QTextItem::width() const
75{
76 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
77 return ti->width.toReal();
78}
79
80/*!
81 \fn QTextItem::RenderFlags QTextItem::renderFlags() const
82
83 Returns the render flags used.
84*/
85QTextItem::RenderFlags QTextItem::renderFlags() const
86{
87 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
88 return ti->flags;
89}
90
91/*!
92 \fn QString QTextItem::text() const
93
94 Returns the text that should be drawn.
95*/
96QString QTextItem::text() const
97{
98 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
99 return QString(ti->chars, ti->num_chars);
100}
101
102/*!
103 \fn QFont QTextItem::font() const
104
105 Returns the font that should be used to draw the text.
106*/
107QFont QTextItem::font() const
108{
109 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
110 return ti->f ? *ti->f : QGuiApplication::font();
111}
112
113
114/*!
115 \class QPaintEngine
116 \ingroup painting
117 \inmodule QtGui
118
119 \brief The QPaintEngine class provides an abstract definition of how
120 QPainter draws to a given device on a given platform.
121
122 Qt provides several premade implementations of QPaintEngine for the
123 different painter backends we support. The primary paint engine
124 provided is the raster paint engine, which contains a software
125 rasterizer which supports the full feature set on all supported platforms.
126 This is the default for painting on QWidget-based classes in e.g. on Windows,
127 X11 and \macos, it is the backend for painting on QImage and it is
128 used as a fallback for paint engines that do not support a certain
129 capability. In addition we provide QPaintEngine implementations for
130 OpenGL (accessible through QOpenGLWidget) and printing (which allows using
131 QPainter to draw on a QPrinter object).
132
133 If one wants to use QPainter to draw to a different backend,
134 one must subclass QPaintEngine and reimplement all its virtual
135 functions. The QPaintEngine implementation is then made available by
136 subclassing QPaintDevice and reimplementing the virtual function
137 QPaintDevice::paintEngine().
139 QPaintEngine is created and owned by the QPaintDevice that created it.
140
141 \sa QPainter, QPaintDevice::paintEngine(), {Paint System}
142*/
143
144/*!
145 \enum QPaintEngine::PaintEngineFeature
146
147 This enum is used to describe the features or capabilities that the
148 paint engine has. If a feature is not supported by the engine,
149 QPainter will do a best effort to emulate that feature through other
150 means and pass on an alpha blended QImage to the engine with the
151 emulated results. Some features cannot be emulated: AlphaBlend and PorterDuff.
152
153 \value AlphaBlend The engine can alpha blend primitives.
154 \value Antialiasing The engine can use antialiasing to improve the appearance
155 of rendered primitives.
156 \value BlendModes The engine supports blending modes.
157 \value BrushStroke The engine supports drawing strokes that
158 contain brushes as fills, not just solid
159 colors (e.g. a dashed gradient line of
160 width 2).
161 \value ConicalGradientFill The engine supports conical gradient fills.
162 \value ConstantOpacity The engine supports the feature provided by
163 QPainter::setOpacity().
164 \value LinearGradientFill The engine supports linear gradient fills.
165 \value MaskedBrush The engine is capable of rendering brushes that has a
166 texture with an alpha channel or a mask.
167 \value ObjectBoundingModeGradients The engine has native support for gradients
168 with coordinate mode QGradient::ObjectBoundingMode.
169 Otherwise, if QPaintEngine::PatternTransform is
170 supported, object bounding mode gradients are
171 converted to gradients with coordinate mode
172 QGradient::LogicalMode and a brush transform for
173 the coordinate mapping.
174 \value PainterPaths The engine has path support.
175 \value PaintOutsidePaintEvent The engine is capable of painting outside of
176 paint events.
177 \value PatternBrush The engine is capable of rendering brushes with
178 the brush patterns specified in Qt::BrushStyle.
179 \value PatternTransform The engine has support for transforming brush
180 patterns.
181 \value PerspectiveTransform The engine has support for performing perspective
182 transformations on primitives.
183 \value PixmapTransform The engine can transform pixmaps, including
184 rotation and shearing.
185 \value PorterDuff The engine supports Porter-Duff operations
186 \value PrimitiveTransform The engine has support for transforming
187 drawing primitives.
188 \value RadialGradientFill The engine supports radial gradient fills.
189 \value RasterOpModes The engine supports bitwise raster operations.
190 \value AllFeatures All of the above features. This enum value is usually
191 used as a bit mask.
192*/
193
194/*!
195 \enum QPaintEngine::PolygonDrawMode
196
197 \value OddEvenMode The polygon should be drawn using OddEven fill
198 rule.
199
200 \value WindingMode The polygon should be drawn using Winding fill rule.
201
202 \value ConvexMode The polygon is a convex polygon and can be drawn
203 using specialized algorithms where available.
204
205 \value PolylineMode Only the outline of the polygon should be
206 drawn.
207
208*/
209
210/*!
211 \enum QPaintEngine::DirtyFlag
212
213 \value DirtyPen The pen is dirty and needs to be updated.
214
215 \value DirtyBrush The brush is dirty and needs to be updated.
216
217 \value DirtyBrushOrigin The brush origin is dirty and needs to
218 updated.
219
220 \value DirtyFont The font is dirty and needs to be updated.
221
222 \value DirtyBackground The background is dirty and needs to be
223 updated.
224
225 \value DirtyBackgroundMode The background mode is dirty and needs
226 to be updated.
227
228 \value DirtyTransform The transform is dirty and needs to be
229 updated.
230
231 \value DirtyClipRegion The clip region is dirty and needs to be
232 updated.
233
234 \value DirtyClipPath The clip path is dirty and needs to be
235 updated.
236
237 \value DirtyHints The render hints is dirty and needs to be
238 updated.
239
240 \value DirtyCompositionMode The composition mode is dirty and
241 needs to be updated.
242
243 \value DirtyClipEnabled Whether clipping is enabled or not is
244 dirty and needs to be updated.
245
246 \value DirtyOpacity The constant opacity has changed and needs to
247 be updated as part of the state change in
248 QPaintEngine::updateState().
249
250 \value AllDirty Convenience enum used internally.
251
252 These types are used by QPainter to trigger lazy updates of the
253 various states in the QPaintEngine using
254 QPaintEngine::updateState().
255
256 A paint engine must update every dirty state.
257*/
258
259/*!
260 \fn void QPaintEngine::syncState()
261
262 \internal
263
264 Updates all dirty states in this engine. This function should ONLY
265 be used when drawing with native handles directly and immediate sync
266 from QPainters state to the native state is required.
267*/
268void QPaintEngine::syncState()
269{
270 Q_ASSERT(state);
271 updateState(*state);
272
273 if (isExtended())
274 static_cast<QPaintEngineEx *>(this)->sync();
275}
276
278struct QT_Point {
279 int x;
280 int y;
281};
283
284/*!
285 \fn void QPaintEngine::drawPolygon(const QPointF *points, int pointCount,
286 PolygonDrawMode mode)
287
288 Reimplement this virtual function to draw the polygon defined
289 by the \a pointCount first points in \a points, using mode \a
290 mode.
291
292 \note At least one of the drawPolygon() functions must be reimplemented.
293*/
294void QPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
295{
296 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
297 "At least one drawPolygon function must be implemented");
298 qt_polygon_recursion = this;
299 Q_ASSERT(sizeof(QT_Point) == sizeof(QPoint));
300 QVarLengthArray<QT_Point> p(pointCount);
301 for (int i = 0; i < pointCount; ++i) {
302 p[i].x = qRound(points[i].x());
303 p[i].y = qRound(points[i].y());
304 }
305 drawPolygon((QPoint *)p.data(), pointCount, mode);
306 qt_polygon_recursion = nullptr;
307}
308
309struct QT_PointF {
312};
314
315/*!
316 \overload
317
318 Reimplement this virtual function to draw the polygon defined by the
319 \a pointCount first points in \a points, using mode \a mode.
320
321 \note At least one of the drawPolygon() functions must be reimplemented.
322*/
323void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
324{
325 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
326 "At least one drawPolygon function must be implemented");
327 qt_polygon_recursion = this;
328 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
329 QVarLengthArray<QT_PointF> p(pointCount);
330 for (int i=0; i<pointCount; ++i) {
331 p[i].x = points[i].x();
332 p[i].y = points[i].y();
333 }
334 drawPolygon((QPointF *)p.data(), pointCount, mode);
335 qt_polygon_recursion = nullptr;
336}
337
338/*!
339 \enum QPaintEngine::Type
340
341 \value X11
342 \value Windows
343 \value MacPrinter
344 \value CoreGraphics \macos's Quartz2D (CoreGraphics)
345 \value QuickDraw \macos's QuickDraw
346 \value QWindowSystem Qt for Embedded Linux
347 \value OpenGL
348 \value Picture QPicture format
349 \value SVG Scalable Vector Graphics XML format
350 \value Raster
351 \value Direct3D Windows only, Direct3D based engine
352 \value Pdf Portable Document Format
353 \value OpenVG
354 \value User First user type ID
355 \value MaxUser Last user type ID
356 \value OpenGL2
357 \value PaintBuffer
358 \value Blitter
359 \value Direct2D Windows only, Direct2D based engine
360*/
361
362/*!
363 \fn bool QPaintEngine::isActive() const
364
365 Returns \c true if the paint engine is actively drawing; otherwise
366 returns \c false.
367
368 \sa setActive()
369*/
370
371/*!
372 \fn void QPaintEngine::setActive(bool state)
373
374 Sets the active state of the paint engine to \a state.
375
376 \sa isActive()
377*/
378
379/*!
380 \fn bool QPaintEngine::begin(QPaintDevice *pdev)
381
382 Reimplement this function to initialise your paint engine when
383 painting is to start on the paint device \a pdev. Return true if
384 the initialization was successful; otherwise return false.
385
386 \sa end(), isActive()
387*/
388
389/*!
390 \fn bool QPaintEngine::end()
391
392 Reimplement this function to finish painting on the current paint
393 device. Return true if painting was finished successfully;
394 otherwise return false.
395
396 \sa begin(), isActive()
397*/
398
399
400/*!
401 Draws the first \a pointCount points in the buffer \a points
402*/
403void QPaintEngine::drawPoints(const QPointF *points, int pointCount)
404{
405 QPainter *p = painter();
406 if (!p)
407 return;
408
409 qreal penWidth = p->pen().widthF();
410 if (penWidth == 0)
411 penWidth = 1;
412
413 bool ellipses = p->pen().capStyle() == Qt::RoundCap;
414
415 p->save();
416
417 QTransform transform;
418 if (p->pen().isCosmetic()) {
419 transform = p->transform();
420 p->setTransform(QTransform());
421 }
422
423 p->setBrush(p->pen().brush());
424 p->setPen(Qt::NoPen);
425
426 for (int i=0; i<pointCount; ++i) {
427 QPointF pos = transform.map(points[i]);
428 QRectF rect(pos.x() - penWidth / 2, pos.y() - penWidth / 2, penWidth, penWidth);
429
430 if (ellipses)
431 p->drawEllipse(rect);
432 else
433 p->drawRect(rect);
434 }
435
436 p->restore();
437}
438
439
440/*!
441 Draws the first \a pointCount points in the buffer \a points
442
443 The default implementation converts the first \a pointCount QPoints in \a points
444 to QPointFs and calls the floating point version of drawPoints.
445
446*/
447void QPaintEngine::drawPoints(const QPoint *points, int pointCount)
448{
449 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
450 QT_PointF fp[256];
451 while (pointCount) {
452 int i = 0;
453 while (i < pointCount && i < 256) {
454 fp[i].x = points[i].x();
455 fp[i].y = points[i].y();
456 ++i;
457 }
458 drawPoints((QPointF *)(void *)fp, i);
459 points += i;
460 pointCount -= i;
461 }
462}
463
464/*!
465 \fn void QPaintEngine::drawEllipse(const QRectF &rect)
466
467 Reimplement this function to draw the largest ellipse that can be
468 contained within rectangle \a rect.
469
470 The default implementation calls drawPolygon().
471*/
472void QPaintEngine::drawEllipse(const QRectF &rect)
473{
474 QPainterPath path;
475 path.addEllipse(rect);
476 if (hasFeature(PainterPaths)) {
477 drawPath(path);
478 } else {
479 QPolygonF polygon = path.toFillPolygon();
480 drawPolygon(polygon.data(), polygon.size(), ConvexMode);
481 }
482}
483
484/*!
485 \overload
486
487 The default implementation of this function calls the floating
488 point version of this function
489*/
490void QPaintEngine::drawEllipse(const QRect &rect)
491{
492 drawEllipse(QRectF(rect));
493}
494
495/*!
496 \fn void QPaintEngine::drawPixmap(const QRectF &r, const QPixmap
497 &pm, const QRectF &sr)
498
499 Reimplement this function to draw the part of the \a pm
500 specified by the \a sr rectangle in the given \a r.
501*/
502
503
504void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
505{
506 QPainter p(tile);
507 p.drawPixmap(0, 0, pixmap);
508 int x = pixmap.width();
509 while (x < tile->width()) {
510 p.drawPixmap(x, 0, *tile, 0, 0, x, pixmap.height());
511 x *= 2;
512 }
513 int y = pixmap.height();
514 while (y < tile->height()) {
515 p.drawPixmap(0, y, *tile, 0, 0, tile->width(), y);
516 y *= 2;
517 }
518}
519
520Q_GUI_EXPORT void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
521 const QPixmap &pixmap, qreal xOffset, qreal yOffset)
522{
523 qreal yPos, xPos, drawH, drawW, yOff, xOff;
524 yPos = y;
525 yOff = yOffset;
526 while(yPos < y + h) {
527 drawH = pixmap.height() - yOff; // Cropping first row
528 if (yPos + drawH > y + h) // Cropping last row
529 drawH = y + h - yPos;
530 xPos = x;
531 xOff = xOffset;
532 while(xPos < x + w) {
533 drawW = pixmap.width() - xOff; // Cropping first column
534 if (xPos + drawW > x + w) // Cropping last column
535 drawW = x + w - xPos;
536 if (drawW > 0 && drawH > 0)
537 gc->drawPixmap(QRectF(xPos, yPos, drawW, drawH), pixmap, QRectF(xOff, yOff, drawW, drawH));
538 xPos += drawW;
539 xOff = 0;
540 }
541 yPos += drawH;
542 yOff = 0;
543 }
544}
545
546
547/*!
548 Reimplement this function to draw the \a pixmap in the given \a
549 rect, starting at the given \a p. The pixmap will be
550 drawn repeatedly until the \a rect is filled.
551*/
552void QPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
553{
554 int sw = pixmap.width();
555 int sh = pixmap.height();
556
557 if (sw*sh < 8192 && sw*sh < 16*rect.width()*rect.height()) {
558 int tw = sw, th = sh;
559 while (tw*th < 32678 && tw < rect.width()/2)
560 tw *= 2;
561 while (tw*th < 32678 && th < rect.height()/2)
562 th *= 2;
563 QPixmap tile;
564 if (pixmap.depth() == 1) {
565 tile = QBitmap(tw, th);
566 } else {
567 tile = QPixmap(tw, th);
568 if (pixmap.hasAlphaChannel())
569 tile.fill(Qt::transparent);
570 }
571 qt_fill_tile(&tile, pixmap);
572 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y());
573 } else {
574 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
575 }
576}
577
578/*!
579 \fn void QPaintEngine::drawImage(const QRectF &rectangle, const QImage
580 &image, const QRectF &sr, Qt::ImageConversionFlags flags)
581
582 Reimplement this function to draw the part of the \a image
583 specified by the \a sr rectangle in the given \a rectangle using
584 the given conversion flags \a flags, to convert it to a pixmap.
585*/
586
587void QPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
588 Qt::ImageConversionFlags flags)
589{
590 QRectF baseSize(0, 0, image.width(), image.height());
591 QImage im = image;
592 if (baseSize != sr)
593 im = im.copy(qFloor(sr.x()), qFloor(sr.y()),
594 qCeil(sr.width()), qCeil(sr.height()));
595 QPixmap pm = QPixmap::fromImage(im, flags);
596 drawPixmap(r, pm, QRectF(QPointF(0, 0), pm.size()));
597}
598
599/*!
600 \fn Type QPaintEngine::type() const
601
602 Reimplement this function to return the paint engine \l{Type}.
603*/
604
605/*!
606 \fn void QPaintEngine::fix_neg_rect(int *x, int *y, int *w, int *h);
607
608 \internal
609*/
610
611/*!
612 \fn bool QPaintEngine::testDirty(DirtyFlags df)
613
614 \internal
615*/
616
617/*!
618 \fn void QPaintEngine::clearDirty(DirtyFlags df)
619
620 \internal
621*/
622
623/*!
624 \fn void QPaintEngine::setDirty(DirtyFlags df)
625
626 \internal
627*/
628
629/*!
630 \fn bool QPaintEngine::hasFeature(PaintEngineFeatures feature) const
631
632 Returns \c true if the paint engine supports the specified \a
633 feature; otherwise returns \c false.
634*/
635
636/*!
637 \fn bool QPaintEngine::isExtended() const
638
639 \internal
640
641 Returns \c true if the paint engine is a QPaintEngineEx derivative.
642*/
643
644/*!
645 \fn void QPaintEngine::updateState(const QPaintEngineState &state)
646
647 Reimplement this function to update the state of a paint engine.
648
649 When implemented, this function is responsible for checking the
650 paint engine's current \a state and update the properties that are
651 changed. Use the QPaintEngineState::state() function to find out
652 which properties that must be updated, then use the corresponding
653 \l {GetFunction}{get function} to retrieve the current values for
654 the given properties.
655
656 \sa QPaintEngineState
657*/
658
659/*!
660 Creates a paint engine with the featureset specified by \a caps.
661*/
662
663QPaintEngine::QPaintEngine(PaintEngineFeatures caps)
664 : state(nullptr),
665 gccaps(caps),
666 active(0),
667 selfDestruct(false),
668 extended(false),
669 d_ptr(new QPaintEnginePrivate)
670{
671 d_ptr->q_ptr = this;
672}
673
674/*!
675 \internal
676*/
677
678QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
679 : state(nullptr),
680 gccaps(caps),
681 active(0),
682 selfDestruct(false),
683 extended(false),
684 d_ptr(&dptr)
685{
686 d_ptr->q_ptr = this;
687}
688
689/*!
690 Destroys the paint engine.
691*/
692QPaintEngine::~QPaintEngine()
693{
694}
695
696/*!
697 Returns the paint engine's painter.
698*/
699QPainter *QPaintEngine::painter() const
700{
701 return state ? state->painter() : nullptr;
702}
703
704/*!
705 The default implementation ignores the \a path and does nothing.
706*/
707
708void QPaintEngine::drawPath(const QPainterPath &)
709{
710 if (hasFeature(PainterPaths)) {
711 qWarning("QPaintEngine::drawPath: Must be implemented when feature PainterPaths is set");
712 }
713}
714
715/*!
716 This function draws the text item \a textItem at position \a p. The
717 default implementation of this function converts the text to a
718 QPainterPath and paints the resulting path.
719*/
720
721void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
722{
723 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
724 if (ti.glyphs.numGlyphs == 0)
725 return;
726
727 if (ti.fontEngine->glyphFormat == QFontEngine::Format_ARGB) {
728 QVarLengthArray<QFixedPoint> positions;
729 QVarLengthArray<glyph_t> glyphs;
730 QTransform matrix = QTransform::fromTranslate(p.x(), p.y());
731 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
732 painter()->save();
733 painter()->setRenderHint(QPainter::SmoothPixmapTransform,
734 bool((painter()->renderHints() & QPainter::TextAntialiasing)
735 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
736 const QColor color = painter()->pen().color();
737 for (qsizetype i = 0; i < glyphs.size(); ++i) {
738 QImage glyph
739 = ti.fontEngine->bitmapForGlyph(glyphs[i], QFixedPoint(), QTransform(), color);
740 if (glyph.isNull())
741 continue;
742 // The glyph positions are on the baseline; place the image using
743 // the glyph's own bearings.
744 const glyph_metrics_t metrics = ti.fontEngine->alphaMapBoundingBox(
745 glyphs[i], QFixedPoint(), QTransform(), QFontEngine::Format_ARGB);
746 painter()->drawImage(QPointF(positions[i].x.toReal() + metrics.x.toReal(),
747 positions[i].y.toReal() + metrics.y.toReal()),
748 glyph);
749 }
750 painter()->restore();
751 return;
752 }
753
754 QPainterPath path;
755 path.setFillRule(Qt::WindingFill);
756 ti.fontEngine->addOutlineToPath(0, 0, ti.glyphs, &path, ti.flags);
757 if (!path.isEmpty()) {
758 painter()->save();
759 painter()->setRenderHint(QPainter::Antialiasing,
760 bool((painter()->renderHints() & QPainter::TextAntialiasing)
761 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
762 painter()->translate(p.x(), p.y());
763 painter()->fillPath(path, painter()->pen().brush());
764 painter()->restore();
765 }
766}
767
768/*!
769 The default implementation splits the list of lines in \a lines
770 into \a lineCount separate calls to drawPath() or drawPolygon()
771 depending on the feature set of the paint engine.
772*/
773void QPaintEngine::drawLines(const QLineF *lines, int lineCount)
774{
775 for (int i=0; i<lineCount; ++i) {
776 QPointF pts[2] = { lines[i].p1(), lines[i].p2() };
777
778 if (pts[0] == pts[1]) {
779 if (state->pen().capStyle() != Qt::FlatCap)
780 drawPoints(pts, 1);
781 continue;
782 }
783
784 drawPolygon(pts, 2, PolylineMode);
785 }
786}
787
788/*!
789 \overload
790
791 The default implementation converts the first \a lineCount lines
792 in \a lines to a QLineF and calls the floating point version of
793 this function.
794*/
795void QPaintEngine::drawLines(const QLine *lines, int lineCount)
796{
797 struct PointF {
798 qreal x;
799 qreal y;
800 };
801 struct LineF {
802 PointF p1;
803 PointF p2;
804 };
805 Q_ASSERT(sizeof(PointF) == sizeof(QPointF));
806 Q_ASSERT(sizeof(LineF) == sizeof(QLineF));
807 LineF fl[256];
808 while (lineCount) {
809 int i = 0;
810 while (i < lineCount && i < 256) {
811 fl[i].p1.x = lines[i].x1();
812 fl[i].p1.y = lines[i].y1();
813 fl[i].p2.x = lines[i].x2();
814 fl[i].p2.y = lines[i].y2();
815 ++i;
816 }
817 drawLines((QLineF *)(void *)fl, i);
818 lines += i;
819 lineCount -= i;
820 }
821}
822
823
824/*!
825 \overload
826
827 The default implementation converts the first \a rectCount
828 rectangles in the buffer \a rects to a QRectF and calls the
829 floating point version of this function.
830*/
831void QPaintEngine::drawRects(const QRect *rects, int rectCount)
832{
833 struct RectF {
834 qreal x;
835 qreal y;
836 qreal w;
837 qreal h;
838 };
839 Q_ASSERT(sizeof(RectF) == sizeof(QRectF));
840 RectF fr[256];
841 while (rectCount) {
842 int i = 0;
843 while (i < rectCount && i < 256) {
844 fr[i].x = rects[i].x();
845 fr[i].y = rects[i].y();
846 fr[i].w = rects[i].width();
847 fr[i].h = rects[i].height();
848 ++i;
849 }
850 drawRects((QRectF *)(void *)fr, i);
851 rects += i;
852 rectCount -= i;
853 }
854}
855
856/*!
857 Draws the first \a rectCount rectangles in the buffer \a
858 rects. The default implementation of this function calls drawPath()
859 or drawPolygon() depending on the feature set of the paint engine.
860*/
861void QPaintEngine::drawRects(const QRectF *rects, int rectCount)
862{
863 if (hasFeature(PainterPaths) &&
864 !state->penNeedsResolving() &&
865 !state->brushNeedsResolving()) {
866 for (int i=0; i<rectCount; ++i) {
867 QPainterPath path;
868 path.addRect(rects[i]);
869 if (path.isEmpty())
870 continue;
871 drawPath(path);
872 }
873 } else {
874 for (int i=0; i<rectCount; ++i) {
875 QRectF rf = rects[i];
876 QPointF pts[4] = { QPointF(rf.x(), rf.y()),
877 QPointF(rf.x() + rf.width(), rf.y()),
878 QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
879 QPointF(rf.x(), rf.y() + rf.height()) };
880 drawPolygon(pts, 4, ConvexMode);
881 }
882 }
883}
884
885/*!
886 \internal
887 Sets the paintdevice that this engine operates on to \a device
888*/
889void QPaintEngine::setPaintDevice(QPaintDevice *device)
890{
891 d_func()->pdev = device;
892}
893
894/*!
895 Returns the device that this engine is painting on, if painting is
896 active; otherwise returns \nullptr.
897*/
898QPaintDevice *QPaintEngine::paintDevice() const
899{
900 return d_func()->pdev;
901}
902
903
904/*!
905 \internal
906
907 Returns the offset from the painters origo to the engines
908 origo. This value is used by QPainter for engines who have
909 internal double buffering.
910
911 This function only makes sense when the engine is active.
912*/
913QPoint QPaintEngine::coordinateOffset() const
914{
915 return QPoint();
916}
917
918/*!
919 \internal
920
921 Sets the system clip for this engine. The system clip defines the
922 basis area that the engine has to draw in. All clips that are
923 set will be an intersection with the system clip.
924
925 Reset the systemclip to no clip by setting an empty region.
926*/
927void QPaintEngine::setSystemClip(const QRegion &region)
928{
929 Q_D(QPaintEngine);
930 d->baseSystemClip = region;
931 // Be backward compatible and only call d->systemStateChanged()
932 // if we currently have a system transform/viewport set.
933 d->updateSystemClip();
934 if (d->hasSystemTransform || d->hasSystemViewport) {
935 d->systemStateChanged();
936 }
937}
938
939/*!
940 \internal
941
942 Returns the system clip. The system clip is read only while the
943 painter is active. An empty region indicates that system clip
944 is not in use.
945*/
946
947QRegion QPaintEngine::systemClip() const
948{
949 return d_func()->systemClip;
950}
951
952/*!
953 \internal
954
955 Sets the target rect for drawing within the backing store. This
956 function should ONLY be used by the backing store.
957*/
958void QPaintEngine::setSystemRect(const QRect &rect)
959{
960 if (isActive()) {
961 qWarning("QPaintEngine::setSystemRect: Should not be changed while engine is active");
962 return;
963 }
964 d_func()->systemRect = rect;
965}
966
967/*!
968 \internal
969
970 Retrieves the rect for drawing within the backing store. This
971 function should ONLY be used by the backing store.
972 */
973QRect QPaintEngine::systemRect() const
974{
975 return d_func()->systemRect;
976}
977
978/*!
979 \internal
980
981 Creates a QPixmap optimized for this paint engine and device.
982*/
983QPixmap QPaintEngine::createPixmap(QSize size)
984{
985 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
986 qWarning("QPaintEngine::createPixmap: QPixmap cannot be created without a QGuiApplication");
987 return QPixmap();
988 }
989
990 std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
991 data->resize(size.width(), size.height());
992 return QPixmap(data.release());
993}
994
995/*!
996 \internal
997
998 Creates a QPixmap optimized for this paint engine and device.
999*/
1000QPixmap QPaintEngine::createPixmapFromImage(QImage image, Qt::ImageConversionFlags flags)
1001{
1002 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
1003 qWarning("QPaintEngine::createPixmapFromImage: QPixmap cannot be created without a QGuiApplication");
1004 return QPixmap();
1005 }
1006
1007 std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
1008 if (image.isDetached())
1009 data->fromImageInPlace(image, flags);
1010 else
1011 data->fromImage(image, flags);
1012 return QPixmap(data.release());
1013}
1014
1015QPaintEnginePrivate::~QPaintEnginePrivate()
1016{
1017}
1018
1019void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
1020{
1021 if (!ti.glyphs.numGlyphs)
1022 return;
1023
1024 // any fixes here should probably also be done in QFontEngineBox::draw
1025 const int size = qRound(ti.fontEngine->ascent());
1026 QVarLengthArray<QFixedPoint> positions;
1027 QVarLengthArray<glyph_t> glyphs;
1028 QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size);
1029 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
1030 if (glyphs.size() == 0)
1031 return;
1032
1033 QSize s(size - 3, size - 3);
1034
1035 QPainter *painter = q_func()->state->painter();
1036 painter->save();
1037 painter->setBrush(Qt::NoBrush);
1038 QPen pen = painter->pen();
1039 pen.setWidthF(ti.fontEngine->lineThickness().toReal());
1040 painter->setPen(pen);
1041 for (int k = 0; k < positions.size(); k++)
1042 painter->drawRect(QRectF(positions[k].toPointF(), s));
1043 painter->restore();
1044}
1045
1046QT_END_NAMESPACE
friend class QPainter
friend class QPaintEngine
Definition qpainter.h:438
Combined button and popup list for selecting options.
Q_DECLARE_TYPEINFO(QT_PointF, Q_PRIMITIVE_TYPE)
Q_GUI_EXPORT void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h, const QPixmap &pixmap, qreal xOffset, qreal yOffset)
void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
Q_DECLARE_TYPEINFO(QT_Point, Q_PRIMITIVE_TYPE)
static QPaintEngine * qt_polygon_recursion