Fix Hdpi Icon Scaling
Menu icons (16x16) were difficult to repurpose for toolbars because they would resize to fit 20x20, this change composites them onto a 20x20 pixmap so this no longer happens, this seems to make the whole process more stable
This commit is contained in:
parent
8280906d92
commit
9fded30646
3 changed files with 129 additions and 27 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -13,6 +13,7 @@ Thumbs.db
|
||||||
|
|
||||||
# bundled thirdparty libraries
|
# bundled thirdparty libraries
|
||||||
/thirdparty/boost
|
/thirdparty/boost
|
||||||
|
/thirdparty/libjpeg-turbo64
|
||||||
/thirdparty/lzo
|
/thirdparty/lzo
|
||||||
/thirdparty/tiff-4.0.3
|
/thirdparty/tiff-4.0.3
|
||||||
/thirdparty/LibJPEG/jpeg-9
|
/thirdparty/LibJPEG/jpeg-9
|
||||||
|
|
|
@ -113,6 +113,10 @@ QPixmap DVAPI recolorPixmap(
|
||||||
QPixmap pixmap, QColor color = Preferences::instance()->getIconTheme()
|
QPixmap pixmap, QColor color = Preferences::instance()->getIconTheme()
|
||||||
? Qt::black
|
? Qt::black
|
||||||
: Qt::white);
|
: Qt::white);
|
||||||
|
QPixmap DVAPI compositePixmap(QPixmap pixmap, qreal opacity,
|
||||||
|
int canvasWidth = 20, int canvasHeight = 20,
|
||||||
|
int iconWidth = 16, int iconHeight = 16,
|
||||||
|
int offset = 0);
|
||||||
QIcon DVAPI createQIcon(const char *iconSVGName, bool useFullOpacity = false);
|
QIcon DVAPI createQIcon(const char *iconSVGName, bool useFullOpacity = false);
|
||||||
QIcon DVAPI createQIconPNG(const char *iconPNGName);
|
QIcon DVAPI createQIconPNG(const char *iconPNGName);
|
||||||
QIcon DVAPI createQIconOnOffPNG(const char *iconPNGName, bool withOver = true);
|
QIcon DVAPI createQIconOnOffPNG(const char *iconPNGName, bool withOver = true);
|
||||||
|
|
|
@ -260,46 +260,143 @@ QPixmap recolorPixmap(QPixmap pixmap, QColor color) {
|
||||||
.rgba();
|
.rgba();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pixmap = QPixmap::fromImage(img);
|
pixmap = QPixmap::fromImage(img);
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
QPixmap compositePixmap(QPixmap pixmap, qreal opacity, int canvasWidth,
|
||||||
|
int canvasHeight, int iconWidth, int iconHeight,
|
||||||
|
int offset) {
|
||||||
|
/* Creates a composite pixmap from two pixmaps. The canvas controls the final
|
||||||
|
* size, whereas pixmap is the image to be composited ontop. You can control
|
||||||
|
* the position of pixmap by setting an offset (top-left), default is 0. */
|
||||||
|
|
||||||
|
static int devPixRatio = getDevPixRatio();
|
||||||
|
|
||||||
|
QPixmap canvas(canvasWidth, canvasHeight);
|
||||||
|
canvas.fill(Qt::transparent); // set this to a color to debug
|
||||||
|
QPixmap combined(canvasWidth, canvasHeight);
|
||||||
|
combined.fill(Qt::transparent);
|
||||||
|
if (!pixmap.isNull()) {
|
||||||
|
QPainter painter;
|
||||||
|
painter.begin(&combined);
|
||||||
|
QRect canvasRect(0, 0, canvasWidth, canvasHeight);
|
||||||
|
painter.drawPixmap(canvasRect, canvas);
|
||||||
|
painter.setOpacity(opacity);
|
||||||
|
QRect iconRect(offset, offset, iconWidth, iconHeight);
|
||||||
|
painter.drawPixmap(iconRect, pixmap);
|
||||||
|
painter.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
QIcon createQIcon(const char *iconSVGName, bool useFullOpacity) {
|
QIcon createQIcon(const char *iconSVGName, bool useFullOpacity) {
|
||||||
QIcon normalIcon = QIcon::fromTheme(iconSVGName);
|
static int devPixRatio = getDevPixRatio();
|
||||||
|
|
||||||
QSize iconSize(0, 0); // Get largest
|
// get icon size
|
||||||
for (QList<QSize> sizes = normalIcon.availableSizes(); !sizes.isEmpty();
|
QIcon themeIcon = QIcon::fromTheme(iconSVGName);
|
||||||
|
QSize iconSize(0, 0);
|
||||||
|
for (QList<QSize> sizes = themeIcon.availableSizes(); !sizes.isEmpty();
|
||||||
sizes.removeFirst())
|
sizes.removeFirst())
|
||||||
if (sizes.first().width() > iconSize.width()) iconSize = sizes.first();
|
if (sizes.first().width() > iconSize.width()) iconSize = sizes.first();
|
||||||
|
|
||||||
const qreal offOpacity = 0.8;
|
QString overStr = QString(iconSVGName) + "_over";
|
||||||
const qreal disabledOpacity = 0.15;
|
QString onStr = QString(iconSVGName) + "_on";
|
||||||
QString overStr = QString(iconSVGName) + "_over";
|
QPixmap themeIconPixmap = recolorPixmap(themeIcon.pixmap(iconSize));
|
||||||
QString onStr = QString(iconSVGName) + "_on";
|
QPixmap overPixmap =
|
||||||
QPixmap normalPm = recolorPixmap(normalIcon.pixmap(iconSize));
|
recolorPixmap(QIcon::fromTheme(overStr).pixmap(iconSize));
|
||||||
QPixmap overPm = recolorPixmap(QIcon::fromTheme(overStr).pixmap(iconSize));
|
QPixmap onPixmap = recolorPixmap(QIcon::fromTheme(onStr).pixmap(iconSize));
|
||||||
QPixmap onPm = recolorPixmap(QIcon::fromTheme(onStr).pixmap(iconSize));
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
|
|
||||||
// Off
|
// build icon
|
||||||
icon.addPixmap(useFullOpacity ? normalPm : setOpacity(normalPm, offOpacity),
|
for (int devPixRatio = 1; devPixRatio <= 2; devPixRatio++) {
|
||||||
QIcon::Normal, QIcon::Off);
|
int iconW = themeIconPixmap.width();
|
||||||
icon.addPixmap(setOpacity(normalPm, disabledOpacity), QIcon::Disabled);
|
int iconH = themeIconPixmap.height();
|
||||||
|
int canvasW = iconW;
|
||||||
|
int canvasH = iconH;
|
||||||
|
int offset = 0;
|
||||||
|
const qreal normalOpacity = useFullOpacity ? 1 : 0.8;
|
||||||
|
const qreal disabledOpacity = 0.15;
|
||||||
|
const qreal onOpacity = 1;
|
||||||
|
|
||||||
// Over
|
// off
|
||||||
icon.addPixmap(!overPm.isNull() ? overPm : normalPm, QIcon::Active);
|
icon.addPixmap(compositePixmap(themeIconPixmap, normalOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH),
|
||||||
|
QIcon::Normal, QIcon::Off);
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH),
|
||||||
|
QIcon::Disabled);
|
||||||
|
|
||||||
// On
|
// over
|
||||||
if (!onPm.isNull()) {
|
icon.addPixmap(
|
||||||
icon.addPixmap(onPm, QIcon::Normal, QIcon::On);
|
compositePixmap(!overPixmap.isNull() ? overPixmap : themeIconPixmap,
|
||||||
icon.addPixmap(setOpacity(onPm, disabledOpacity), QIcon::Disabled,
|
onOpacity, canvasW, canvasH, iconW, iconH),
|
||||||
QIcon::On);
|
QIcon::Active);
|
||||||
} else {
|
|
||||||
// If file doesn't exist, let's add an opaque normal pixmap
|
// on
|
||||||
icon.addPixmap(normalPm, QIcon::Normal, QIcon::On);
|
if (!onPixmap.isNull()) {
|
||||||
icon.addPixmap(setOpacity(normalPm, disabledOpacity), QIcon::Disabled,
|
icon.addPixmap(
|
||||||
QIcon::On);
|
compositePixmap(onPixmap, onOpacity, canvasW, canvasH, iconW, iconH),
|
||||||
|
QIcon::Normal, QIcon::On);
|
||||||
|
icon.addPixmap(compositePixmap(onPixmap, normalOpacity, canvasW, canvasH,
|
||||||
|
iconW, iconH),
|
||||||
|
QIcon::Disabled, QIcon::On);
|
||||||
|
} else {
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, onOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH),
|
||||||
|
QIcon::Normal, QIcon::On);
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH),
|
||||||
|
QIcon::Disabled, QIcon::On);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If size is 16x16 (suitable for menu) we composite it onto a separate
|
||||||
|
* 20x20 pixmap so that it is compatible with toolbars, otherwise it will be
|
||||||
|
* scaled up and blur. You need to add icons to all QIcon modes otherwise it
|
||||||
|
* will use the original size, which is undesirable. This is equal to having
|
||||||
|
* two sets loaded into the icon (16x16 and 20x20) and is dynamically used
|
||||||
|
* depending on iconSize for toolbars.
|
||||||
|
*/
|
||||||
|
if (iconSize == (QSize(16, 16))) {
|
||||||
|
canvasW = 20 * devPixRatio;
|
||||||
|
canvasH = 20 * devPixRatio;
|
||||||
|
offset = 2 * devPixRatio;
|
||||||
|
|
||||||
|
// off
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, normalOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH, offset),
|
||||||
|
QIcon::Normal, QIcon::Off);
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH, offset),
|
||||||
|
QIcon::Disabled);
|
||||||
|
// over
|
||||||
|
icon.addPixmap(
|
||||||
|
compositePixmap(!overPixmap.isNull() ? overPixmap : themeIconPixmap,
|
||||||
|
onOpacity, canvasW, canvasH, iconW, iconH, offset),
|
||||||
|
QIcon::Active);
|
||||||
|
|
||||||
|
// on
|
||||||
|
if (!onPixmap.isNull()) {
|
||||||
|
icon.addPixmap(compositePixmap(onPixmap, onOpacity, canvasW, canvasH,
|
||||||
|
iconW, iconH, offset),
|
||||||
|
QIcon::Normal, QIcon::On);
|
||||||
|
icon.addPixmap(compositePixmap(onPixmap, disabledOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH, offset),
|
||||||
|
QIcon::Disabled, QIcon::On);
|
||||||
|
} else {
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, onOpacity, canvasW,
|
||||||
|
canvasH, iconW, iconH, offset),
|
||||||
|
QIcon::Normal, QIcon::On);
|
||||||
|
icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity,
|
||||||
|
canvasW, canvasH, iconW, iconH, offset),
|
||||||
|
QIcon::Disabled, QIcon::On);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue