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

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