21 explicit Texture(QSGTexture *t,
const qint8 key)
25 MaskTextureCache::instance()->m_cache[cacheKey] =
this;
29 MaskTextureCache::instance()->m_cache.remove(cacheKey);
34 QSGTexture *texture =
nullptr;
37 typedef QExplicitlySharedDataPointer<Texture> TextureData;
46 TextureData getTexture(QSGRenderContext *context,
int radius,
bool antialiasing)
49 qint8 to_cache_key_key = ((antialiasing << 7) | radius);
50 Texture *texture =
nullptr;
52 if (m_radiusToCacheKey.contains(to_cache_key_key)) {
53 texture = m_cache.value(m_radiusToCacheKey.value(to_cache_key_key));
58 QImage mask(QSize(radius + 1, radius + 1), QImage::Format_ARGB32);
59 mask.fill(Qt::transparent);
61 const QColor maskColor = Qt::white;
64 const QRect r = mask.rect();
65 pa.drawLine(r.bottomLeft(), r.bottomRight());
66 pa.drawLine(r.topRight(), r.bottomRight());
67 pa.setRenderHint(QPainter::Antialiasing, antialiasing);
69 path.moveTo(radius, radius);
70 path.arcTo(0, 0, radius * 2, radius * 2, 90, 90);
71 path.lineTo(radius, radius);
73 pa.fillPath(path, maskColor);
76 texture =
new Texture(context->createTexture(mask), to_cache_key_key);
77 texture->texture->setFiltering(QSGTexture::Nearest);
78 texture->texture->setVerticalWrapMode(QSGTexture::ClampToEdge);
79 texture->texture->setHorizontalWrapMode(QSGTexture::ClampToEdge);
81 m_radiusToCacheKey[to_cache_key_key] = texture->cacheKey;
85 TextureData data(texture);
95 QHash<qint8, Texture*> m_cache;
96 QMap<int, qint8> m_radiusToCacheKey;
144 DirtySourceSizeRatio = 0x1,
145 DirtyMaskTexture = 0x2,
146 DirtyMaskSizeRatio = 0x4,
147 DirtyMaskOffset = 0x8,
148 DirtyContentNode = 0x10
150 Q_DECLARE_FLAGS(DirtyState, DirtyStateBit)
160 inline void markDirtys(DirtyState states) {
161 dirtyState |= states;
163 inline void markDirty(DirtyStateBit state,
bool dirty =
true) {
167 dirtyState &= ~state;
172 void initSourceItem(QQuickItem *old, QQuickItem *item);
174 void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange data,
const QRectF &)
override;
176 inline const QVector2D &getSoureSizeRatio() {
177 if (Q_LIKELY(!dirtyState.testFlag(DirtySourceSizeRatio))) {
178 return soureSizeRatio;
181 Q_ASSERT(sourceItem);
182 markDirty(DirtySourceSizeRatio,
false);
183 const auto &sr = getSourceRect();
184 soureSizeRatio.setX(
static_cast<float>(sourceItem->width() / sr.width()));
185 soureSizeRatio.setY(
static_cast<float>(sourceItem->height() / sr.height()));
186 return soureSizeRatio;
188 inline const QVector2D &getMaskSizeRatio() {
189 if (Q_LIKELY(!dirtyState.testFlag(DirtyMaskSizeRatio))) {
190 return maskSizeRatio;
193 markDirty(DirtyMaskSizeRatio,
false);
194 const auto &sr = getSourceRect();
195 maskSizeRatio.setX(radius <= 0 ? sr.width() :
static_cast<float>(sr.width() /
static_cast<qreal
>(radius)));
196 maskSizeRatio.setY(radius <= 0 ? sr.height() :
static_cast<float>(sr.height() /
static_cast<qreal
>(radius)));
197 return maskSizeRatio;
199 inline const QVector2D &getMaskOffset() {
200 if (Q_LIKELY(!dirtyState.testFlag(DirtyMaskOffset))) {
204 Q_ASSERT(sourceItem && sourceItem->width() > 0 && sourceItem->height() > 0);
205 markDirty(DirtyMaskOffset,
false);
206 auto offset = getSourceRect().topLeft();
207 maskOffset.setX(
static_cast<float>(offset.x() / sourceItem->width()));
208 maskOffset.setY(
static_cast<float>(offset.y() / sourceItem->height()));
212 inline QSGTexture *textureForRadiusMask()
214 if (Q_UNLIKELY(dirtyState.testFlag(DirtyMaskTexture) || !maskTexture)) {
215 QQuickItemPrivate *d = QQuickItemPrivate::get(q_func());
216 maskTexture = MaskTextureCache::instance()->getTexture(d->sceneGraphRenderContext(),
217 qRound(radius * d->window->effectiveDevicePixelRatio()),
220 markDirty(DirtyMaskTexture,
false);
223 return maskTexture->texture;
227 inline bool needMaskNode()
const {
229#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
230 || compositionMode != DefaultCompositionMode
235 inline bool updateOffset(
const QPointF &offset) {
236 if (this->offset == offset)
238 this->offset = offset;
239 markDirty(DirtyMaskOffset);
243 inline QRectF getSourceRect()
const {
244 QRectF sr = sourceRect;
245 if (!sourceRect.isValid()) {
246 sr = QRectF(QPointF(0, 0), q_func()->size());
249 return fixed ? sr : sr.translated(offset);
253 inline void updateSourceRect(T *node)
const {
254 const QSizeF &textureSize = node->texture()->textureSize();
255 qreal xScale = textureSize.width() / sourceItem->width();
256 qreal yScale = textureSize.height() / sourceItem->height();
258 const QRectF &sourceRect = getSourceRect();
260 node->setSourceRect(QRectF(sourceRect.x() * xScale, sourceRect.y() * yScale,
261 sourceRect.width() * xScale, sourceRect.height() * yScale));
266 void updateUsePreprocess()
const;
267 void ensureTexture();
271 QPointer<QQuickItem> sourceItem;
272 QAtomicPointer<PreprocessNode> preprocessNode;
274 QVector2D soureSizeRatio;
276 MaskTextureCache::TextureData maskTexture;
278 QVector2D maskSizeRatio;
280 QVector2D maskOffset;
281 QMetaObject::Connection textureChangedConnection;
283 QPointF offset = QPointF(0, 0);
286 DirtyState dirtyState = DirtyNothing;
290 bool hideSource =
false;
291 QSGLayer *texture =
nullptr;
294#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
295 constexpr static QPainter::CompositionMode DefaultCompositionMode = QPainter::CompositionMode_SourceOver;
296 QPainter::CompositionMode compositionMode = DefaultCompositionMode;
Definition dquickitemviewport_p.h:103
Definition dquickitemviewport_p.h:19
Definition dquickitemviewport_p.h:17