@@ -260,46 +260,143 @@ QPixmap recolorPixmap(QPixmap pixmap, QColor color) {
260260 .rgba ();
261261 }
262262 }
263- return pixmap = QPixmap::fromImage (img);
263+ pixmap = QPixmap::fromImage (img);
264+ return pixmap;
265+ }
266+
267+ // -----------------------------------------------------------------------------
268+
269+ QPixmap compositePixmap (QPixmap pixmap, qreal opacity, int canvasWidth,
270+ int canvasHeight, int iconWidth, int iconHeight,
271+ int offset) {
272+ /* Creates a composite pixmap from two pixmaps. The canvas controls the final
273+ * size, whereas pixmap is the image to be composited ontop. You can control
274+ * the position of pixmap by setting an offset (top-left), default is 0. */
275+
276+ static int devPixRatio = getDevPixRatio ();
277+
278+ QPixmap canvas (canvasWidth, canvasHeight);
279+ canvas.fill (Qt::transparent); // set this to a color to debug
280+ QPixmap combined (canvasWidth, canvasHeight);
281+ combined.fill (Qt::transparent);
282+ if (!pixmap.isNull ()) {
283+ QPainter painter;
284+ painter.begin (&combined);
285+ QRect canvasRect (0 , 0 , canvasWidth, canvasHeight);
286+ painter.drawPixmap (canvasRect, canvas);
287+ painter.setOpacity (opacity);
288+ QRect iconRect (offset, offset, iconWidth, iconHeight);
289+ painter.drawPixmap (iconRect, pixmap);
290+ painter.end ();
291+ }
292+
293+ return combined;
264294}
265295
266296// -----------------------------------------------------------------------------
267297
268298QIcon createQIcon (const char *iconSVGName, bool useFullOpacity) {
269- QIcon normalIcon = QIcon::fromTheme (iconSVGName );
299+ static int devPixRatio = getDevPixRatio ( );
270300
271- QSize iconSize (0 , 0 ); // Get largest
272- for (QList<QSize> sizes = normalIcon.availableSizes (); !sizes.isEmpty ();
301+ // get icon size
302+ QIcon themeIcon = QIcon::fromTheme (iconSVGName);
303+ QSize iconSize (0 , 0 );
304+ for (QList<QSize> sizes = themeIcon.availableSizes (); !sizes.isEmpty ();
273305 sizes.removeFirst ())
274306 if (sizes.first ().width () > iconSize.width ()) iconSize = sizes.first ();
275307
276- const qreal offOpacity = 0.8 ;
277- const qreal disabledOpacity = 0.15 ;
278- QString overStr = QString (iconSVGName) + " _over" ;
279- QString onStr = QString (iconSVGName) + " _on" ;
280- QPixmap normalPm = recolorPixmap (normalIcon.pixmap (iconSize));
281- QPixmap overPm = recolorPixmap (QIcon::fromTheme (overStr).pixmap (iconSize));
282- QPixmap onPm = recolorPixmap (QIcon::fromTheme (onStr).pixmap (iconSize));
308+ QString overStr = QString (iconSVGName) + " _over" ;
309+ QString onStr = QString (iconSVGName) + " _on" ;
310+ QPixmap themeIconPixmap = recolorPixmap (themeIcon.pixmap (iconSize));
311+ QPixmap overPixmap =
312+ recolorPixmap (QIcon::fromTheme (overStr).pixmap (iconSize));
313+ QPixmap onPixmap = recolorPixmap (QIcon::fromTheme (onStr).pixmap (iconSize));
283314 QIcon icon;
284315
285- // Off
286- icon.addPixmap (useFullOpacity ? normalPm : setOpacity (normalPm, offOpacity),
287- QIcon::Normal, QIcon::Off);
288- icon.addPixmap (setOpacity (normalPm, disabledOpacity), QIcon::Disabled);
289-
290- // Over
291- icon.addPixmap (!overPm.isNull () ? overPm : normalPm, QIcon::Active);
316+ // build icon
317+ for (int devPixRatio = 1 ; devPixRatio <= 2 ; devPixRatio++) {
318+ int iconW = themeIconPixmap.width ();
319+ int iconH = themeIconPixmap.height ();
320+ int canvasW = iconW;
321+ int canvasH = iconH;
322+ int offset = 0 ;
323+ const qreal normalOpacity = useFullOpacity ? 1 : 0.8 ;
324+ const qreal disabledOpacity = 0.15 ;
325+ const qreal onOpacity = 1 ;
326+
327+ // off
328+ icon.addPixmap (compositePixmap (themeIconPixmap, normalOpacity, canvasW,
329+ canvasH, iconW, iconH),
330+ QIcon::Normal, QIcon::Off);
331+ icon.addPixmap (compositePixmap (themeIconPixmap, disabledOpacity, canvasW,
332+ canvasH, iconW, iconH),
333+ QIcon::Disabled);
334+
335+ // over
336+ icon.addPixmap (
337+ compositePixmap (!overPixmap.isNull () ? overPixmap : themeIconPixmap,
338+ onOpacity, canvasW, canvasH, iconW, iconH),
339+ QIcon::Active);
340+
341+ // on
342+ if (!onPixmap.isNull ()) {
343+ icon.addPixmap (
344+ compositePixmap (onPixmap, onOpacity, canvasW, canvasH, iconW, iconH),
345+ QIcon::Normal, QIcon::On);
346+ icon.addPixmap (compositePixmap (onPixmap, normalOpacity, canvasW, canvasH,
347+ iconW, iconH),
348+ QIcon::Disabled, QIcon::On);
349+ } else {
350+ icon.addPixmap (compositePixmap (themeIconPixmap, onOpacity, canvasW,
351+ canvasH, iconW, iconH),
352+ QIcon::Normal, QIcon::On);
353+ icon.addPixmap (compositePixmap (themeIconPixmap, disabledOpacity, canvasW,
354+ canvasH, iconW, iconH),
355+ QIcon::Disabled, QIcon::On);
356+ }
292357
293- // On
294- if (!onPm.isNull ()) {
295- icon.addPixmap (onPm, QIcon::Normal, QIcon::On);
296- icon.addPixmap (setOpacity (onPm, disabledOpacity), QIcon::Disabled,
297- QIcon::On);
298- } else {
299- // If file doesn't exist, let's add an opaque normal pixmap
300- icon.addPixmap (normalPm, QIcon::Normal, QIcon::On);
301- icon.addPixmap (setOpacity (normalPm, disabledOpacity), QIcon::Disabled,
302- QIcon::On);
358+ /* If size is 16x16 (suitable for menu) we composite it onto a separate
359+ * 20x20 pixmap so that it is compatible with toolbars, otherwise it will be
360+ * scaled up and blur. You need to add icons to all QIcon modes otherwise it
361+ * will use the original size, which is undesirable. This is equal to having
362+ * two sets loaded into the icon (16x16 and 20x20) and is dynamically used
363+ * depending on iconSize for toolbars.
364+ */
365+ if (iconSize == (QSize (16 , 16 ))) {
366+ canvasW = 20 * devPixRatio;
367+ canvasH = 20 * devPixRatio;
368+ offset = 2 * devPixRatio;
369+
370+ // off
371+ icon.addPixmap (compositePixmap (themeIconPixmap, normalOpacity, canvasW,
372+ canvasH, iconW, iconH, offset),
373+ QIcon::Normal, QIcon::Off);
374+ icon.addPixmap (compositePixmap (themeIconPixmap, disabledOpacity, canvasW,
375+ canvasH, iconW, iconH, offset),
376+ QIcon::Disabled);
377+ // over
378+ icon.addPixmap (
379+ compositePixmap (!overPixmap.isNull () ? overPixmap : themeIconPixmap,
380+ onOpacity, canvasW, canvasH, iconW, iconH, offset),
381+ QIcon::Active);
382+
383+ // on
384+ if (!onPixmap.isNull ()) {
385+ icon.addPixmap (compositePixmap (onPixmap, onOpacity, canvasW, canvasH,
386+ iconW, iconH, offset),
387+ QIcon::Normal, QIcon::On);
388+ icon.addPixmap (compositePixmap (onPixmap, disabledOpacity, canvasW,
389+ canvasH, iconW, iconH, offset),
390+ QIcon::Disabled, QIcon::On);
391+ } else {
392+ icon.addPixmap (compositePixmap (themeIconPixmap, onOpacity, canvasW,
393+ canvasH, iconW, iconH, offset),
394+ QIcon::Normal, QIcon::On);
395+ icon.addPixmap (compositePixmap (themeIconPixmap, disabledOpacity,
396+ canvasW, canvasH, iconW, iconH, offset),
397+ QIcon::Disabled, QIcon::On);
398+ }
399+ }
303400 }
304401 return icon;
305402}
@@ -340,8 +437,11 @@ QIcon createQIconOnOffPNG(const char *iconPNGName, bool withOver) {
340437// -----------------------------------------------------------------------------
341438
342439QIcon createTemporaryIconFromName (const char *commandName) {
343- const int visibleIconSize = 20 ;
344- const int menubarIconSize = 16 ;
440+ const int visibleIconSize = 20 ;
441+ const int menubarIconSize = 16 ;
442+ const qreal normalOpacity = 0.8 ;
443+ const qreal disabledOpacity = 0.15 ;
444+ const qreal onOpacity = 1 ;
345445 QString name (commandName);
346446 QList<QChar> iconChar;
347447
@@ -397,8 +497,18 @@ QIcon createTemporaryIconFromName(const char *commandName) {
397497
398498 icon.addPixmap (transparentPm);
399499 icon.addPixmap (transparentPm, QIcon::Disabled);
400- icon.addPixmap (pixmap);
401- icon.addPixmap (setOpacity (pixmap, 0.15 ), QIcon::Disabled);
500+ icon.addPixmap (compositePixmap (pixmap, normalOpacity, pxSize, pxSize,
501+ pixmap.width (), pixmap.height ()),
502+ QIcon::Normal, QIcon::Off);
503+ icon.addPixmap (compositePixmap (pixmap, onOpacity, pxSize, pxSize,
504+ pixmap.width (), pixmap.height ()),
505+ QIcon::Normal, QIcon::On);
506+ icon.addPixmap (compositePixmap (pixmap, onOpacity, pxSize, pxSize,
507+ pixmap.width (), pixmap.height ()),
508+ QIcon::Active);
509+ icon.addPixmap (compositePixmap (pixmap, disabledOpacity, pxSize, pxSize,
510+ pixmap.width (), pixmap.height ()),
511+ QIcon::Disabled);
402512 }
403513 return icon;
404514}
0 commit comments