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#include <private/qemulationpaintengine_p.h>
5#include <private/qpainter_p.h>
6#include <private/qtextengine_p.h>
7#include <qdebug.h>
8
9QT_BEGIN_NAMESPACE
10
11QEmulationPaintEngine::QEmulationPaintEngine(QPaintEngineEx *engine)
12 : real_engine(engine)
13{
14 QPaintEngine::state = real_engine->state();
15}
16
17
18QPaintEngine::Type QEmulationPaintEngine::type() const
19{
20 return real_engine->type();
21}
22
23bool QEmulationPaintEngine::begin(QPaintDevice *)
24{
25 return true;
26}
27
28bool QEmulationPaintEngine::end()
29{
30 return true;
31}
32
33
34QPainterState *QEmulationPaintEngine::createState(QPainterState *orig) const
35{
36 return real_engine->createState(orig);
37}
38
39static inline void combineXForm(QBrush *brush, const QRectF &r)
40{
41 QTransform t(r.width(), 0, 0, r.height(), r.x(), r.y());
42 if (brush->gradient() && brush->gradient()->coordinateMode() != QGradient::ObjectMode)
43 brush->setTransform(t * brush->transform()); // compat mode
44 else
45 brush->setTransform(brush->transform() * t);
46}
47
48void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
49{
50 QPainterState *s = state();
51
52 if (s->bgMode == Qt::OpaqueMode) {
53 Qt::BrushStyle style = brush.style();
54 if ((style >= Qt::Dense1Pattern && style <= Qt::DiagCrossPattern) || (style == Qt::TexturePattern ))
55 real_engine->fill(path, brush: s->bgBrush);
56 }
57
58 Qt::BrushStyle style = qbrush_style(b: brush);
59 if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
60 QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
61 if (coMode > QGradient::LogicalMode) {
62 QBrush copy = brush;
63 const QPaintDevice *d = real_engine->painter()->device();
64 QRectF r = (coMode == QGradient::StretchToDeviceMode) ? QRectF(0, 0, d->width(), d->height()) : path.controlPointRect();
65 combineXForm(brush: &copy, r);
66 real_engine->fill(path, brush: copy);
67 return;
68 }
69 } else if (style == Qt::TexturePattern) {
70 qreal dpr = qHasPixmapTexture(brush) ? brush.texture().devicePixelRatio() : brush.textureImage().devicePixelRatio();
71 if (!qFuzzyCompare(p1: dpr, p2: qreal(1.0))) {
72 QBrush copy = brush;
73 combineXForm(brush: &copy, r: QRectF(0, 0, 1.0/dpr, 1.0/dpr));
74 real_engine->fill(path, brush: copy);
75 return;
76 }
77 }
78
79 real_engine->fill(path, brush);
80}
81
82void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
83{
84 QPainterState *s = state();
85
86 if (s->bgMode == Qt::OpaqueMode && pen.style() > Qt::SolidLine) {
87 QPen bgPen = pen;
88 bgPen.setBrush(s->bgBrush);
89 bgPen.setStyle(Qt::SolidLine);
90 real_engine->stroke(path, pen: bgPen);
91 }
92
93 QBrush brush = pen.brush();
94 QPen copy = pen;
95 Qt::BrushStyle style = qbrush_style(b: brush);
96 if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern ) {
97 QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
98 if (coMode > QGradient::LogicalMode) {
99 const QPaintDevice *d = real_engine->painter()->device();
100 QRectF r = (coMode == QGradient::StretchToDeviceMode) ? QRectF(0, 0, d->width(), d->height()) : path.controlPointRect();
101 combineXForm(brush: &brush, r);
102 copy.setBrush(brush);
103 real_engine->stroke(path, pen: copy);
104 return;
105 }
106 }
107
108 real_engine->stroke(path, pen);
109}
110
111void QEmulationPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
112{
113 real_engine->clip(path, op);
114}
115
116void QEmulationPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
117{
118 if (state()->bgMode == Qt::OpaqueMode && pm.isQBitmap())
119 fillBGRect(r);
120 real_engine->drawPixmap(r, pm, sr);
121}
122
123void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
124{
125 if (state()->bgMode == Qt::OpaqueMode) {
126 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
127 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent).toReal());
128 fillBGRect(r: rect);
129 }
130
131 QPainterState *s = state();
132 Qt::BrushStyle style = qbrush_style(b: s->pen.brush());
133 if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern)
134 {
135 QPen savedPen = s->pen;
136 QGradient g = *s->pen.brush().gradient();
137
138 if (g.coordinateMode() > QGradient::LogicalMode) {
139 QBrush copy = s->pen.brush();
140 const QPaintDevice *d = real_engine->painter()->device();
141 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
142 QRectF r = (g.coordinateMode() == QGradient::StretchToDeviceMode) ?
143 QRectF(0, 0, d->width(), d->height()) :
144 QRectF(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
145 combineXForm(brush: &copy, r);
146 g.setCoordinateMode(QGradient::LogicalMode);
147 QBrush brush(g);
148 brush.setTransform(copy.transform());
149 s->pen.setBrush(brush);
150 penChanged();
151 real_engine->drawTextItem(p, textItem);
152 s->pen = savedPen;
153 penChanged();
154 return;
155 }
156 }
157
158 real_engine->drawTextItem(p, textItem);
159}
160
161void QEmulationPaintEngine::drawStaticTextItem(QStaticTextItem *item)
162{
163 real_engine->drawStaticTextItem(item);
164}
165
166void QEmulationPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
167{
168 if (state()->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
169 fillBGRect(r);
170 real_engine->drawTiledPixmap(r, pixmap, s);
171}
172
173void QEmulationPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags)
174{
175 real_engine->drawImage(r, pm, sr, flags);
176}
177
178void QEmulationPaintEngine::clipEnabledChanged()
179{
180 real_engine->clipEnabledChanged();
181}
182
183void QEmulationPaintEngine::penChanged()
184{
185 real_engine->penChanged();
186}
187
188void QEmulationPaintEngine::brushChanged()
189{
190 real_engine->brushChanged();
191}
192
193void QEmulationPaintEngine::brushOriginChanged()
194{
195 real_engine->brushOriginChanged();
196}
197
198void QEmulationPaintEngine::opacityChanged()
199{
200 real_engine->opacityChanged();
201}
202
203void QEmulationPaintEngine::compositionModeChanged()
204{
205 real_engine->compositionModeChanged();
206}
207
208void QEmulationPaintEngine::renderHintsChanged()
209{
210 real_engine->renderHintsChanged();
211}
212
213void QEmulationPaintEngine::transformChanged()
214{
215 real_engine->transformChanged();
216}
217
218void QEmulationPaintEngine::setState(QPainterState *s)
219{
220 QPaintEngine::state = s;
221 real_engine->setState(s);
222}
223
224void QEmulationPaintEngine::beginNativePainting()
225{
226 real_engine->beginNativePainting();
227}
228
229void QEmulationPaintEngine::endNativePainting()
230{
231 real_engine->endNativePainting();
232}
233
234void QEmulationPaintEngine::fillBGRect(const QRectF &r)
235{
236 qreal pts[] = { r.x(), r.y(), r.x() + r.width(), r.y(),
237 r.x() + r.width(), r.y() + r.height(), r.x(), r.y() + r.height() };
238 QVectorPath vp(pts, 4, nullptr, QVectorPath::RectangleHint);
239 real_engine->fill(path: vp, brush: state()->bgBrush);
240}
241
242QT_END_NAMESPACE
243

source code of qtbase/src/gui/painting/qemulationpaintengine.cpp