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