620void QQuickImage::updatePaintedGeometry()
624 if (d->fillMode == PreserveAspectFit) {
625 if (!d->currentPix->width() || !d->currentPix->height()) {
626 setImplicitSize(0, 0);
629 const qreal pixWidth = d->currentPix->width() / d->devicePixelRatio;
630 const qreal pixHeight = d->currentPix->height() / d->devicePixelRatio;
631 const qreal w = widthValid() ? width() : pixWidth;
632 const qreal widthScale = w / pixWidth;
633 const qreal h = heightValid() ? height() : pixHeight;
634 const qreal heightScale = h / pixHeight;
635 if (widthScale <= heightScale) {
637 d->paintedHeight = widthScale * pixHeight;
638 }
else if (heightScale < widthScale) {
639 d->paintedWidth = heightScale * pixWidth;
640 d->paintedHeight = h;
642 const qreal iHeight = (widthValid() && !heightValid()) ? d->paintedHeight : pixHeight;
643 const qreal iWidth = (heightValid() && !widthValid()) ? d->paintedWidth : pixWidth;
644 setImplicitSize(iWidth, iHeight);
646 }
else if (d->fillMode == PreserveAspectCrop) {
647 if (!d->currentPix->width() || !d->currentPix->height())
649 const qreal pixWidth = d->currentPix->width() / d->devicePixelRatio;
650 const qreal pixHeight = d->currentPix->height() / d->devicePixelRatio;
651 qreal widthScale = width() / pixWidth;
652 qreal heightScale = height() / pixHeight;
653 if (widthScale < heightScale) {
654 widthScale = heightScale;
655 }
else if (heightScale < widthScale) {
656 heightScale = widthScale;
659 d->paintedHeight = heightScale * pixHeight;
660 d->paintedWidth = widthScale * pixWidth;
661 }
else if (d->fillMode == Pad) {
662 d->paintedWidth = d->currentPix->width() / d->devicePixelRatio;
663 d->paintedHeight = d->currentPix->height() / d->devicePixelRatio;
665 d->paintedWidth = width();
666 d->paintedHeight = height();
668 emit paintedGeometryChanged();
727QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
731 QSGTexture *texture = d->sceneGraphRenderContext()->textureForFactory(d->currentPix->textureFactory(), window());
735 d->provider->m_smooth = d->smooth;
736 d->provider->m_mipmap = d->mipmap;
737 d->provider->updateTexture(texture);
740 if (!texture || width() <= 0 || height() <= 0) {
745 QSGInternalImageNode *node =
static_cast<QSGInternalImageNode *>(oldNode);
747 d->pixmapChanged =
true;
748 node = d->sceneGraphContext()->createInternalImageNode(d->sceneGraphRenderContext());
753 QSGTexture::WrapMode hWrap = QSGTexture::ClampToEdge;
754 QSGTexture::WrapMode vWrap = QSGTexture::ClampToEdge;
756 qreal pixWidth = (d->fillMode == PreserveAspectFit) ? d->paintedWidth : d->currentPix->width() / d->devicePixelRatio;
757 qreal pixHeight = (d->fillMode == PreserveAspectFit) ? d->paintedHeight : d->currentPix->height() / d->devicePixelRatio;
760 if (d->hAlign == QQuickImage::AlignHCenter)
761 xOffset = (width() - pixWidth) / 2;
762 else if (d->hAlign == QQuickImage::AlignRight)
763 xOffset = qCeil(width() - pixWidth);
766 if (d->vAlign == QQuickImage::AlignVCenter)
767 yOffset = (height() - pixHeight) / 2;
768 else if (d->vAlign == QQuickImage::AlignBottom)
769 yOffset = qCeil(height() - pixHeight);
771 switch (d->fillMode) {
773 targetRect = QRectF(0, 0, width(), height());
774 sourceRect = d->currentPix->rect();
777 case PreserveAspectFit:
778 targetRect = QRectF(xOffset, yOffset, d->paintedWidth, d->paintedHeight);
779 sourceRect = d->currentPix->rect();
782 case PreserveAspectCrop: {
783 targetRect = QRectF(0, 0, width(), height());
784 qreal wscale = width() / qreal(d->currentPix->width());
785 qreal hscale = height() / qreal(d->currentPix->height());
787 if (wscale > hscale) {
788 int src = (hscale / wscale) * qreal(d->currentPix->height());
790 if (d->vAlign == QQuickImage::AlignVCenter)
791 y = qCeil((d->currentPix->height() - src) / 2.);
792 else if (d->vAlign == QQuickImage::AlignBottom)
793 y = qCeil(d->currentPix->height() - src);
794 sourceRect = QRectF(0, y, d->currentPix->width(), src);
797 int src = (wscale / hscale) * qreal(d->currentPix->width());
799 if (d->hAlign == QQuickImage::AlignHCenter)
800 x = qCeil((d->currentPix->width() - src) / 2.);
801 else if (d->hAlign == QQuickImage::AlignRight)
802 x = qCeil(d->currentPix->width() - src);
803 sourceRect = QRectF(x, 0, src, d->currentPix->height());
809 targetRect = QRectF(0, 0, width(), height());
810 sourceRect = QRectF(-xOffset, -yOffset, width(), height());
811 hWrap = QSGTexture::Repeat;
812 vWrap = QSGTexture::Repeat;
815 case TileHorizontally:
816 targetRect = QRectF(0, 0, width(), height());
817 sourceRect = QRectF(-xOffset, 0, width(), d->currentPix->height());
818 hWrap = QSGTexture::Repeat;
822 targetRect = QRectF(0, 0, width(), height());
823 sourceRect = QRectF(0, -yOffset, d->currentPix->width(), height());
824 vWrap = QSGTexture::Repeat;
828 qreal w = qMin(qreal(pixWidth), width());
829 qreal h = qMin(qreal(pixHeight), height());
830 qreal x = (pixWidth > width()) ? -xOffset : 0;
831 qreal y = (pixHeight > height()) ? -yOffset : 0;
832 targetRect = QRectF(x + xOffset, y + yOffset, w, h);
833 sourceRect = QRectF(x, y, w, h);
837 qreal nsWidth = (hWrap == QSGTexture::Repeat || d->fillMode == Pad) ? d->currentPix->width() / d->devicePixelRatio : d->currentPix->width();
838 qreal nsHeight = (vWrap == QSGTexture::Repeat || d->fillMode == Pad) ? d->currentPix->height() / d->devicePixelRatio : d->currentPix->height();
839 QRectF nsrect(sourceRect.x() / nsWidth,
840 sourceRect.y() / nsHeight,
841 sourceRect.width() / nsWidth,
842 sourceRect.height() / nsHeight);
844 if (targetRect.isEmpty()
845 || !qt_is_finite(targetRect.width()) || !qt_is_finite(targetRect.height())
847 || !qt_is_finite(nsrect.width()) || !qt_is_finite(nsrect.height())) {
852 if (d->pixmapChanged) {
855 if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat || d->mipmap))
856 node->setTexture(texture->removedFromAtlas());
858 node->setTexture(texture);
859 d->pixmapChanged =
false;
862 node->setMipmapFiltering(d->mipmap ? QSGTexture::Linear : QSGTexture::None);
863 node->setHorizontalWrapMode(hWrap);
864 node->setVerticalWrapMode(vWrap);
865 node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
867 node->setTargetRect(targetRect);
868 node->setInnerTargetRect(targetRect);
869 node->setSubSourceRect(nsrect);
870 node->setMirror(d->mirrorHorizontally, d->mirrorVertically);
871 node->setAntialiasing(d->antialiasing);