diff options
author | Jonas Schnelli <jonas.schnelli@include7.ch> | 2014-11-06 16:28:29 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-12-16 11:15:05 +0100 |
commit | 54f2571a00632e9813b9fabb447c7cc80f74ad29 (patch) | |
tree | 61367fc9f103d08a4708a01fde086bbb8b98a4c1 /src/qt | |
parent | f3af0c898f1ba280761101844c4694c7427f304a (diff) |
Qt: HiDPI (retina) support for splash screen
- remove splash screen images (reduce binary size)
- dynamicly draw splash screen with available icon.
- remove testnet icon
- dynamicly colorize testnet icon
Diffstat (limited to 'src/qt')
-rw-r--r-- | src/qt/bitcoin.qrc | 3 | ||||
-rw-r--r-- | src/qt/networkstyle.cpp | 92 | ||||
-rw-r--r-- | src/qt/networkstyle.h | 10 | ||||
-rw-r--r-- | src/qt/res/bitcoin-qt-res.rc | 1 | ||||
-rw-r--r-- | src/qt/res/icons/bitcoin.png | bin | 32547 -> 350390 bytes | |||
-rwxr-xr-x | src/qt/res/icons/bitcoin_testnet.ico | bin | 45855 -> 0 bytes | |||
-rw-r--r-- | src/qt/res/icons/bitcoin_testnet.png | bin | 28227 -> 0 bytes | |||
-rw-r--r-- | src/qt/res/images/splash.png | bin | 43398 -> 0 bytes | |||
-rw-r--r-- | src/qt/res/images/splash_testnet.png | bin | 34142 -> 0 bytes | |||
-rw-r--r-- | src/qt/splashscreen.cpp | 41 |
10 files changed, 119 insertions, 28 deletions
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index cd71b4b3fc..b54f2e2ed6 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -25,7 +25,6 @@ <file alias="editpaste">res/icons/editpaste.png</file> <file alias="editcopy">res/icons/editcopy.png</file> <file alias="add">res/icons/add.png</file> - <file alias="bitcoin_testnet">res/icons/bitcoin_testnet.png</file> <file alias="edit">res/icons/edit.png</file> <file alias="history">res/icons/history.png</file> <file alias="overview">res/icons/overview.png</file> @@ -52,8 +51,6 @@ </qresource> <qresource prefix="/images"> <file alias="about">res/images/about.png</file> - <file alias="splash">res/images/splash.png</file> - <file alias="splash_testnet">res/images/splash_testnet.png</file> </qresource> <qresource prefix="/movies"> <file alias="spinner-000">res/movies/spinner-000.png</file> diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index 62c44703f4..b8112799df 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -11,22 +11,22 @@ static const struct { const char *networkId; const char *appName; - const char *appIcon; + const int iconColorHueShift; + const int iconColorSaturationReduction; const char *titleAddText; - const char *splashImage; } network_styles[] = { - {"main", QAPP_APP_NAME_DEFAULT, ":/icons/bitcoin", "", ":/images/splash"}, - {"test", QAPP_APP_NAME_TESTNET, ":/icons/bitcoin_testnet", QT_TRANSLATE_NOOP("SplashScreen", "[testnet]"), ":/images/splash_testnet"}, - {"regtest", QAPP_APP_NAME_TESTNET, ":/icons/bitcoin_testnet", "[regtest]", ":/images/splash_testnet"} + {"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""}, + {"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")}, + {"regtest", QAPP_APP_NAME_TESTNET, 70, 30, "[regtest]"} }; static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles); // titleAddText needs to be const char* for tr() -NetworkStyle::NetworkStyle(const QString &appName, const QString &appIcon, const char *titleAddText, const QString &splashImage): +NetworkStyle::NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText): appName(appName), - appIcon(appIcon), - titleAddText(qApp->translate("SplashScreen", titleAddText)), - splashImage(splashImage) + iconColorHueShift(iconColorHueShift), + iconColorSaturationReduction(iconColorSaturationReduction), + titleAddText(qApp->translate("SplashScreen", titleAddText)) { } @@ -38,10 +38,78 @@ const NetworkStyle *NetworkStyle::instantiate(const QString &networkId) { return new NetworkStyle( network_styles[x].appName, - network_styles[x].appIcon, - network_styles[x].titleAddText, - network_styles[x].splashImage); + network_styles[x].iconColorHueShift, + network_styles[x].iconColorSaturationReduction, + network_styles[x].titleAddText); } } return 0; } + +QIcon NetworkStyle::getAppIcon() const +{ + return getAppIcon(QSize(256,256)); +} + +QIcon NetworkStyle::getAppIcon(const QSize size) const +{ + // load pixmap + QPixmap pixmap(":/icons/bitcoin"); + + if(pixmap.size().width() != size.width() && pixmap.size().height() != size.height()) + { + QPixmap scaledPixmap = pixmap.scaled(size, Qt::KeepAspectRatio); + if(!scaledPixmap.isNull()) + { + pixmap = scaledPixmap; + } + } + + if(iconColorHueShift != 0 && iconColorSaturationReduction != 0) + { + // copy the pixmap because on linux the original pixmap will be affected + pixmap = pixmap.copy(); + + // generate QImage from QPixmap + QImage img = pixmap.toImage(); + + int h,s,l,a; + + // traverse though lines + for(int y=0;y<img.height();y++) + { + QRgb *scL = reinterpret_cast< QRgb *>( img.scanLine( y ) ); + + // loop through pixels + for(int x=0;x<img.width();x++) + { + // preserve alpha because QColor::getHsl doesen't return the alpha value + a = qAlpha(scL[x]); + QColor col(scL[x]); + + // get hue value + col.getHsl(&h,&s,&l); + + // rotate color on RGB color circle + // 70° should end up with the typical "testnet" green + h+=iconColorHueShift; + + // change saturation value + if(s>iconColorSaturationReduction) + { + s -= iconColorSaturationReduction; + } + col.setHsl(h,s,l,a); + + // set the pixel + scL[x] = col.rgba(); + } + } + + //convert back to QPixmap + pixmap.convertFromImage(img); + } + + QIcon icon(pixmap); + return icon; +} diff --git a/src/qt/networkstyle.h b/src/qt/networkstyle.h index e49b86c950..2bfb3c1d55 100644 --- a/src/qt/networkstyle.h +++ b/src/qt/networkstyle.h @@ -17,17 +17,17 @@ public: static const NetworkStyle *instantiate(const QString &networkId); const QString &getAppName() const { return appName; } - const QIcon &getAppIcon() const { return appIcon; } const QString &getTitleAddText() const { return titleAddText; } - const QPixmap &getSplashImage() const { return splashImage; } + QIcon getAppIcon() const; + QIcon getAppIcon(const QSize size) const; private: - NetworkStyle(const QString &appName, const QString &appIcon, const char *titleAddText, const QString &splashImage); + NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText); QString appName; - QIcon appIcon; + int iconColorHueShift; + int iconColorSaturationReduction; QString titleAddText; - QPixmap splashImage; }; #endif // BITCOIN_QT_NETWORKSTYLE_H diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc index 809235be5f..a72dfc02f6 100644 --- a/src/qt/res/bitcoin-qt-res.rc +++ b/src/qt/res/bitcoin-qt-res.rc @@ -1,5 +1,4 @@ IDI_ICON1 ICON DISCARDABLE "icons/bitcoin.ico" -IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico" #include <windows.h> // needed for VERSIONINFO #include "../../clientversion.h" // holds the needed client version information diff --git a/src/qt/res/icons/bitcoin.png b/src/qt/res/icons/bitcoin.png Binary files differindex ce5fbb0c2c..705a20260a 100644 --- a/src/qt/res/icons/bitcoin.png +++ b/src/qt/res/icons/bitcoin.png diff --git a/src/qt/res/icons/bitcoin_testnet.ico b/src/qt/res/icons/bitcoin_testnet.ico Binary files differdeleted file mode 100755 index d67d9d5ce5..0000000000 --- a/src/qt/res/icons/bitcoin_testnet.ico +++ /dev/null diff --git a/src/qt/res/icons/bitcoin_testnet.png b/src/qt/res/icons/bitcoin_testnet.png Binary files differdeleted file mode 100644 index 1202021f53..0000000000 --- a/src/qt/res/icons/bitcoin_testnet.png +++ /dev/null diff --git a/src/qt/res/images/splash.png b/src/qt/res/images/splash.png Binary files differdeleted file mode 100644 index 3f2b2fb2bf..0000000000 --- a/src/qt/res/images/splash.png +++ /dev/null diff --git a/src/qt/res/images/splash_testnet.png b/src/qt/res/images/splash_testnet.png Binary files differdeleted file mode 100644 index 786dc9c3bb..0000000000 --- a/src/qt/res/images/splash_testnet.png +++ /dev/null diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index b4b81440ca..bfc69636bb 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -19,6 +19,7 @@ #include <QCloseEvent> #include <QDesktopWidget> #include <QPainter> +#include <QRadialGradient> SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) : QWidget(0, f), curAlignment(0) @@ -30,6 +31,10 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) int titleCopyrightVSpace = 40; float fontFactor = 1.0; + float devicePixelRatio = 1.0; +#if QT_VERSION > 0x050100 + devicePixelRatio = ((QGuiApplication*)QCoreApplication::instance())->devicePixelRatio(); +#endif // define text to place QString titleText = tr("Bitcoin Core"); @@ -39,12 +44,34 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) QString font = "Arial"; - // load the bitmap for writing some text over it - pixmap = networkStyle->getSplashImage(); + // create a bitmap according to device pixelratio + QSize splashSize(480*devicePixelRatio,320*devicePixelRatio); + pixmap = QPixmap(splashSize); + +#if QT_VERSION > 0x050100 + // change to HiDPI if it makes sense + pixmap.setDevicePixelRatio(devicePixelRatio); +#endif QPainter pixPaint(&pixmap); pixPaint.setPen(QColor(100,100,100)); + // draw a slighly radial gradient + QRadialGradient gradient(QPoint(0,0), splashSize.width()/devicePixelRatio); + gradient.setColorAt(0, Qt::white); + gradient.setColorAt(1, QColor(247,247,247)); + QRect rGradient(QPoint(0,0), splashSize); + pixPaint.fillRect(rGradient, gradient); + + // draw the bitcoin icon, expected size of PNG: 1024x1024 + QRect rectIcon(QPoint(-150,-122), QSize(430,430)); + + const QSize requiredSize(1024,1024); + QIcon appIcon = networkStyle->getAppIcon(requiredSize); + QPixmap icon(appIcon.pixmap(requiredSize)); + + pixPaint.drawPixmap(rectIcon, icon); + // check font size and drawing with pixPaint.setFont(QFont(font, 33*fontFactor)); QFontMetrics fm = pixPaint.fontMetrics(); @@ -57,7 +84,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) pixPaint.setFont(QFont(font, 33*fontFactor)); fm = pixPaint.fontMetrics(); titleTextWidth = fm.width(titleText); - pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight,paddingTop,titleText); + pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight,paddingTop,titleText); pixPaint.setFont(QFont(font, 15*fontFactor)); @@ -68,11 +95,11 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) pixPaint.setFont(QFont(font, 10*fontFactor)); titleVersionVSpace -= 5; } - pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText); + pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText); // draw copyright stuff pixPaint.setFont(QFont(font, 10*fontFactor)); - pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText); + pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText); // draw additional text if special network if(!titleAddText.isEmpty()) { @@ -81,7 +108,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) pixPaint.setFont(boldFont); fm = pixPaint.fontMetrics(); int titleAddTextWidth = fm.width(titleAddText); - pixPaint.drawText(pixmap.width()-titleAddTextWidth-10,15,titleAddText); + pixPaint.drawText(pixmap.width()/devicePixelRatio-titleAddTextWidth-10,15,titleAddText); } pixPaint.end(); @@ -90,7 +117,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) setWindowTitle(titleText + " " + titleAddText); // Resize window and move to center of desktop, disallow resizing - QRect r(QPoint(), pixmap.size()); + QRect r(QPoint(), QSize(pixmap.size().width()/devicePixelRatio,pixmap.size().height()/devicePixelRatio)); resize(r.size()); setFixedSize(r.size()); move(QApplication::desktop()->screenGeometry().center() - r.center()); |