Coverage Report

Created: 2026-05-31 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/painting/qpaintengine_raster_p.h
Line
Count
Source
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 QPAINTENGINE_RASTER_P_H
6
#define QPAINTENGINE_RASTER_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 for the convenience
13
// of other Qt classes.  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 "private/qpaintengineex_p.h"
21
#include "QtGui/qpainterpath.h"
22
#include "private/qdatabuffer_p.h"
23
#include "private/qdrawhelper_p.h"
24
#include "private/qpaintengine_p.h"
25
#include "private/qrasterizer_p.h"
26
#include "private/qstroker_p.h"
27
#include "private/qpainter_p.h"
28
#include "private/qtextureglyphcache_p.h"
29
#include "private/qoutlinemapper_p.h"
30
31
#include <stdlib.h>
32
33
QT_BEGIN_NAMESPACE
34
35
class QOutlineMapper;
36
class QRasterPaintEnginePrivate;
37
class QRasterBuffer;
38
class QClipData;
39
40
class QRasterPaintEngineState : public QPainterState
41
{
42
public:
43
    QRasterPaintEngineState(const QRasterPaintEngineState &other);
44
    QRasterPaintEngineState();
45
    ~QRasterPaintEngineState();
46
47
48
    QPen lastPen;
49
    QSpanData penData;
50
    QStrokerOps *stroker;
51
    uint strokeFlags;
52
53
    QBrush lastBrush;
54
    QSpanData brushData;
55
    uint fillFlags;
56
57
    uint pixmapFlags;
58
    int intOpacity;
59
60
    qreal txscale;
61
62
    QClipData *clip;
63
//     QRect clipRect;
64
//     QRegion clipRegion;
65
66
//     QPainter::RenderHints hints;
67
//     QPainter::CompositionMode compositionMode;
68
69
    uint dirty;
70
71
    struct Flags {
72
        uint has_clip_ownership : 1;        // should delete the clip member..
73
        uint fast_pen : 1;                  // cosmetic 1-width pens, using midpoint drawlines
74
        uint non_complex_pen : 1;           // can use rasterizer, rather than stroker
75
        uint antialiased : 1;
76
        uint bilinear : 1;
77
        uint fast_text : 1;
78
        uint tx_noshear : 1;
79
        uint fast_images : 1;
80
        uint cosmetic_brush : 1;
81
    };
82
83
    union {
84
        Flags flags;
85
        uint flag_bits;
86
    };
87
};
88
89
90
91
92
/*******************************************************************************
93
 * QRasterPaintEngine
94
 */
95
class Q_GUI_EXPORT QRasterPaintEngine : public QPaintEngineEx
96
{
97
    Q_DECLARE_PRIVATE(QRasterPaintEngine)
98
public:
99
100
    QRasterPaintEngine(QPaintDevice *device);
101
    ~QRasterPaintEngine();
102
    bool begin(QPaintDevice *device) override;
103
    bool end() override;
104
105
    void penChanged() override;
106
    void brushChanged() override;
107
    void brushOriginChanged() override;
108
    void opacityChanged() override;
109
    void compositionModeChanged() override;
110
    void renderHintsChanged() override;
111
    void transformChanged() override;
112
    void clipEnabledChanged() override;
113
114
    void setState(QPainterState *s) override;
115
    QPainterState *createState(QPainterState *orig) const override;
116
5.53M
    inline QRasterPaintEngineState *state() {
117
5.53M
        return static_cast<QRasterPaintEngineState *>(QPaintEngineEx::state());
118
5.53M
    }
119
6.33M
    inline const QRasterPaintEngineState *state() const {
120
6.33M
        return static_cast<const QRasterPaintEngineState *>(QPaintEngineEx::state());
121
6.33M
    }
122
123
    void updateBrush(const QBrush &brush);
124
    void updatePen(const QPen &pen);
125
126
    void updateMatrix(const QTransform &matrix);
127
128
    virtual void fillPath(const QPainterPath &path, QSpanData *fillData);
129
    virtual void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
130
131
    void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) override;
132
    void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) override;
133
134
    void drawEllipse(const QRectF &rect) override;
135
136
    void fillRect(const QRectF &rect, const QBrush &brush) override;
137
    void fillRect(const QRectF &rect, const QColor &color) override;
138
139
    void drawRects(const QRect  *rects, int rectCount) override;
140
    void drawRects(const QRectF *rects, int rectCount) override;
141
142
    void drawPixmap(const QPointF &p, const QPixmap &pm) override;
143
    void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
144
    void drawImage(const QPointF &p, const QImage &img) override;
145
    void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
146
                   Qt::ImageConversionFlags flags = Qt::AutoColor) override;
147
    void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr) override;
148
    void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
149
150
    void drawLines(const QLine *line, int lineCount) override;
151
    void drawLines(const QLineF *line, int lineCount) override;
152
153
    void drawPoints(const QPointF *points, int pointCount) override;
154
    void drawPoints(const QPoint *points, int pointCount) override;
155
156
    void stroke(const QVectorPath &path, const QPen &pen) override;
157
    void fill(const QVectorPath &path, const QBrush &brush) override;
158
159
    void clip(const QVectorPath &path, Qt::ClipOperation op) override;
160
    void clip(const QRect &rect, Qt::ClipOperation op) override;
161
    void clip(const QRegion &region, Qt::ClipOperation op) override;
162
    inline const QClipData *clipData() const;
163
164
    void drawStaticTextItem(QStaticTextItem *textItem) override;
165
    virtual bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions,
166
                                  QFontEngine *fontEngine);
167
168
    enum ClipType {
169
        RectClip,
170
        ComplexClip
171
    };
172
    ClipType clipType() const;
173
    QRectF clipBoundingRect() const;
174
175
#ifdef Q_OS_WIN
176
    void setDC(HDC hdc);
177
    HDC getDC() const;
178
    void releaseDC(HDC hdc) const;
179
    static bool clearTypeFontsEnabled();
180
#endif
181
182
    QRasterBuffer *rasterBuffer();
183
    void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h, bool useGammaCorrection);
184
185
18.6k
    Type type() const override { return Raster; }
186
187
    QPoint coordinateOffset() const override;
188
189
    bool requiresPretransformedGlyphPositions(QFontEngine *fontEngine, const QTransform &m) const override;
190
    bool shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const override;
191
192
protected:
193
    QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *);
194
private:
195
    friend struct QSpanData;
196
    friend class QBlitterPaintEngine;
197
    friend class QBlitterPaintEnginePrivate;
198
    void init();
199
200
    void fillRect(const QRectF &rect, QSpanData *data);
201
    void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill);
202
203
    bool setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op);
204
205
    QRect toNormalizedFillRect(const QRectF &rect);
206
207
63.4k
    inline void ensureBrush(const QBrush &brush) {
208
63.4k
        if (!qbrush_fast_equals(state()->lastBrush, brush) || state()->fillFlags)
209
58.4k
            updateBrush(brush);
210
63.4k
    }
211
0
    inline void ensureBrush() { ensureBrush(state()->brush); }
212
213
311k
    inline void ensurePen(const QPen &pen) {
214
311k
        if (!qpen_fast_equals(state()->lastPen, pen) || (pen.style() != Qt::NoPen && state()->strokeFlags))
215
143k
            updatePen(pen);
216
311k
    }
217
283k
    inline void ensurePen() { ensurePen(state()->pen); }
218
219
    void updateOutlineMapper();
220
    inline void ensureOutlineMapper();
221
222
    void updateRasterState();
223
425k
    inline void ensureRasterState() {
224
425k
        if (state()->dirty)
225
145k
            updateRasterState();
226
425k
    }
227
};
228
229
230
/*******************************************************************************
231
 * QRasterPaintEnginePrivate
232
 */
233
class QRasterPaintEnginePrivate : public QPaintEngineExPrivate
234
{
235
    Q_DECLARE_PUBLIC(QRasterPaintEngine)
236
public:
237
    QRasterPaintEnginePrivate();
238
239
    void rasterizeLine_dashed(QLineF line, qreal width,
240
                              int *dashIndex, qreal *dashOffset, bool *inDash);
241
    void rasterize(QT_FT_Outline *outline, ProcessSpans callback, QSpanData *spanData, QRasterBuffer *rasterBuffer);
242
    void rasterize(QT_FT_Outline *outline, ProcessSpans callback, void *userData, QRasterBuffer *rasterBuffer);
243
    void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix);
244
    void updateClipping();
245
246
    void systemStateChanged() override;
247
248
    void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func,
249
                   const QRect &clip, int alpha, const QRect &sr = QRect());
250
    void blitImage(const QPointF &pt, const QImage &img,
251
                   const QRect &clip, const QRect &sr = QRect());
252
253
58.4k
    QTransform brushMatrix() const {
254
58.4k
        Q_Q(const QRasterPaintEngine);
255
58.4k
        const QRasterPaintEngineState *s = q->state();
256
58.4k
        QTransform m(s->matrix);
257
58.4k
        m.translate(s->brushOrigin.x(), s->brushOrigin.y());
258
58.4k
        return m;
259
58.4k
    }
260
261
    bool isUnclipped_normalized(const QRect &rect) const;
262
    bool isUnclipped(const QRect &rect, int penWidth) const;
263
    bool isUnclipped(const QRectF &rect, int penWidth) const;
264
    ProcessSpans getPenFunc(const QRectF &rect, const QSpanData *data) const;
265
    ProcessSpans getBrushFunc(const QRect &rect, const QSpanData *data) const;
266
    ProcessSpans getBrushFunc(const QRectF &rect, const QSpanData *data) const;
267
268
    inline const QClipData *clip() const;
269
270
    void initializeRasterizer(QSpanData *data);
271
272
    void recalculateFastImages();
273
    bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const;
274
    bool canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image, const QPointF &pt, const QRectF &sr) const;
275
276
    QPaintDevice *device;
277
    QScopedPointer<QOutlineMapper> outlineMapper;
278
    QScopedPointer<QRasterBuffer>  rasterBuffer;
279
280
#if defined (Q_OS_WIN)
281
    HDC hdc;
282
#endif
283
284
    QRect deviceRect;
285
    QRect deviceRectUnclipped;
286
287
    QStroker basicStroker;
288
    QScopedPointer<QDashStroker> dashStroker;
289
290
    QScopedPointer<QT_FT_Raster> grayRaster;
291
292
    QDataBuffer<QLineF> cachedLines;
293
    QSpanData image_filler;
294
    QSpanData image_filler_xform;
295
    QSpanData solid_color_filler;
296
297
298
    QFontEngine::GlyphFormat glyphCacheFormat;
299
300
    QScopedPointer<QClipData> baseClip;
301
302
    int deviceDepth;
303
304
    uint mono_surface : 1;
305
    uint outlinemapper_xform_dirty : 1;
306
307
    QScopedPointer<QRasterizer> rasterizer;
308
};
309
310
311
class QClipData {
312
public:
313
    QClipData(int height);
314
    ~QClipData();
315
316
    int clipSpanHeight;
317
    struct ClipLine {
318
        int count;
319
        QT_FT_Span *spans;
320
    } *m_clipLines;
321
322
    void initialize();
323
324
0
    inline ClipLine *clipLines() {
325
0
        if (!m_clipLines)
326
0
            initialize();
327
0
        return m_clipLines;
328
0
    }
329
330
0
    inline QT_FT_Span *spans() {
331
0
        if (!m_spans)
332
0
            initialize();
333
0
        return m_spans;
334
0
    }
335
336
    int allocated;
337
    int count;
338
    QT_FT_Span *m_spans;
339
    int xmin, xmax, ymin, ymax;
340
341
    QRect clipRect;
342
    QRegion clipRegion;
343
344
    uint enabled : 1;
345
    uint hasRectClip : 1;
346
    uint hasRegionClip : 1;
347
348
    void appendSpan(int x, int length, int y, int coverage);
349
    void appendSpans(const QT_FT_Span *s, int num);
350
351
    // ### Should optimize and actually kill the QSpans if the rect is
352
    // ### a subset of The current region. Thus the "fast" clipspan
353
    // ### callback can be used
354
    void setClipRect(const QRect &rect);
355
    void setClipRegion(const QRegion &region);
356
    void fixup();
357
};
358
359
inline void QClipData::appendSpan(int x, int length, int y, int coverage)
360
0
{
361
0
    Q_ASSERT(m_spans); // initialize() has to be called prior to adding spans..
362
0
363
0
    if (count == allocated) {
364
0
        allocated *= 2;
365
0
        m_spans = static_cast<QT_FT_Span*>(q_check_ptr(realloc(m_spans, allocated * sizeof(QT_FT_Span))));
366
0
    }
367
0
    m_spans[count].x = x;
368
0
    m_spans[count].len = length;
369
0
    m_spans[count].y = y;
370
0
    m_spans[count].coverage = coverage;
371
0
    ++count;
372
0
}
373
374
inline void QClipData::appendSpans(const QT_FT_Span *s, int num)
375
0
{
376
0
    Q_ASSERT(m_spans);
377
378
0
    if (count + num > allocated) {
379
0
        do {
380
0
            allocated *= 2;
381
0
        } while (count + num > allocated);
382
0
        m_spans = static_cast<QT_FT_Span*>(q_check_ptr(realloc(m_spans, allocated * sizeof(QT_FT_Span))));
383
0
    }
384
0
    memcpy(m_spans+count, s, num*sizeof(QT_FT_Span));
385
0
    count += num;
386
0
}
387
388
/*******************************************************************************
389
 * QRasterBuffer
390
 */
391
class QRasterBuffer
392
{
393
public:
394
118k
    QRasterBuffer() : m_width(0), m_height(0), m_buffer(nullptr) { init(); }
395
396
    ~QRasterBuffer();
397
398
    void init();
399
400
    QImage::Format prepare(QImage *image);
401
402
47.9M
    uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * bytes_per_line; }
403
404
0
    int width() const { return m_width; }
405
278k
    int height() const { return m_height; }
406
9
    qsizetype bytesPerLine() const { return bytes_per_line; }
407
0
    int bytesPerPixel() const { return bytes_per_pixel; }
408
    template<typename T>
409
990k
    int stride() { return static_cast<int>(bytes_per_line / sizeof(T)); }
int QRasterBuffer::stride<unsigned int>()
Line
Count
Source
409
990k
    int stride() { return static_cast<int>(bytes_per_line / sizeof(T)); }
Unexecuted instantiation: int QRasterBuffer::stride<unsigned short>()
410
411
9
    uchar *buffer() const { return m_buffer; }
412
413
    bool monoDestinationWithClut;
414
    QRgb destColor0;
415
    QRgb destColor1;
416
417
    QPainter::CompositionMode compositionMode;
418
    QImage::Format format;
419
    QColorSpace colorSpace;
420
    QImage colorizeBitmap(const QImage &image, const QColor &color);
421
422
private:
423
    int m_width;
424
    int m_height;
425
    qsizetype bytes_per_line;
426
    int bytes_per_pixel;
427
    uchar *m_buffer;
428
};
429
430
192k
inline void QRasterPaintEngine::ensureOutlineMapper() {
431
192k
    if (d_func()->outlinemapper_xform_dirty)
432
192k
        updateOutlineMapper();
433
192k
}
434
435
2.03M
inline const QClipData *QRasterPaintEnginePrivate::clip() const {
436
2.03M
    Q_Q(const QRasterPaintEngine);
437
2.03M
    if (q->state() && q->state()->clip && q->state()->clip->enabled)
438
1.21M
        return q->state()->clip;
439
823k
    return baseClip.data();
440
2.03M
}
441
442
0
inline const QClipData *QRasterPaintEngine::clipData() const {
443
0
    Q_D(const QRasterPaintEngine);
444
0
    if (state() && state()->clip && state()->clip->enabled)
445
0
        return state()->clip;
446
0
    return d->baseClip.data();
447
0
}
448
449
QT_END_NAMESPACE
450
#endif // QPAINTENGINE_RASTER_P_H