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
68 QT_BEGIN_NAMESPACE
69
70 class QOutlineMapper;
71 class QRasterPaintEnginePrivate;
72 class QRasterBuffer;
73 class QClipData;
74
75 class QRasterPaintEngineState : public QPainterState
76 {
77 public:
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 */
131 class Q_GUI_EXPORT QRasterPaintEngine : public QPaintEngineEx
132 {
133 Q_DECLARE_PRIVATE(QRasterPaintEngine)
134 public:
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;
state()152 inline QRasterPaintEngineState *state() {
153 return static_cast<QRasterPaintEngineState *>(QPaintEngineEx::state());
154 }
state()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 ®ion, 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
type()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
228 protected:
229 QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *);
230 private:
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
ensureBrush(const QBrush & brush)243 inline void ensureBrush(const QBrush &brush) {
244 if (!qbrush_fast_equals(state()->lastBrush, brush) || state()->fillFlags)
245 updateBrush(brush);
246 }
ensureBrush()247 inline void ensureBrush() { ensureBrush(state()->brush); }
248
ensurePen(const QPen & pen)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 }
ensurePen()253 inline void ensurePen() { ensurePen(state()->pen); }
254
255 void updateOutlineMapper();
256 inline void ensureOutlineMapper();
257
258 void updateRasterState();
ensureRasterState()259 inline void ensureRasterState() {
260 if (state()->dirty)
261 updateRasterState();
262 }
263 };
264
265
266 /*******************************************************************************
267 * QRasterPaintEnginePrivate
268 */
269 class QRasterPaintEnginePrivate : public QPaintEngineExPrivate
270 {
271 Q_DECLARE_PUBLIC(QRasterPaintEngine)
272 public:
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
brushMatrix()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
346 class QClipData {
347 public:
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
clipLines()359 inline ClipLine *clipLines() {
360 if (!m_clipLines)
361 initialize();
362 return m_clipLines;
363 }
364
spans()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 ®ion);
391 void fixup();
392 };
393
appendSpan(int x,int length,int y,int coverage)394 inline 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
appendSpans(const QSpan * s,int num)409 inline 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 */
426 class QRasterBuffer
427 {
428 public:
QRasterBuffer()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
scanLine(int y)437 uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * qsizetype(bytes_per_line); }
438
width()439 int width() const { return m_width; }
height()440 int height() const { return m_height; }
bytesPerLine()441 int bytesPerLine() const { return bytes_per_line; }
bytesPerPixel()442 int bytesPerPixel() const { return bytes_per_pixel; }
443 template<typename T>
stride()444 int stride() { return bytes_per_line / sizeof(T); }
445
buffer()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
456 private:
457 int m_width;
458 int m_height;
459 int bytes_per_line;
460 int bytes_per_pixel;
461 uchar *m_buffer;
462 };
463
ensureOutlineMapper()464 inline void QRasterPaintEngine::ensureOutlineMapper() {
465 if (d_func()->outlinemapper_xform_dirty)
466 updateOutlineMapper();
467 }
468
clip()469 inline 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
clipData()476 inline 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
483 QT_END_NAMESPACE
484 #endif // QPAINTENGINE_RASTER_P_H
485