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 "qsgsoftwareinternalimagenode_p.h" |
5 | |
6 | #include "qsgsoftwarepixmaptexture_p.h" |
7 | #include "qsgsoftwarelayer_p.h" |
8 | #include <QPainter> |
9 | #include <qmath.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | namespace QSGSoftwareHelpers { |
14 | // Helper from widgets/styles/qdrawutil.cpp |
15 | |
16 | static inline QMargins normalizedMargins(const QMargins &m) |
17 | { |
18 | return QMargins(qMax(a: m.left(), b: 0), qMax(a: m.top(), b: 0), qMax(a: m.right(), b: 0), qMax(a: m.bottom(), b: 0)); |
19 | } |
20 | |
21 | void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMarginsIn, |
22 | const QPixmap &pixmap, const QRect &sourceRect, const QMargins &sourceMarginsIn, |
23 | const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) |
24 | { |
25 | QPainter::PixmapFragment d; |
26 | d.opacity = 1.0; |
27 | d.rotation = 0.0; |
28 | |
29 | QPixmapFragmentsArray opaqueData; |
30 | QPixmapFragmentsArray translucentData; |
31 | |
32 | QMargins sourceMargins = normalizedMargins(m: sourceMarginsIn); |
33 | QMargins targetMargins = normalizedMargins(m: targetMarginsIn); |
34 | |
35 | const qreal sourceDpr = pixmap.devicePixelRatio(); |
36 | sourceMargins *= sourceDpr; |
37 | |
38 | // source center |
39 | const int sourceCenterTop = sourceRect.top() + sourceMargins.top(); |
40 | const int sourceCenterLeft = sourceRect.left() + sourceMargins.left(); |
41 | const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1; |
42 | const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1; |
43 | const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft; |
44 | const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop; |
45 | // target center |
46 | const int targetCenterTop = targetRect.top() + targetMargins.top(); |
47 | const int targetCenterLeft = targetRect.left() + targetMargins.left(); |
48 | const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1; |
49 | const int targetCenterRight = targetRect.right() - targetMargins.right() + 1; |
50 | const int targetCenterWidth = targetCenterRight - targetCenterLeft; |
51 | const int targetCenterHeight = targetCenterBottom - targetCenterTop; |
52 | |
53 | QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles |
54 | QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles |
55 | |
56 | int columns = 3; |
57 | int rows = 3; |
58 | if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0) |
59 | columns = qMax(a: 3, b: 2 + qCeil(v: (targetCenterWidth * sourceDpr) / qreal(sourceCenterWidth))); |
60 | if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0) |
61 | rows = qMax(a: 3, b: 2 + qCeil(v: (targetCenterHeight * sourceDpr) / qreal(sourceCenterHeight))); |
62 | |
63 | xTarget.resize(sz: columns + 1); |
64 | yTarget.resize(sz: rows + 1); |
65 | |
66 | xTarget[0] = targetRect.left(); |
67 | xTarget[1] = targetCenterLeft; |
68 | xTarget[columns - 1] = targetCenterRight; |
69 | xTarget[columns] = targetRect.left() + targetRect.width(); |
70 | |
71 | yTarget[0] = targetRect.top(); |
72 | yTarget[1] = targetCenterTop; |
73 | yTarget[rows - 1] = targetCenterBottom; |
74 | yTarget[rows] = targetRect.top() + targetRect.height(); |
75 | |
76 | qreal dx = targetCenterWidth; |
77 | qreal dy = targetCenterHeight; |
78 | |
79 | switch (rules.horizontal) { |
80 | case Qt::StretchTile: |
81 | dx = targetCenterWidth; |
82 | break; |
83 | case Qt::RepeatTile: |
84 | dx = sourceCenterWidth / sourceDpr; |
85 | break; |
86 | case Qt::RoundTile: |
87 | dx = targetCenterWidth / qreal(columns - 2); |
88 | break; |
89 | } |
90 | |
91 | for (int i = 2; i < columns - 1; ++i) |
92 | xTarget[i] = xTarget[i - 1] + dx; |
93 | |
94 | switch (rules.vertical) { |
95 | case Qt::StretchTile: |
96 | dy = targetCenterHeight; |
97 | break; |
98 | case Qt::RepeatTile: |
99 | dy = sourceCenterHeight / sourceDpr; |
100 | break; |
101 | case Qt::RoundTile: |
102 | dy = targetCenterHeight / qreal(rows - 2); |
103 | break; |
104 | } |
105 | |
106 | for (int i = 2; i < rows - 1; ++i) |
107 | yTarget[i] = yTarget[i - 1] + dy; |
108 | |
109 | // corners |
110 | if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left |
111 | d.x = (0.5 * (xTarget[1] + xTarget[0])); |
112 | d.y = (0.5 * (yTarget[1] + yTarget[0])); |
113 | d.sourceLeft = sourceRect.left(); |
114 | d.sourceTop = sourceRect.top(); |
115 | d.width = sourceMargins.left(); |
116 | d.height = sourceMargins.top(); |
117 | d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; |
118 | d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; |
119 | if (hints & QDrawBorderPixmap::OpaqueTopLeft) |
120 | opaqueData.append(t: d); |
121 | else |
122 | translucentData.append(t: d); |
123 | } |
124 | if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right |
125 | d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); |
126 | d.y = (0.5 * (yTarget[1] + yTarget[0])); |
127 | d.sourceLeft = sourceCenterRight; |
128 | d.sourceTop = sourceRect.top(); |
129 | d.width = sourceMargins.right(); |
130 | d.height = sourceMargins.top(); |
131 | d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; |
132 | d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; |
133 | if (hints & QDrawBorderPixmap::OpaqueTopRight) |
134 | opaqueData.append(t: d); |
135 | else |
136 | translucentData.append(t: d); |
137 | } |
138 | if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left |
139 | d.x = (0.5 * (xTarget[1] + xTarget[0])); |
140 | d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1])); |
141 | d.sourceLeft = sourceRect.left(); |
142 | d.sourceTop = sourceCenterBottom; |
143 | d.width = sourceMargins.left(); |
144 | d.height = sourceMargins.bottom(); |
145 | d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; |
146 | d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; |
147 | if (hints & QDrawBorderPixmap::OpaqueBottomLeft) |
148 | opaqueData.append(t: d); |
149 | else |
150 | translucentData.append(t: d); |
151 | } |
152 | if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right |
153 | d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); |
154 | d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); |
155 | d.sourceLeft = sourceCenterRight; |
156 | d.sourceTop = sourceCenterBottom; |
157 | d.width = sourceMargins.right(); |
158 | d.height = sourceMargins.bottom(); |
159 | d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; |
160 | d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; |
161 | if (hints & QDrawBorderPixmap::OpaqueBottomRight) |
162 | opaqueData.append(t: d); |
163 | else |
164 | translucentData.append(t: d); |
165 | } |
166 | |
167 | // horizontal edges |
168 | if (targetCenterWidth > 0 && sourceCenterWidth > 0) { |
169 | if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top |
170 | QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData; |
171 | d.sourceLeft = sourceCenterLeft; |
172 | d.sourceTop = sourceRect.top(); |
173 | d.width = sourceCenterWidth; |
174 | d.height = sourceMargins.top(); |
175 | d.y = (0.5 * (yTarget[1] + yTarget[0])); |
176 | d.scaleX = dx / d.width; |
177 | d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; |
178 | for (int i = 1; i < columns - 1; ++i) { |
179 | d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); |
180 | data.append(t: d); |
181 | } |
182 | if (rules.horizontal == Qt::RepeatTile) |
183 | data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); |
184 | } |
185 | if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom |
186 | QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData; |
187 | d.sourceLeft = sourceCenterLeft; |
188 | d.sourceTop = sourceCenterBottom; |
189 | d.width = sourceCenterWidth; |
190 | d.height = sourceMargins.bottom(); |
191 | d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); |
192 | d.scaleX = dx / d.width; |
193 | d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; |
194 | for (int i = 1; i < columns - 1; ++i) { |
195 | d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); |
196 | data.append(t: d); |
197 | } |
198 | if (rules.horizontal == Qt::RepeatTile) |
199 | data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); |
200 | } |
201 | } |
202 | |
203 | // vertical edges |
204 | if (targetCenterHeight > 0 && sourceCenterHeight > 0) { |
205 | if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left |
206 | QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData; |
207 | d.sourceLeft = sourceRect.left(); |
208 | d.sourceTop = sourceCenterTop; |
209 | d.width = sourceMargins.left(); |
210 | d.height = sourceCenterHeight; |
211 | d.x = (0.5 * (xTarget[1] + xTarget[0])); |
212 | d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; |
213 | d.scaleY = dy / d.height; |
214 | for (int i = 1; i < rows - 1; ++i) { |
215 | d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); |
216 | data.append(t: d); |
217 | } |
218 | if (rules.vertical == Qt::RepeatTile) |
219 | data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); |
220 | } |
221 | if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right |
222 | QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData; |
223 | d.sourceLeft = sourceCenterRight; |
224 | d.sourceTop = sourceCenterTop; |
225 | d.width = sourceMargins.right(); |
226 | d.height = sourceCenterHeight; |
227 | d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); |
228 | d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; |
229 | d.scaleY = dy / d.height; |
230 | for (int i = 1; i < rows - 1; ++i) { |
231 | d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); |
232 | data.append(t: d); |
233 | } |
234 | if (rules.vertical == Qt::RepeatTile) |
235 | data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); |
236 | } |
237 | } |
238 | |
239 | // center |
240 | if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) { |
241 | QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData; |
242 | d.sourceLeft = sourceCenterLeft; |
243 | d.sourceTop = sourceCenterTop; |
244 | d.width = sourceCenterWidth; |
245 | d.height = sourceCenterHeight; |
246 | d.scaleX = dx / d.width; |
247 | d.scaleY = dy / d.height; |
248 | |
249 | qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX; |
250 | qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY; |
251 | |
252 | for (int j = 1; j < rows - 1; ++j) { |
253 | d.y = (0.5 * (yTarget[j + 1] + yTarget[j])); |
254 | for (int i = 1; i < columns - 1; ++i) { |
255 | d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); |
256 | data.append(t: d); |
257 | } |
258 | if (rules.horizontal == Qt::RepeatTile) |
259 | data[data.size() - 1].width = repeatWidth; |
260 | } |
261 | if (rules.vertical == Qt::RepeatTile) { |
262 | for (int i = 1; i < columns - 1; ++i) |
263 | data[data.size() - i].height = repeatHeight; |
264 | } |
265 | } |
266 | |
267 | if (opaqueData.size()) |
268 | painter->drawPixmapFragments(fragments: opaqueData.data(), fragmentCount: opaqueData.size(), pixmap, hints: QPainter::OpaqueHint); |
269 | if (translucentData.size()) |
270 | painter->drawPixmapFragments(fragments: translucentData.data(), fragmentCount: translucentData.size(), pixmap); |
271 | } |
272 | |
273 | } // QSGSoftwareHelpers namespace |
274 | |
275 | QSGSoftwareInternalImageNode::QSGSoftwareInternalImageNode() |
276 | : m_innerSourceRect(0, 0, 1, 1) |
277 | , m_subSourceRect(0, 0, 1, 1) |
278 | , m_texture(nullptr) |
279 | , m_mirrorHorizontally(false) |
280 | , m_mirrorVertically(false) |
281 | , m_textureIsLayer(false) |
282 | , m_smooth(true) |
283 | , m_tileHorizontal(false) |
284 | , m_tileVertical(false) |
285 | , m_cachedMirroredPixmapIsDirty(false) |
286 | { |
287 | setMaterial((QSGMaterial*)1); |
288 | setGeometry((QSGGeometry*)1); |
289 | } |
290 | |
291 | |
292 | void QSGSoftwareInternalImageNode::setTargetRect(const QRectF &rect) |
293 | { |
294 | if (rect == m_targetRect) |
295 | return; |
296 | m_targetRect = rect; |
297 | markDirty(bits: DirtyGeometry); |
298 | } |
299 | |
300 | void QSGSoftwareInternalImageNode::setInnerTargetRect(const QRectF &rect) |
301 | { |
302 | if (rect == m_innerTargetRect) |
303 | return; |
304 | m_innerTargetRect = rect; |
305 | markDirty(bits: DirtyGeometry); |
306 | } |
307 | |
308 | void QSGSoftwareInternalImageNode::setInnerSourceRect(const QRectF &rect) |
309 | { |
310 | if (rect == m_innerSourceRect) |
311 | return; |
312 | m_innerSourceRect = rect; |
313 | markDirty(bits: DirtyGeometry); |
314 | } |
315 | |
316 | void QSGSoftwareInternalImageNode::setSubSourceRect(const QRectF &rect) |
317 | { |
318 | if (rect == m_subSourceRect) |
319 | return; |
320 | m_subSourceRect = rect; |
321 | markDirty(bits: DirtyGeometry); |
322 | } |
323 | |
324 | void QSGSoftwareInternalImageNode::setTexture(QSGTexture *texture) |
325 | { |
326 | m_texture = texture; |
327 | m_cachedMirroredPixmapIsDirty = true; |
328 | m_textureIsLayer = static_cast<bool>(qobject_cast<QSGSoftwareLayer*>(object: texture)); |
329 | markDirty(bits: DirtyMaterial); |
330 | } |
331 | |
332 | void QSGSoftwareInternalImageNode::setMirror(bool mirrorHorizontally, bool mirrorVertically) |
333 | { |
334 | if (mirrorHorizontally == m_mirrorHorizontally && mirrorVertically == m_mirrorVertically) |
335 | return; |
336 | m_mirrorHorizontally = mirrorHorizontally; |
337 | m_mirrorVertically = mirrorVertically; |
338 | m_cachedMirroredPixmapIsDirty = true; |
339 | markDirty(bits: DirtyMaterial); |
340 | } |
341 | |
342 | void QSGSoftwareInternalImageNode::setMipmapFiltering(QSGTexture::Filtering /*filtering*/) |
343 | { |
344 | } |
345 | |
346 | void QSGSoftwareInternalImageNode::setFiltering(QSGTexture::Filtering filtering) |
347 | { |
348 | bool smooth = (filtering == QSGTexture::Linear); |
349 | if (smooth == m_smooth) |
350 | return; |
351 | |
352 | m_smooth = smooth; |
353 | markDirty(bits: DirtyMaterial); |
354 | } |
355 | |
356 | void QSGSoftwareInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) |
357 | { |
358 | bool tileHorizontal = (wrapMode == QSGTexture::Repeat); |
359 | if (tileHorizontal == m_tileHorizontal) |
360 | return; |
361 | |
362 | m_tileHorizontal = tileHorizontal; |
363 | markDirty(bits: DirtyMaterial); |
364 | } |
365 | |
366 | void QSGSoftwareInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) |
367 | { |
368 | bool tileVertical = (wrapMode == QSGTexture::Repeat); |
369 | if (tileVertical == m_tileVertical) |
370 | return; |
371 | |
372 | m_tileVertical = (wrapMode == QSGTexture::Repeat); |
373 | markDirty(bits: DirtyMaterial); |
374 | } |
375 | |
376 | void QSGSoftwareInternalImageNode::update() |
377 | { |
378 | if (m_cachedMirroredPixmapIsDirty) { |
379 | if (m_mirrorHorizontally || m_mirrorVertically || m_textureIsLayer) { |
380 | QTransform transform( |
381 | (m_mirrorHorizontally ? -1 : 1), 0, |
382 | 0 , (m_textureIsLayer ? -1 : 1) * (m_mirrorVertically ? -1 : 1), |
383 | 0 , 0 |
384 | ); |
385 | m_cachedMirroredPixmap = pixmap().transformed(transform); |
386 | } else { |
387 | //Cleanup cached pixmap if necessary |
388 | if (!m_cachedMirroredPixmap.isNull()) |
389 | m_cachedMirroredPixmap = QPixmap(); |
390 | } |
391 | m_cachedMirroredPixmapIsDirty = false; |
392 | } |
393 | } |
394 | |
395 | void QSGSoftwareInternalImageNode::preprocess() |
396 | { |
397 | bool doDirty = false; |
398 | QSGLayer *t = qobject_cast<QSGLayer *>(object: m_texture); |
399 | if (t) { |
400 | doDirty = t->updateTexture(); |
401 | markDirty(bits: DirtyGeometry); |
402 | } |
403 | if (doDirty) |
404 | markDirty(bits: DirtyMaterial); |
405 | m_cachedMirroredPixmapIsDirty = doDirty; |
406 | } |
407 | |
408 | static Qt::TileRule getTileRule(qreal factor) |
409 | { |
410 | int ifactor = qRound(d: factor); |
411 | if (qFuzzyCompare(p1: factor, p2: ifactor )) { |
412 | if (ifactor == 1 || ifactor == 0) |
413 | return Qt::StretchTile; |
414 | return Qt::RoundTile; |
415 | } |
416 | return Qt::RepeatTile; |
417 | } |
418 | |
419 | |
420 | void QSGSoftwareInternalImageNode::paint(QPainter *painter) |
421 | { |
422 | painter->setRenderHint(hint: QPainter::SmoothPixmapTransform, on: m_smooth); |
423 | // Disable antialiased clipping. It causes transformed tiles to have gaps. |
424 | painter->setRenderHint(hint: QPainter::Antialiasing, on: false); |
425 | |
426 | const QPixmap &pm = m_mirrorHorizontally || m_mirrorVertically || m_textureIsLayer ? m_cachedMirroredPixmap : pixmap(); |
427 | |
428 | if (m_innerTargetRect != m_targetRect) { |
429 | // border image |
430 | QMargins margins(m_innerTargetRect.left() - m_targetRect.left(), m_innerTargetRect.top() - m_targetRect.top(), |
431 | m_targetRect.right() - m_innerTargetRect.right(), m_targetRect.bottom() - m_innerTargetRect.bottom()); |
432 | QSGSoftwareHelpers::QTileRules tilerules(getTileRule(factor: m_subSourceRect.width()), getTileRule(factor: m_subSourceRect.height())); |
433 | QSGSoftwareHelpers::qDrawBorderPixmap(painter, targetRect: m_targetRect.toRect(), targetMarginsIn: margins, pixmap: pm, sourceRect: QRect(0, 0, pm.width(), pm.height()), |
434 | sourceMarginsIn: margins, rules: tilerules, hints: QSGSoftwareHelpers::QDrawBorderPixmap::DrawingHints{}); |
435 | return; |
436 | } |
437 | |
438 | if (m_tileHorizontal || m_tileVertical) { |
439 | painter->save(); |
440 | qreal sx = m_targetRect.width()/(m_subSourceRect.width()*pm.width()); |
441 | qreal sy = m_targetRect.height()/(m_subSourceRect.height()*pm.height()); |
442 | painter->setTransform(transform: QTransform::fromScale(dx: sx, dy: sy), combine: true); |
443 | painter->drawTiledPixmap(rect: QRectF(m_targetRect.x()/sx, m_targetRect.y()/sy, m_targetRect.width()/sx, m_targetRect.height()/sy), |
444 | pm, |
445 | offset: QPointF(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height())); |
446 | painter->restore(); |
447 | } else { |
448 | QRectF sr(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height(), |
449 | m_subSourceRect.width()*pm.width(), m_subSourceRect.height()*pm.height()); |
450 | painter->drawPixmap(targetRect: m_targetRect, pixmap: pm, sourceRect: sr); |
451 | } |
452 | } |
453 | |
454 | |
455 | QRectF QSGSoftwareInternalImageNode::rect() const |
456 | { |
457 | return m_targetRect; |
458 | } |
459 | |
460 | const QPixmap &QSGSoftwareInternalImageNode::pixmap() const |
461 | { |
462 | if (QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture*>(object: m_texture)) |
463 | return pt->pixmap(); |
464 | if (QSGSoftwareLayer *layer = qobject_cast<QSGSoftwareLayer*>(object: m_texture)) |
465 | return layer->pixmap(); |
466 | Q_ASSERT(m_texture == nullptr); |
467 | static const QPixmap nullPixmap; |
468 | return nullPixmap; |
469 | } |
470 | |
471 | QT_END_NAMESPACE |
472 | |