Coverage Report

Created: 2025-07-16 07:53

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