From 2dbe43fe89991e1429893d0720e71b40eb386470 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 27 Dec 2012 01:21:39 +0100 Subject: [PATCH] fixed the flickering white border issue when scaling CoverImages --- data/qml/tomahawkimports/CoverImage.qml | 127 +++++++++--------- .../widgets/DeclarativeCoverArtProvider.cpp | 97 +++++++++++-- 2 files changed, 149 insertions(+), 75 deletions(-) diff --git a/data/qml/tomahawkimports/CoverImage.qml b/data/qml/tomahawkimports/CoverImage.qml index 51946a4ab..518137aac 100644 --- a/data/qml/tomahawkimports/CoverImage.qml +++ b/data/qml/tomahawkimports/CoverImage.qml @@ -53,43 +53,74 @@ Item { } } + Rectangle { + id: itemShadow + color: backgroundColor + anchors.fill: parent + + //opacity: 1 - itemBrightness + + Behavior on opacity { + NumberAnimation { easing.type: Easing.Linear; duration: 300 } + } + } + Component { id: coverImage - Rectangle { - color: "white" - border.color: borderColor - border.width: borderWidth + Item { + property bool isMirror: false Image { anchors.fill: parent - //anchors.margins: borderWidth - source: "image://albumart/" + artworkId + source: "image://albumart/" + artworkId + (isMirror ? "-mirror" : "") + (showLabels ? "-labels" : "") smooth: root.smooth - } - - Rectangle { - id: itemGlow - color: "white" - anchors.fill: parent - - opacity: mouseArea.containsMouse ? .2 : 0 - + opacity: itemBrightness Behavior on opacity { - NumberAnimation { easing.type: Easing.Linear; duration: 300 } + NumberAnimation { duration: 300 } } } Rectangle { - id: textBackground - anchors { left: parent.left; right: parent.right; bottom: parent.bottom } - anchors.margins: -1 - height: (artistText.height + trackText.height) * 3 - opacity: showLabels ? 1 : 0 - gradient: Gradient { + id: itemGlow + anchors.fill: parent + anchors.topMargin: isMirror ? parent.height / 2 : 0 + + opacity: (mouseArea.containsMouse ? .2 : 0) + + Gradient { + id: glowGradient + GradientStop { position: 0.0; color: "white" } + GradientStop { position: 0.7; color: "white" } + GradientStop { position: 0.8; color: "#00000000" } + GradientStop { position: 1.0; color: "#00000000" } + } + Gradient { + id: mirrorGlowGradient GradientStop { position: 0.0; color: "#00000000" } - GradientStop { position: 0.6; color: "#E1000000" } - GradientStop { position: 1.0; color: "#E1000000" } + GradientStop { position: 0.5; color: "#00000000" } + GradientStop { position: 1.0; color: "#44FFFFFF" } + } + + states: [ + State { + name: "mirrored"; when: isMirror + PropertyChanges { + target: itemGlow + gradient: mirrorGlowGradient + } + }, + State { + name: "normal"; when: !isMirror + PropertyChanges { + target: itemGlow + gradient: glowGradient + } + } + ] + + Behavior on opacity { + NumberAnimation { easing.type: Easing.Linear; duration: 300 } } } @@ -102,8 +133,11 @@ Item { anchors.margins: 2 horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight - opacity: showLabels ? 1 : 0 + opacity: showLabels ? itemBrightness * (isMirror ? 0.5 : 1): 0 font.pixelSize: root.height / 15 + Behavior on opacity { + NumberAnimation { duration: 300 } + } } Text { id: artistText @@ -114,8 +148,11 @@ Item { anchors.margins: root.height / 20 horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight - opacity: showLabels ? 1 : 0 + opacity: showLabels ? itemBrightness * (isMirror ? 0.5 : 1) : 0 font.pixelSize: trackText.text.length == 0 ? root.height / 10 : root.height / 15 + Behavior on opacity { + NumberAnimation { duration: 300 } + } } } @@ -129,6 +166,9 @@ Item { id: mirroredCover sourceComponent: parent.showMirror ? coverImage : undefined anchors.fill: parent + onLoaded: { + item.isMirror = true + } transform : [ Rotation { angle: 180; origin.y: root.height @@ -137,41 +177,6 @@ Item { ] } - Rectangle { - id: itemShadow - color: backgroundColor - anchors.fill: parent - //anchors.bottomMargin: - parent.height - - // scaling might be off a pixel... make sure that the shadow is at least as large as the image - anchors.leftMargin: -2 - anchors.rightMargin: -2 - anchors.topMargin: -2 - - opacity: 1 - itemBrightness - - Behavior on opacity { - NumberAnimation { easing.type: Easing.Linear; duration: 300 } - } - } - - Rectangle { - id: mirrorShadow - color: parent.backgroundColor - height: parent.height + 2 - width: parent.width + 4 - anchors.centerIn: parent - anchors.verticalCenterOffset: parent.height - visible: showMirror - - gradient: Gradient { - // TODO: no clue how to get the RGB component of the container rectangle color - // For now the Qt.rgba needs to be manually updated to match the backgroundColor 454e59 - GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, 1-mirrorBrightness) } - GradientStop { position: 0.5; color: backgroundColor } - } - } - Image { id: playButton visible: showPlayButton ? (mouseArea.containsMouse || currentlyPlaying) : false diff --git a/src/libtomahawk/widgets/DeclarativeCoverArtProvider.cpp b/src/libtomahawk/widgets/DeclarativeCoverArtProvider.cpp index 28b8901aa..49e743c86 100644 --- a/src/libtomahawk/widgets/DeclarativeCoverArtProvider.cpp +++ b/src/libtomahawk/widgets/DeclarativeCoverArtProvider.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Tomahawk { @@ -26,7 +27,6 @@ DeclarativeCoverArtProvider::~DeclarativeCoverArtProvider() QPixmap DeclarativeCoverArtProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) { - tDebug() << "requresting albumart" << id; // We always can generate it in the requested size int width = requestedSize.width() > 0 ? requestedSize.width() : 230; int height = requestedSize.height() > 0 ? requestedSize.height() : 230; @@ -36,21 +36,22 @@ QPixmap DeclarativeCoverArtProvider::requestPixmap(const QString &id, QSize *siz QPixmap cover; - tDebug() << "Getting by id:" << id << requestedSize; + tDebug() << "DeclarativeCoverArtprovider: Getting album art by id:" << id << requestedSize; - album_ptr album = Album::getByCoverId( id ); - if ( !album.isNull() ) - { - tDebug() << "Returning album cover:" << album->cover( *size ).isNull(); - cover = album->cover( *size ); - if ( cover.isNull() ) - { - tDebug() << Q_FUNC_INFO << "Returning default album image"; - cover = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultAlbumCover, TomahawkUtils::Original, *size ); - } + bool mirrored = false; + bool labeled = false; + + QString coverId = id; + if(coverId.contains("-mirror")) { + coverId.remove("-mirror"); + mirrored = true; + } + if(coverId.contains("-labels")) { + coverId.remove("-labels"); + labeled = true; } - artist_ptr artist = Artist::getByCoverId( id ); + artist_ptr artist = Artist::getByCoverId( coverId ); if ( !artist.isNull() ) { tDebug() << "Returning artist cover:" << artist->cover( *size ).isNull(); @@ -62,12 +63,80 @@ QPixmap DeclarativeCoverArtProvider::requestPixmap(const QString &id, QSize *siz } } + if ( cover.isNull() ) + { + album_ptr album = Album::getByCoverId( coverId ); + if ( !album.isNull() ) + { + tDebug() << "Returning album cover:" << album->cover( *size ).isNull(); + cover = album->cover( *size ); + if ( cover.isNull() ) + { + tDebug() << Q_FUNC_INFO << "Returning default album image"; + cover = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultAlbumCover, TomahawkUtils::Original, *size ); + } + } + } + if ( cover.isNull() ) { tDebug() << Q_FUNC_INFO << "Returning default track image"; cover = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultTrackImage, TomahawkUtils::Original, *size ); } - return cover; + + QImage image(*size, QImage::Format_ARGB32); + + if(labeled) { + QImage coverImage(*size, QImage::Format_RGB32); + QPainter bgPainter(&coverImage); + bgPainter.drawPixmap(0, 0, size->width(), size->height(), cover); + + QColor c1; + c1.setRgb( 0, 0, 0 ); + c1.setAlphaF( 0.00 ); + QColor c2; + c2.setRgb( 0, 0, 0 ); + c2.setAlphaF( 0.88 ); + + QLinearGradient gradient( QPointF( 0, 0 ), QPointF( 0, 1 ) ); + gradient.setCoordinateMode( QGradient::ObjectBoundingMode ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.6, c2 ); + gradient.setColorAt( 1.0, c2 ); + + bgPainter.setPen( Qt::transparent ); + bgPainter.setBrush(QBrush(gradient)); + bgPainter.drawRect(0, size->height() * 0.7, size->width(), size->height() * 0.3); + cover = QPixmap::fromImage(coverImage); + } + + QPainter painter(&image); + if(!mirrored) { + image.fill(Qt::white); + painter.drawPixmap(0, 0, size->width(), size->height(), cover); + } else { + image.fill(QColor(0, 0, 0, 0)); + + // Lets paint half of the image in a fragment per line + int mirrorHeight = size->height() / 2; + int fragmentCount = mirrorHeight; + int fragmentHeight = mirrorHeight / fragmentCount; + + QPainter::PixmapFragment fragments[fragmentCount]; + + qreal fragmentOpacity = 0; + int fragmentStartY = size->height() - mirrorHeight; + for(int i = 0; i < fragmentCount; ++i) { + QPointF point = QPointF(size->width() / 2, fragmentStartY + (fragmentHeight / 2)); + QRectF sourceRect = QRectF(0, fragmentStartY, size->width(), fragmentHeight); + fragments[i] = QPainter::PixmapFragment::create(point, sourceRect, 1, 1, 0, fragmentOpacity); + fragmentOpacity += 0.5 / fragmentCount; + fragmentStartY += fragmentHeight; + } + painter.drawPixmapFragments(fragments, fragmentCount, cover); + } + + return QPixmap::fromImage(image); } }