Coverage Report

Created: 2025-11-16 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/painting/qstroker_p.h
Line
Count
Source
1
/****************************************************************************
2
**
3
** Copyright (C) 2016 The Qt Company Ltd.
4
** Contact: https://www.qt.io/licensing/
5
**
6
** This file is part of the QtGui module of the Qt Toolkit.
7
**
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and The Qt Company. For licensing terms
14
** and conditions see https://www.qt.io/terms-conditions. For further
15
** information use the contact form at https://www.qt.io/contact-us.
16
**
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 3 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL3 included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 3 requirements
23
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24
**
25
** GNU General Public License Usage
26
** Alternatively, this file may be used under the terms of the GNU
27
** General Public License version 2.0 or (at your option) the GNU General
28
** Public license version 3 or any later version approved by the KDE Free
29
** Qt Foundation. The licenses are as published by the Free Software
30
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31
** included in the packaging of this file. Please review the following
32
** information to ensure the GNU General Public License requirements will
33
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34
** https://www.gnu.org/licenses/gpl-3.0.html.
35
**
36
** $QT_END_LICENSE$
37
**
38
****************************************************************************/
39
40
#ifndef QSTROKER_P_H
41
#define QSTROKER_P_H
42
43
//
44
//  W A R N I N G
45
//  -------------
46
//
47
// This file is not part of the Qt API.  It exists purely as an
48
// implementation detail.  This header file may change from version to
49
// version without notice, or even be removed.
50
//
51
// We mean it.
52
//
53
54
#include <QtGui/private/qtguiglobal_p.h>
55
#include "QtGui/qpainterpath.h"
56
#include "private/qdatabuffer_p.h"
57
#include "private/qnumeric_p.h"
58
59
QT_BEGIN_NAMESPACE
60
61
// #define QFIXED_IS_26_6
62
63
#if defined QFIXED_IS_26_6
64
typedef int qfixed;
65
#define qt_real_to_fixed(real) qfixed(real * 64)
66
#define qt_int_to_fixed(real) qfixed(int(real) << 6)
67
#define qt_fixed_to_real(fixed) qreal(fixed / qreal(64))
68
#define qt_fixed_to_int(fixed) int(fixed >> 6)
69
struct qfixed2d
70
{
71
    qfixed x;
72
    qfixed y;
73
74
    bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
75
};
76
#elif defined QFIXED_IS_32_32
77
typedef qint64 qfixed;
78
#define qt_real_to_fixed(real) qfixed(real * double(qint64(1) << 32))
79
#define qt_fixed_to_real(fixed) qreal(fixed / double(qint64(1) << 32))
80
struct qfixed2d
81
{
82
    qfixed x;
83
    qfixed y;
84
85
    bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
86
};
87
#elif defined QFIXED_IS_16_16
88
typedef int qfixed;
89
#define qt_real_to_fixed(real) qfixed(real * qreal(1 << 16))
90
#define qt_fixed_to_real(fixed) qreal(fixed / qreal(1 << 16))
91
struct qfixed2d
92
{
93
    qfixed x;
94
    qfixed y;
95
96
    bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
97
};
98
#else
99
typedef qreal qfixed;
100
154k
#define qt_real_to_fixed(real) qfixed(real)
101
0
#define qt_fixed_to_real(fixed) fixed
102
struct qfixed2d
103
{
104
    qfixed x;
105
    qfixed y;
106
107
0
    bool isFinite() { return qIsFinite(x) && qIsFinite(y); }
108
0
    bool operator==(const qfixed2d &other) const { return qFuzzyCompare(x, other.x)
109
0
                                                       && qFuzzyCompare(y, other.y); }
110
};
111
#endif
112
113
0
#define QT_PATH_KAPPA 0.5522847498
114
115
QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength,
116
                          QPointF *controlPoints, int *point_count);
117
118
qreal qt_t_for_arc_angle(qreal angle);
119
120
typedef void (*qStrokerMoveToHook)(qfixed x, qfixed y, void *data);
121
typedef void (*qStrokerLineToHook)(qfixed x, qfixed y, void *data);
122
typedef void (*qStrokerCubicToHook)(qfixed c1x, qfixed c1y,
123
                                    qfixed c2x, qfixed c2y,
124
                                    qfixed ex, qfixed ey,
125
                                    void *data);
126
127
// qtransform.cpp
128
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
129
130
class Q_GUI_EXPORT QStrokerOps
131
{
132
public:
133
    struct Element {
134
        QPainterPath::ElementType type;
135
        qfixed x;
136
        qfixed y;
137
138
0
        inline bool isMoveTo() const { return type == QPainterPath::MoveToElement; }
139
0
        inline bool isLineTo() const { return type == QPainterPath::LineToElement; }
140
0
        inline bool isCurveTo() const { return type == QPainterPath::CurveToElement; }
141
142
0
        operator qfixed2d () { qfixed2d pt = { x, y }; return pt; }
143
    };
144
145
    QStrokerOps();
146
    virtual ~QStrokerOps();
147
148
28.0k
    void setMoveToHook(qStrokerMoveToHook moveToHook) { m_moveTo = moveToHook; }
149
28.0k
    void setLineToHook(qStrokerLineToHook lineToHook) { m_lineTo = lineToHook; }
150
28.0k
    void setCubicToHook(qStrokerCubicToHook cubicToHook) { m_cubicTo = cubicToHook; }
151
152
    virtual void begin(void *customData);
153
    virtual void end();
154
155
    inline void moveTo(qfixed x, qfixed y);
156
    inline void lineTo(qfixed x, qfixed y);
157
    inline void cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey);
158
159
    void strokePath(const QPainterPath &path, void *data, const QTransform &matrix);
160
    void strokePolygon(const QPointF *points, int pointCount, bool implicit_close,
161
                       void *data, const QTransform &matrix);
162
    void strokeEllipse(const QRectF &ellipse, void *data, const QTransform &matrix);
163
164
0
    QRectF clipRect() const { return m_clip_rect; }
165
14.0k
    void setClipRect(const QRectF &clip) { m_clip_rect = clip; }
166
167
    void setCurveThresholdFromTransform(const QTransform &transform)
168
0
    {
169
0
        qreal scale;
170
0
        qt_scaleForTransform(transform, &scale);
171
0
        m_dashThreshold = scale == 0 ? qreal(0.5) : (qreal(0.5) / scale);
172
0
    }
173
174
0
    void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
175
0
    qfixed curveThreshold() const { return m_curveThreshold; }
176
177
protected:
178
    inline void emitMoveTo(qfixed x, qfixed y);
179
    inline void emitLineTo(qfixed x, qfixed y);
180
    inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
181
182
    virtual void processCurrentSubpath() = 0;
183
    QDataBuffer<Element> m_elements;
184
185
    QRectF m_clip_rect;
186
    qfixed m_curveThreshold;
187
    qfixed m_dashThreshold;
188
189
    void *m_customData;
190
    qStrokerMoveToHook m_moveTo;
191
    qStrokerLineToHook m_lineTo;
192
    qStrokerCubicToHook m_cubicTo;
193
194
};
195
196
class Q_GUI_EXPORT QStroker : public QStrokerOps
197
{
198
public:
199
200
    enum LineJoinMode {
201
        FlatJoin,
202
        SquareJoin,
203
        MiterJoin,
204
        RoundJoin,
205
        RoundCap,
206
        SvgMiterJoin
207
    };
208
209
    QStroker();
210
    ~QStroker();
211
212
    void setStrokeWidth(qfixed width)
213
14.0k
    {
214
14.0k
        m_strokeWidth = width;
215
14.0k
        m_curveThreshold = qt_real_to_fixed(qBound(0.00025, 1.0 / qt_fixed_to_real(width), 0.25));
216
14.0k
    }
217
0
    qfixed strokeWidth() const { return m_strokeWidth; }
218
219
14.0k
    void setCapStyle(Qt::PenCapStyle capStyle) { m_capStyle = joinModeForCap(capStyle); }
220
0
    Qt::PenCapStyle capStyle() const { return capForJoinMode(m_capStyle); }
221
0
    LineJoinMode capStyleMode() const { return m_capStyle; }
222
223
14.0k
    void setJoinStyle(Qt::PenJoinStyle style) { m_joinStyle = joinModeForJoin(style); }
224
0
    Qt::PenJoinStyle joinStyle() const { return joinForJoinMode(m_joinStyle); }
225
0
    LineJoinMode joinStyleMode() const { return m_joinStyle; }
226
227
14.0k
    void setMiterLimit(qfixed length) { m_miterLimit = length; }
228
0
    qfixed miterLimit() const { return m_miterLimit; }
229
230
0
    void setForceOpen(bool state) { m_forceOpen = state; }
231
0
    bool forceOpen() { return m_forceOpen; }
232
233
    void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
234
    inline void emitMoveTo(qfixed x, qfixed y);
235
    inline void emitLineTo(qfixed x, qfixed y);
236
    inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
237
238
protected:
239
    static Qt::PenCapStyle capForJoinMode(LineJoinMode mode);
240
    static LineJoinMode joinModeForCap(Qt::PenCapStyle);
241
242
    static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode);
243
    static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle);
244
245
    void processCurrentSubpath() override;
246
247
    qfixed m_strokeWidth;
248
    qfixed m_miterLimit;
249
250
    LineJoinMode m_capStyle;
251
    LineJoinMode m_joinStyle;
252
253
    qfixed m_back1X;
254
    qfixed m_back1Y;
255
256
    qfixed m_back2X;
257
    qfixed m_back2Y;
258
259
    bool m_forceOpen;
260
};
261
262
class Q_GUI_EXPORT QDashStroker : public QStrokerOps
263
{
264
public:
265
    QDashStroker(QStroker *stroker);
266
    ~QDashStroker();
267
268
0
    QStroker *stroker() const { return m_stroker; }
269
270
    static QVector<qfixed> patternForStyle(Qt::PenStyle style);
271
0
    static int repetitionLimit() { return 10000; }
272
273
0
    void setDashPattern(const QVector<qfixed> &dashPattern) { m_dashPattern = dashPattern; }
274
0
    QVector<qfixed> dashPattern() const { return m_dashPattern; }
275
276
0
    void setDashOffset(qreal offset) { m_dashOffset = offset; }
277
0
    qreal dashOffset() const { return m_dashOffset; }
278
279
    void begin(void *data) override;
280
    void end() override;
281
282
0
    inline void setStrokeWidth(qreal width) { m_stroke_width = width; }
283
0
    inline void setMiterLimit(qreal limit) { m_miter_limit = limit; }
284
285
protected:
286
    void processCurrentSubpath() override;
287
288
    QStroker *m_stroker;
289
    QVector<qfixed> m_dashPattern;
290
    qreal m_dashOffset;
291
292
    qreal m_stroke_width;
293
    qreal m_miter_limit;
294
};
295
296
297
/*******************************************************************************
298
 * QStrokerOps inline membmers
299
 */
300
301
inline void QStrokerOps::emitMoveTo(qfixed x, qfixed y)
302
0
{
303
0
    Q_ASSERT(m_moveTo);
304
0
    m_moveTo(x, y, m_customData);
305
0
}
306
307
inline void QStrokerOps::emitLineTo(qfixed x, qfixed y)
308
0
{
309
0
    Q_ASSERT(m_lineTo);
310
0
    m_lineTo(x, y, m_customData);
311
0
}
312
313
inline void QStrokerOps::emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey)
314
0
{
315
0
    Q_ASSERT(m_cubicTo);
316
0
    m_cubicTo(c1x, c1y, c2x, c2y, ex, ey, m_customData);
317
0
}
318
319
inline void QStrokerOps::moveTo(qfixed x, qfixed y)
320
0
{
321
0
    if (m_elements.size()>1)
322
0
        processCurrentSubpath();
323
0
    m_elements.reset();
324
0
    Element e = { QPainterPath::MoveToElement, x, y };
325
0
    m_elements.add(e);
326
0
}
327
328
inline void QStrokerOps::lineTo(qfixed x, qfixed y)
329
0
{
330
0
    Element e = { QPainterPath::LineToElement, x, y };
331
0
    m_elements.add(e);
332
0
}
333
334
inline void QStrokerOps::cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey)
335
0
{
336
0
    Element c1 = { QPainterPath::CurveToElement, x1, y1 };
337
0
    Element c2 = { QPainterPath::CurveToDataElement, x2, y2 };
338
0
    Element e = { QPainterPath::CurveToDataElement, ex, ey };
339
0
    m_elements.add(c1);
340
0
    m_elements.add(c2);
341
0
    m_elements.add(e);
342
0
}
343
344
/*******************************************************************************
345
 * QStroker inline members
346
 */
347
inline void QStroker::emitMoveTo(qfixed x, qfixed y)
348
0
{
349
0
    m_back2X = m_back1X;
350
0
    m_back2Y = m_back1Y;
351
0
    m_back1X = x;
352
0
    m_back1Y = y;
353
0
    QStrokerOps::emitMoveTo(x, y);
354
0
}
355
356
inline void QStroker::emitLineTo(qfixed x, qfixed y)
357
0
{
358
0
    m_back2X = m_back1X;
359
0
    m_back2Y = m_back1Y;
360
0
    m_back1X = x;
361
0
    m_back1Y = y;
362
0
    QStrokerOps::emitLineTo(x, y);
363
0
}
364
365
inline void QStroker::emitCubicTo(qfixed c1x, qfixed c1y,
366
                                  qfixed c2x, qfixed c2y,
367
                                  qfixed ex, qfixed ey)
368
0
{
369
0
    if (c2x == ex && c2y == ey) {
370
0
        if (c1x == ex && c1y == ey) {
371
0
            m_back2X = m_back1X;
372
0
            m_back2Y = m_back1Y;
373
0
        } else {
374
0
            m_back2X = c1x;
375
0
            m_back2Y = c1y;
376
0
        }
377
0
    } else {
378
0
        m_back2X = c2x;
379
0
        m_back2Y = c2y;
380
0
    }
381
0
    m_back1X = ex;
382
0
    m_back1Y = ey;
383
0
    QStrokerOps::emitCubicTo(c1x, c1y, c2x, c2y, ex, ey);
384
0
}
385
386
/*******************************************************************************
387
 * QDashStroker inline members
388
 */
389
inline void QDashStroker::begin(void *data)
390
0
{
391
0
    if (m_stroker)
392
0
        m_stroker->begin(data);
393
0
    QStrokerOps::begin(data);
394
0
}
395
396
inline void QDashStroker::end()
397
0
{
398
0
    QStrokerOps::end();
399
0
    if (m_stroker)
400
0
        m_stroker->end();
401
0
}
402
403
QT_END_NAMESPACE
404
405
#endif // QSTROKER_P_H