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
qstroker_p.h
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
5#ifndef QSTROKER_P_H
6#define QSTROKER_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtGui/private/qtguiglobal_p.h>
20#include "QtGui/qpainterpath.h"
21#include "private/qdatabuffer_p.h"
22#include "private/qnumeric_p.h"
23
25
26// #define QFIXED_IS_26_6
27
28#if defined QFIXED_IS_26_6
29typedef int qfixed;
30#define qt_real_to_fixed(real) qfixed(real * 64)
31#define qt_int_to_fixed(real) qfixed(int(real) << 6)
32#define qt_fixed_to_real(fixed) qreal(fixed / qreal(64))
33#define qt_fixed_to_int(fixed) int(fixed >> 6)
34struct qfixed2d
35{
36 qfixed x;
37 qfixed y;
38
39 bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
40};
41#elif defined QFIXED_IS_32_32
42typedef qint64 qfixed;
43#define qt_real_to_fixed(real) qfixed(real * double(qint64(1) << 32))
44#define qt_fixed_to_real(fixed) qreal(fixed / double(qint64(1) << 32))
45struct qfixed2d
46{
47 qfixed x;
48 qfixed y;
49
50 bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
51};
52#elif defined QFIXED_IS_16_16
53typedef int qfixed;
54#define qt_real_to_fixed(real) qfixed(real * qreal(1 << 16))
55#define qt_fixed_to_real(fixed) qreal(fixed / qreal(1 << 16))
56struct qfixed2d
57{
58 qfixed x;
59 qfixed y;
60
61 bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
62};
63#else
64typedef qreal qfixed;
65#define qt_real_to_fixed(real) qfixed(real)
66#define qt_fixed_to_real(fixed) fixed
68{
71
72 bool isFinite() { return qIsFinite(x) && qIsFinite(y); }
73 bool operator==(const qfixed2d &other) const { return qFuzzyCompare(x, other.x)
74 && qFuzzyCompare(y, other.y); }
75};
76#endif
77
78#define QT_PATH_KAPPA 0.5522847498
79
80QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength,
81 QPointF *controlPoints, int *point_count);
82
83qreal qt_t_for_arc_angle(qreal angle);
84
85typedef void (*qStrokerMoveToHook)(qfixed x, qfixed y, void *data);
86typedef void (*qStrokerLineToHook)(qfixed x, qfixed y, void *data);
87typedef void (*qStrokerCubicToHook)(qfixed c1x, qfixed c1y,
88 qfixed c2x, qfixed c2y,
89 qfixed ex, qfixed ey,
90 void *data);
91
92// qtransform.cpp
93Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
94
95class Q_GUI_EXPORT QStrokerOps
96{
97public:
98 struct Element {
99 QPainterPath::ElementType type;
100 qfixed x;
101 qfixed y;
102
103 inline bool isMoveTo() const { return type == QPainterPath::MoveToElement; }
104 inline bool isLineTo() const { return type == QPainterPath::LineToElement; }
105 inline bool isCurveTo() const { return type == QPainterPath::CurveToElement; }
106
107 operator qfixed2d () { qfixed2d pt = { x, y }; return pt; }
108 };
109
110 QStrokerOps();
111 virtual ~QStrokerOps();
112
113 void setMoveToHook(qStrokerMoveToHook moveToHook) { m_moveTo = moveToHook; }
114 void setLineToHook(qStrokerLineToHook lineToHook) { m_lineTo = lineToHook; }
115 void setCubicToHook(qStrokerCubicToHook cubicToHook) { m_cubicTo = cubicToHook; }
116
117 virtual void begin(void *customData);
118 virtual void end();
119
120 inline void moveTo(qfixed x, qfixed y);
121 inline void lineTo(qfixed x, qfixed y);
122 inline void cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey);
123
124 void strokePath(const QPainterPath &path, void *data, const QTransform &matrix);
125 void strokePolygon(const QPointF *points, int pointCount, bool implicit_close,
126 void *data, const QTransform &matrix);
127 void strokeEllipse(const QRectF &ellipse, void *data, const QTransform &matrix);
128
129 QRectF clipRect() const { return m_clip_rect; }
130 void setClipRect(const QRectF &clip) { m_clip_rect = clip; }
131
132 void setCurveThresholdFromTransform(const QTransform &transform)
133 {
134 qreal scale;
135 qt_scaleForTransform(transform, &scale);
136 const qreal threshold = scale == 0 ? qreal(0.5) : (qreal(0.5) / scale);
137 // The dashes are flattened with this threshold; an explicitly set curve
138 // threshold puts an upper bound on it.
139 m_dashThreshold =
140 m_curveThresholdExplicitlySet ? qMin(threshold, m_curveThreshold) : threshold;
141 }
142
143 void setCurveThreshold(qfixed threshold)
144 {
145 m_curveThreshold = threshold;
146 m_curveThresholdExplicitlySet = true;
147 }
148 qfixed curveThreshold() const { return m_curveThreshold; }
149 bool curveThresholdExplicitlySet() const { return m_curveThresholdExplicitlySet; }
150
151protected:
152 inline void emitMoveTo(qfixed x, qfixed y);
153 inline void emitLineTo(qfixed x, qfixed y);
154 inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
155
156 virtual void processCurrentSubpath() = 0;
157 QDataBuffer<Element> m_elements;
158
159 QRectF m_clip_rect;
160 qfixed m_curveThreshold;
161 qfixed m_dashThreshold;
162 bool m_curveThresholdExplicitlySet;
163
164 void *m_customData;
165 qStrokerMoveToHook m_moveTo;
166 qStrokerLineToHook m_lineTo;
167 qStrokerCubicToHook m_cubicTo;
168
169};
170
171class Q_GUI_EXPORT QStroker : public QStrokerOps
172{
173public:
174
175 enum LineJoinMode {
176 FlatJoin,
177 SquareJoin,
178 MiterJoin,
179 RoundJoin,
180 RoundCap,
181 SvgMiterJoin
182 };
183
184 QStroker();
185 ~QStroker();
186
187 void setStrokeWidth(qfixed width)
188 {
189 m_strokeWidth = width;
190 m_curveThreshold = qt_real_to_fixed(qBound(0.00025, 1.0 / qt_fixed_to_real(width), 0.25));
191 }
192 qfixed strokeWidth() const { return m_strokeWidth; }
193
194 void setCapStyle(Qt::PenCapStyle capStyle) { m_capStyle = joinModeForCap(capStyle); }
195 Qt::PenCapStyle capStyle() const { return capForJoinMode(m_capStyle); }
196 LineJoinMode capStyleMode() const { return m_capStyle; }
197
198 void setJoinStyle(Qt::PenJoinStyle style) { m_joinStyle = joinModeForJoin(style); }
199 Qt::PenJoinStyle joinStyle() const { return joinForJoinMode(m_joinStyle); }
200 LineJoinMode joinStyleMode() const { return m_joinStyle; }
201
202 void setMiterLimit(qfixed length) { m_miterLimit = length; }
203 qfixed miterLimit() const { return m_miterLimit; }
204
205 void setForceOpen(bool state) { m_forceOpen = state; }
206 bool forceOpen() const { return m_forceOpen; }
207
208 void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
209 inline void emitMoveTo(qfixed x, qfixed y);
210 inline void emitLineTo(qfixed x, qfixed y);
211 inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
212
213protected:
214 static Qt::PenCapStyle capForJoinMode(LineJoinMode mode);
215 static LineJoinMode joinModeForCap(Qt::PenCapStyle);
216
217 static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode);
218 static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle);
219
220 void processCurrentSubpath() override;
221
222 qfixed m_strokeWidth;
223 qfixed m_miterLimit;
224
225 LineJoinMode m_capStyle;
226 LineJoinMode m_joinStyle;
227
228 qfixed m_back1X;
229 qfixed m_back1Y;
230
231 qfixed m_back2X;
232 qfixed m_back2Y;
233
234 bool m_forceOpen;
235};
236
237class Q_GUI_EXPORT QDashStroker : public QStrokerOps
238{
239public:
240 QDashStroker(QStroker *stroker);
241 ~QDashStroker();
242
243 QStroker *stroker() const { return m_stroker; }
244
245 static QList<qfixed> patternForStyle(Qt::PenStyle style);
246 static int repetitionLimit() { return 10000; }
247
248 void setDashPattern(const QList<qfixed> &dashPattern) { m_dashPattern = dashPattern; }
249 QList<qfixed> dashPattern() const { return m_dashPattern; }
250
251 void setDashOffset(qreal offset) { m_dashOffset = offset; }
252 qreal dashOffset() const { return m_dashOffset; }
253
254 void begin(void *data) override;
255 void end() override;
256
257 inline void setStrokeWidth(qreal width) { m_stroke_width = width; }
258 inline void setMiterLimit(qreal limit) { m_miter_limit = limit; }
259
260protected:
261 void processCurrentSubpath() override;
262
263 QStroker *m_stroker;
264 QList<qfixed> m_dashPattern;
265 qreal m_dashOffset;
266
267 qreal m_stroke_width;
268 qreal m_miter_limit;
269};
270
271
272/*******************************************************************************
273 * QStrokerOps inline membmers
274 */
275
276inline void QStrokerOps::emitMoveTo(qfixed x, qfixed y)
277{
278 Q_ASSERT(m_moveTo);
279 m_moveTo(x, y, m_customData);
280}
281
282inline void QStrokerOps::emitLineTo(qfixed x, qfixed y)
283{
284 Q_ASSERT(m_lineTo);
285 m_lineTo(x, y, m_customData);
286}
287
288inline void QStrokerOps::emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey)
289{
290 Q_ASSERT(m_cubicTo);
291 m_cubicTo(c1x, c1y, c2x, c2y, ex, ey, m_customData);
292}
293
294inline void QStrokerOps::moveTo(qfixed x, qfixed y)
295{
296 if (m_elements.size()>1)
297 processCurrentSubpath();
298 m_elements.reset();
299 Element e = { QPainterPath::MoveToElement, x, y };
300 m_elements.add(e);
301}
302
303inline void QStrokerOps::lineTo(qfixed x, qfixed y)
304{
305 Element e = { QPainterPath::LineToElement, x, y };
306 m_elements.add(e);
307}
308
309inline void QStrokerOps::cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey)
310{
311 Element c1 = { QPainterPath::CurveToElement, x1, y1 };
312 Element c2 = { QPainterPath::CurveToDataElement, x2, y2 };
313 Element e = { QPainterPath::CurveToDataElement, ex, ey };
314 m_elements.add(c1);
315 m_elements.add(c2);
316 m_elements.add(e);
317}
318
319/*******************************************************************************
320 * QStroker inline members
321 */
322inline void QStroker::emitMoveTo(qfixed x, qfixed y)
323{
324 m_back2X = m_back1X;
325 m_back2Y = m_back1Y;
326 m_back1X = x;
327 m_back1Y = y;
328 QStrokerOps::emitMoveTo(x, y);
329}
330
331inline void QStroker::emitLineTo(qfixed x, qfixed y)
332{
333 m_back2X = m_back1X;
334 m_back2Y = m_back1Y;
335 m_back1X = x;
336 m_back1Y = y;
337 QStrokerOps::emitLineTo(x, y);
338}
339
340inline void QStroker::emitCubicTo(qfixed c1x, qfixed c1y,
341 qfixed c2x, qfixed c2y,
342 qfixed ex, qfixed ey)
343{
344 if (c2x == ex && c2y == ey) {
345 if (c1x == ex && c1y == ey) {
346 m_back2X = m_back1X;
347 m_back2Y = m_back1Y;
348 } else {
349 m_back2X = c1x;
350 m_back2Y = c1y;
351 }
352 } else {
353 m_back2X = c2x;
354 m_back2Y = c2y;
355 }
356 m_back1X = ex;
357 m_back1Y = ey;
358 QStrokerOps::emitCubicTo(c1x, c1y, c2x, c2y, ex, ey);
359}
360
361/*******************************************************************************
362 * QDashStroker inline members
363 */
364inline void QDashStroker::begin(void *data)
365{
366 if (m_stroker)
367 m_stroker->begin(data);
368 QStrokerOps::begin(data);
369}
370
371inline void QDashStroker::end()
372{
373 QStrokerOps::end();
374 if (m_stroker)
375 m_stroker->end();
376}
377
378QT_END_NAMESPACE
379
380#endif // QSTROKER_P_H
\inmodule QtGui
\inmodule QtGui
Definition qstroker_p.h:96
Combined button and popup list for selecting options.
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal ex, qreal ey, void *data)
static const QPainterPath::ElementType qpaintengineex_ellipse_types[]
static const QPainterPath::ElementType qpaintengineex_rect4_types_32[]
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)
const QVectorPath & qtVectorPathForPath(const QPainterPath &path)
static void qpaintengineex_lineTo(qreal x, qreal y, void *data)
static const QPainterPath::ElementType qpaintengineex_roundedrect_types[]
static const QPainterPath::ElementType qpaintengineex_line_types_16[]
static void qpaintengineex_moveTo(qreal x, qreal y, void *data)
void(* qStrokerCubicToHook)(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey, void *data)
Definition qstroker_p.h:87
void(* qStrokerLineToHook)(qfixed x, qfixed y, void *data)
Definition qstroker_p.h:86
QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength, QPointF *controlPoints, int *point_count)
Definition qstroker.cpp:824
void(* qStrokerMoveToHook)(qfixed x, qfixed y, void *data)
Definition qstroker_p.h:85
qreal qt_t_for_arc_angle(qreal angle)
Definition qstroker.cpp:764
#define qt_fixed_to_real(fixed)
Definition qstroker_p.h:66
#define qt_real_to_fixed(real)
Definition qstroker_p.h:65
QT_BEGIN_NAMESPACE typedef qreal qfixed
Definition qstroker_p.h:64
StrokeHandler(int reserve)
QDataBuffer< QPainterPath::ElementType > types
QDataBuffer< qreal > pts
qfixed x
Definition qstroker_p.h:69
bool operator==(const qfixed2d &other) const
Definition qstroker_p.h:73
bool isFinite()
Definition qstroker_p.h:72
qfixed y
Definition qstroker_p.h:70