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#ifndef QPAINTER_P_H
5#define QPAINTER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qvarlengtharray.h>
19#include <QtGui/private/qtguiglobal_p.h>
20#include "QtGui/qbrush.h"
21#include "QtGui/qcolorspace.h"
22#include "QtGui/qcolortransform.h"
23#include "QtGui/qfont.h"
24#include "QtGui/qpen.h"
25#include "QtGui/qregion.h"
26#include "QtGui/qpainter.h"
27#include "QtGui/qpainterpath.h"
28#include "QtGui/qpaintengine.h"
29
30#include <private/qpen_p.h>
31
32#include <memory>
33#include <stack>
34
35QT_BEGIN_NAMESPACE
36
37class QPaintEngine;
38class QEmulationPaintEngine;
39class QPaintEngineEx;
40struct QFixedPoint;
41
42struct QTLWExtra;
43
44struct DataPtrContainer {
45 void *ptr;
46};
47
48inline const void *data_ptr(const QTransform &t) { return (const DataPtrContainer *) &t; }
49inline bool qtransform_fast_equals(const QTransform &a, const QTransform &b) { return data_ptr(t: a) == data_ptr(t: b); }
50
51// QPen inline functions...
52inline QPen::DataPtr &data_ptr(const QPen &p) { return const_cast<QPen &>(p).data_ptr(); }
53inline bool qpen_fast_equals(const QPen &a, const QPen &b) { return data_ptr(p: a) == data_ptr(p: b); }
54inline QBrush qpen_brush(const QPen &p) { return data_ptr(p)->brush; }
55inline qreal qpen_widthf(const QPen &p) { return data_ptr(p)->width; }
56inline Qt::PenStyle qpen_style(const QPen &p) { return data_ptr(p)->style; }
57inline Qt::PenCapStyle qpen_capStyle(const QPen &p) { return data_ptr(p)->capStyle; }
58inline Qt::PenJoinStyle qpen_joinStyle(const QPen &p) { return data_ptr(p)->joinStyle; }
59
60// QBrush inline functions...
61inline QBrush::DataPtr &data_ptr(const QBrush &p) { return const_cast<QBrush &>(p).data_ptr(); }
62inline bool qbrush_fast_equals(const QBrush &a, const QBrush &b) { return data_ptr(p: a) == data_ptr(p: b); }
63inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(p: b)->style; }
64inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(p: b)->color; }
65inline bool qbrush_has_transform(const QBrush &b) { return data_ptr(p: b)->transform.type() > QTransform::TxNone; }
66
67class QPainterClipInfo
68{
69public:
70 QPainterClipInfo() { } // for QList, don't use
71 enum ClipType { RegionClip, PathClip, RectClip, RectFClip };
72
73 QPainterClipInfo(const QPainterPath &p, Qt::ClipOperation op, const QTransform &m) :
74 clipType(PathClip), matrix(m), operation(op), path(p) { }
75
76 QPainterClipInfo(const QRegion &r, Qt::ClipOperation op, const QTransform &m) :
77 clipType(RegionClip), matrix(m), operation(op), region(r) { }
78
79 QPainterClipInfo(const QRect &r, Qt::ClipOperation op, const QTransform &m) :
80 clipType(RectClip), matrix(m), operation(op), rect(r) { }
81
82 QPainterClipInfo(const QRectF &r, Qt::ClipOperation op, const QTransform &m) :
83 clipType(RectFClip), matrix(m), operation(op), rectf(r) { }
84
85 ClipType clipType;
86 QTransform matrix;
87 Qt::ClipOperation operation;
88 QPainterPath path;
89 QRegion region;
90 QRect rect;
91 QRectF rectf;
92
93 // ###
94// union {
95// QRegionData *d;
96// QPainterPathPrivate *pathData;
97
98// struct {
99// int x, y, w, h;
100// } rectData;
101// struct {
102// qreal x, y, w, h;
103// } rectFData;
104// };
105
106};
107
108Q_DECLARE_TYPEINFO(QPainterClipInfo, Q_RELOCATABLE_TYPE);
109
110class Q_GUI_EXPORT QPainterState : public QPaintEngineState
111{
112public:
113 QPainterState();
114 QPainterState(const QPainterState *s);
115 virtual ~QPainterState();
116 void init(QPainter *p);
117
118 QPointF brushOrigin;
119 QFont font;
120 QFont deviceFont;
121 QPen pen;
122 QBrush brush;
123 QBrush bgBrush = Qt::white; // background brush
124 QRegion clipRegion;
125 QPainterPath clipPath;
126 Qt::ClipOperation clipOperation = Qt::NoClip;
127 QPainter::RenderHints renderHints;
128 QList<QPainterClipInfo> clipInfo; // ### Make me smaller and faster to copy around...
129 QTransform worldMatrix; // World transformation matrix, not window and viewport
130 QTransform matrix; // Complete transformation matrix,
131 QTransform redirectionMatrix;
132 int wx = 0, wy = 0, ww = 0, wh = 0; // window rectangle
133 int vx = 0, vy = 0, vw = 0, vh = 0; // viewport rectangle
134 qreal opacity = 1;
135
136 uint WxF:1; // World transformation
137 uint VxF:1; // View transformation
138 uint clipEnabled:1;
139
140 Qt::BGMode bgMode = Qt::TransparentMode;
141 QPainter *painter = nullptr;
142 Qt::LayoutDirection layoutDirection;
143 QPainter::CompositionMode composition_mode = QPainter::CompositionMode_SourceOver;
144 uint emulationSpecifier = 0;
145 uint changeFlags = 0;
146};
147
148struct QPainterDummyState
149{
150 QFont font;
151 QPen pen;
152 QBrush brush;
153 QTransform transform;
154};
155
156class QRawFont;
157class QPainterPrivate
158{
159 Q_DECLARE_PUBLIC(QPainter)
160public:
161 explicit QPainterPrivate(QPainter *painter);
162 ~QPainterPrivate();
163
164 QPainter *q_ptr;
165 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
166 // redirections within the same paintEvent(), which should be enough
167 // in 99% of all cases). E.g: A renders B which renders C which renders D.
168 static constexpr qsizetype NDPtrs = 4;
169 QVarLengthArray<QPainterPrivate*, NDPtrs> d_ptrs;
170
171 std::unique_ptr<QPainterState> state;
172 template <typename T, std::size_t N = 8>
173 struct SmallStack : std::stack<T, QVarLengthArray<T, N>> {
174 void clear() { this->c.clear(); }
175 };
176 SmallStack<std::unique_ptr<QPainterState>> savedStates;
177
178 mutable std::unique_ptr<QPainterDummyState> dummyState;
179
180 QTransform invMatrix;
181 uint txinv:1;
182 uint inDestructor : 1;
183 uint refcount = 1;
184
185 enum DrawOperation { StrokeDraw = 0x1,
186 FillDraw = 0x2,
187 StrokeAndFillDraw = 0x3
188 };
189
190 QPainterDummyState *fakeState() const {
191 if (!dummyState)
192 dummyState = std::make_unique<QPainterDummyState>();
193 return dummyState.get();
194 }
195
196 void updateEmulationSpecifier(QPainterState *s);
197 void updateStateImpl(QPainterState *state);
198 void updateState(QPainterState *state);
199 void updateState(std::unique_ptr<QPainterState> &state) { updateState(state: state.get()); }
200
201 void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw);
202 void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
203 void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
204 void drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine);
205
206#if !defined(QT_NO_RAWFONT)
207 void drawGlyphs(const QPointF &decorationPosition, const quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount,
208 QFontEngine *fontEngine, bool overline = false, bool underline = false,
209 bool strikeOut = false);
210#endif
211
212 void updateMatrix();
213 void updateInvMatrix();
214
215 void checkEmulation();
216
217 static QPainterPrivate *get(QPainter *painter)
218 {
219 return painter->d_ptr.get();
220 }
221
222 QTransform viewTransform() const;
223 qreal effectiveDevicePixelRatio() const;
224 QTransform hidpiScaleTransform() const;
225 static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
226 void detachPainterPrivate(QPainter *q);
227 void initFrom(const QPaintDevice *device);
228
229 QPaintDevice *device = nullptr;
230 QPaintDevice *original_device = nullptr;
231 QPaintDevice *helper_device = nullptr;
232
233 struct QPaintEngineDestructor {
234 void operator()(QPaintEngine *pe) const noexcept
235 {
236 if (pe && pe->autoDestruct())
237 delete pe;
238 }
239 };
240 std::unique_ptr<QPaintEngine, QPaintEngineDestructor> engine;
241
242 std::unique_ptr<QEmulationPaintEngine> emulationEngine;
243 QPaintEngineEx *extended = nullptr;
244 QBrush colorBrush; // for fill with solid color
245};
246
247Q_GUI_EXPORT void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation);
248
249QString qt_generate_brush_key(const QBrush &brush);
250
251
252QT_END_NAMESPACE
253
254#endif // QPAINTER_P_H
255

source code of qtbase/src/gui/painting/qpainter_p.h