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 &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 
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 &region);
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