- bsc#1183834: Fix displaying of icons by using QSvgRenderer
* Add libqt5xdg-svg-render.patch OBS-URL: https://build.opensuse.org/package/show/X11:LXQt/libqt5xdg?expand=0&rev=18
This commit is contained in:
parent
485fc69f87
commit
cafe3cf97b
249
libqt5xdg-svg-render.patch
Normal file
249
libqt5xdg-svg-render.patch
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
From 07bb4531fe90afed28785ae2ce1a5b3f8de1c022 Mon Sep 17 00:00:00 2001
|
||||||
|
From: tsujan <tsujan2000@gmail.com>
|
||||||
|
Date: Wed, 24 Mar 2021 14:24:55 +0430
|
||||||
|
Subject: [PATCH] Use QSvgRenderer for SVG icons (#247)
|
||||||
|
|
||||||
|
* Use QSvgRenderer for SVG icons
|
||||||
|
|
||||||
|
`QSvgRenderer` is used with a cache for both ordinary and colorized SVG icons. In this way, LXQt's icon handling cannot be broken by intruding icon engines, which register themselves for "svg" (see https://github.com/lxqt/libqtxdg/issues/246). Moreover, it does not depend on a specific code structure of `qtsvg` or any other icon engine.
|
||||||
|
|
||||||
|
* Just removed a redundant computation
|
||||||
|
|
||||||
|
* Used the same key structure for SVG cache
|
||||||
|
---
|
||||||
|
src/xdgiconloader/xdgiconloader.cpp | 179 ++++++++++++++++------------
|
||||||
|
1 file changed, 100 insertions(+), 79 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/xdgiconloader/xdgiconloader.cpp b/src/xdgiconloader/xdgiconloader.cpp
|
||||||
|
index aeabda8..66d3dd8 100644
|
||||||
|
--- a/src/xdgiconloader/xdgiconloader.cpp
|
||||||
|
+++ b/src/xdgiconloader/xdgiconloader.cpp
|
||||||
|
@@ -53,6 +53,7 @@
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
+#include <QSvgRenderer>
|
||||||
|
|
||||||
|
#include <private/qhexstring_p.h>
|
||||||
|
|
||||||
|
@@ -787,121 +788,141 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st
|
||||||
|
return cachedPixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
-// XXX: duplicated from qiconloader.cpp, because this symbol isn't exported :(
|
||||||
|
+// NOTE: For SVG, QSvgRenderer is used to prevent our icon handling from
|
||||||
|
+// being broken by icon engines that register themselves for SVG.
|
||||||
|
QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||||
|
{
|
||||||
|
- if (svgIcon.isNull())
|
||||||
|
- svgIcon = QIcon(filename);
|
||||||
|
+ QPixmap pm;
|
||||||
|
+ if (size.isEmpty())
|
||||||
|
+ return pm;
|
||||||
|
|
||||||
|
- // Bypass QIcon API, as that will scale by device pixel ratio of the
|
||||||
|
- // highest DPR screen since we're not passing on any QWindow.
|
||||||
|
- if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||||
|
- return engine->pixmap(size, mode, state);
|
||||||
|
+ QString key = QLatin1String("lxqt_")
|
||||||
|
+ % filename
|
||||||
|
+ % HexString<int>(mode)
|
||||||
|
+ % HexString<int>(state)
|
||||||
|
+ % HexString<int>(size.width())
|
||||||
|
+ % HexString<int>(size.height());
|
||||||
|
+ if (!QPixmapCache::find(key, &pm))
|
||||||
|
+ {
|
||||||
|
+ int icnSize = qMin(size.width(), size.height());
|
||||||
|
+ pm = QPixmap(icnSize, icnSize);
|
||||||
|
+ pm.fill(Qt::transparent);
|
||||||
|
|
||||||
|
- return QPixmap();
|
||||||
|
+ QSvgRenderer renderer;
|
||||||
|
+ if (renderer.load(filename))
|
||||||
|
+ {
|
||||||
|
+ QPainter p;
|
||||||
|
+ p.begin(&pm);
|
||||||
|
+ renderer.render(&p, QRect(0, 0, icnSize, icnSize));
|
||||||
|
+ p.end();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ svgIcon = QIcon(pm);
|
||||||
|
+ if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||||
|
+ pm = engine->pixmap(size, mode, state);
|
||||||
|
+ QPixmapCache::insert(key, pm);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const QString STYLE = QStringLiteral("\n.ColorScheme-Text, .ColorScheme-NeutralText {color:%1;}\
|
||||||
|
\n.ColorScheme-Background {color:%2;}\
|
||||||
|
\n.ColorScheme-Highlight {color:%3;}");
|
||||||
|
-// Note: Qt palette does not have any colors for positive/negative text
|
||||||
|
+// NOTE: Qt palette does not have any colors for positive/negative text
|
||||||
|
// .ColorScheme-PositiveText,ColorScheme-NegativeText {color:%4;}
|
||||||
|
|
||||||
|
QPixmap ScalableFollowsColorEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||||
|
{
|
||||||
|
QPixmap pm;
|
||||||
|
- // see ScalableEntry::pixmap() for the reason
|
||||||
|
- if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||||
|
- pm = engine->pixmap(size, mode, state);
|
||||||
|
+ if (size.isEmpty())
|
||||||
|
+ return pm;
|
||||||
|
|
||||||
|
- // Note: not checking the QIcon::isNull(), because in Qt5.10 the isNull() is not reliable
|
||||||
|
- // for svg icons desierialized from stream (see https://codereview.qt-project.org/#/c/216086/)
|
||||||
|
- if (pm.isNull())
|
||||||
|
+ const QPalette pal = qApp->palette();
|
||||||
|
+ QString txtCol, bgCol, hCol;
|
||||||
|
+ if (mode == QIcon::Disabled)
|
||||||
|
+ {
|
||||||
|
+ txtCol = pal.color(QPalette::Disabled, QPalette::WindowText).name();
|
||||||
|
+ bgCol = pal.color(QPalette::Disabled, QPalette::Window).name();
|
||||||
|
+ hCol = pal.color(QPalette::Disabled, QPalette::Highlight).name();
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (mode == QIcon::Selected)
|
||||||
|
+ {
|
||||||
|
+ txtCol = pal.highlightedText().color().name();
|
||||||
|
+ bgCol = pal.highlight().color().name();
|
||||||
|
+ }
|
||||||
|
+ else // normal or active
|
||||||
|
+ {
|
||||||
|
+ txtCol = pal.windowText().color().name();
|
||||||
|
+ bgCol = pal.window().color().name();
|
||||||
|
+ }
|
||||||
|
+ hCol = pal.highlight().color().name();
|
||||||
|
+ }
|
||||||
|
+ QString key = QLatin1String("lxqt_")
|
||||||
|
+ % filename
|
||||||
|
+ % HexString<int>(mode)
|
||||||
|
+ % HexString<int>(state)
|
||||||
|
+ % HexString<int>(size.width())
|
||||||
|
+ % HexString<int>(size.height())
|
||||||
|
+ % txtCol % bgCol % hCol;
|
||||||
|
+ if (!QPixmapCache::find(key, &pm))
|
||||||
|
{
|
||||||
|
- // The following lines are adapted and updated from KDE's "kiconloader.cpp" ->
|
||||||
|
- // KIconLoaderPrivate::processSvg() and KIconLoaderPrivate::createIconImage().
|
||||||
|
- // They read the SVG color scheme of SVG icons and give images based on the icon mode.
|
||||||
|
- QHash<int, QByteArray> svg_buffers;
|
||||||
|
+ int icnSize = qMin(size.width(), size.height());
|
||||||
|
+ pm = QPixmap(icnSize, icnSize);
|
||||||
|
+ pm.fill(Qt::transparent);
|
||||||
|
+
|
||||||
|
QFile device{filename};
|
||||||
|
if (device.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
- const QPalette pal = qApp->palette();
|
||||||
|
- // Note: indexes are assembled as in qtsvg (QSvgIconEnginePrivate::hashKey())
|
||||||
|
- QMap<int, QString> style_sheets;
|
||||||
|
- style_sheets[(QIcon::Normal<<4)|QIcon::Off] = STYLE.arg(pal.windowText().color().name(), pal.window().color().name(), pal.highlight().color().name());
|
||||||
|
- style_sheets[(QIcon::Selected<<4)|QIcon::Off] = STYLE.arg(pal.highlightedText().color().name(), pal.highlight().color().name(), pal.highlightedText().color().name());
|
||||||
|
- QMap<int, QSharedPointer<QXmlStreamWriter> > writers;
|
||||||
|
- for (auto i = style_sheets.cbegin(); i != style_sheets.cend(); ++i)
|
||||||
|
- {
|
||||||
|
- writers[i.key()].reset(new QXmlStreamWriter{&svg_buffers[i.key()]});
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
+ QString styleSheet = STYLE.arg(txtCol, bgCol, hCol);
|
||||||
|
+ QByteArray svgBuffer;
|
||||||
|
+ QXmlStreamWriter writer(&svgBuffer);
|
||||||
|
QXmlStreamReader xmlReader(&device);
|
||||||
|
while (!xmlReader.atEnd())
|
||||||
|
{
|
||||||
|
if (xmlReader.readNext() == QXmlStreamReader::StartElement
|
||||||
|
- && xmlReader.qualifiedName() == QLatin1String("style")
|
||||||
|
- && xmlReader.attributes().value(QLatin1String("id")) == QLatin1String("current-color-scheme"))
|
||||||
|
+ && xmlReader.qualifiedName() == QLatin1String("style")
|
||||||
|
+ && xmlReader.attributes().value(QLatin1String("id")) == QLatin1String("current-color-scheme"))
|
||||||
|
{
|
||||||
|
const auto attribs = xmlReader.attributes();
|
||||||
|
// store original data/text of the <style> element
|
||||||
|
- QString original_data;
|
||||||
|
+ QString origData;
|
||||||
|
while (xmlReader.tokenType() != QXmlStreamReader::EndElement)
|
||||||
|
{
|
||||||
|
if (xmlReader.tokenType() == QXmlStreamReader::Characters)
|
||||||
|
- original_data += xmlReader.text();
|
||||||
|
+ origData += xmlReader.text();
|
||||||
|
xmlReader.readNext();
|
||||||
|
}
|
||||||
|
- for (auto i = style_sheets.cbegin(); i != style_sheets.cend(); ++i)
|
||||||
|
- {
|
||||||
|
- QXmlStreamWriter & writer = *writers[i.key()];
|
||||||
|
- writer.writeStartElement(QLatin1String("style"));
|
||||||
|
- writer.writeAttributes(attribs);
|
||||||
|
- // Note: We're writting the original style text to leave
|
||||||
|
- // there "defaults" for unknown/unsupported classes.
|
||||||
|
- // Then appending our "overrides"
|
||||||
|
- writer.writeCharacters(original_data);
|
||||||
|
- writer.writeCharacters(*i);
|
||||||
|
- writer.writeEndElement();
|
||||||
|
- }
|
||||||
|
- } else if (xmlReader.tokenType() != QXmlStreamReader::Invalid)
|
||||||
|
- {
|
||||||
|
- for (auto i = style_sheets.cbegin(); i != style_sheets.cend(); ++i)
|
||||||
|
- {
|
||||||
|
- writers[i.key()]->writeCurrentToken(xmlReader);
|
||||||
|
- }
|
||||||
|
+ writer.writeStartElement(QLatin1String("style"));
|
||||||
|
+ writer.writeAttributes(attribs);
|
||||||
|
+ writer.writeCharacters(origData);
|
||||||
|
+ writer.writeCharacters(styleSheet);
|
||||||
|
+ writer.writeEndElement();
|
||||||
|
}
|
||||||
|
+ else if (xmlReader.tokenType() != QXmlStreamReader::Invalid)
|
||||||
|
+ writer.writeCurrentToken(xmlReader);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!svgBuffer.isEmpty())
|
||||||
|
+ {
|
||||||
|
+ QSvgRenderer renderer;
|
||||||
|
+ renderer.load(svgBuffer);
|
||||||
|
+ QPainter p;
|
||||||
|
+ p.begin(&pm);
|
||||||
|
+ renderer.render(&p, QRect(0, 0, icnSize, icnSize));
|
||||||
|
+ p.end();
|
||||||
|
}
|
||||||
|
- // duplicate the contets also for opposite state
|
||||||
|
- svg_buffers[(QIcon::Normal<<4)|QIcon::On] = svg_buffers[(QIcon::Normal<<4)|QIcon::Off];
|
||||||
|
- svg_buffers[(QIcon::Selected<<4)|QIcon::On] = svg_buffers[(QIcon::Selected<<4)|QIcon::Off];
|
||||||
|
}
|
||||||
|
- // use the QSvgIconEngine
|
||||||
|
- // - assemble the content as it is done by the operator <<(QDataStream &s, const QIcon &icon)
|
||||||
|
- // (the QSvgIconEngine::key() + QSvgIconEngine::write())
|
||||||
|
- // - create the QIcon from the content by usage of the QIcon::operator >>(QDataStream &s, const QIcon &icon)
|
||||||
|
- // (icon with the (QSvgIconEngine) will be used)
|
||||||
|
- QByteArray icon_arr;
|
||||||
|
- QDataStream str{&icon_arr, QIODevice::WriteOnly};
|
||||||
|
- str.setVersion(QDataStream::Qt_4_4);
|
||||||
|
- QHash<int, QString> filenames;
|
||||||
|
- filenames[0] = filename; // Note: filenames are ignored in the QSvgIconEngine::read()
|
||||||
|
- str << QStringLiteral("svg") << filenames << static_cast<int>(0)/*isCompressed*/ << svg_buffers << static_cast<int>(0)/*hasAddedPimaps*/;
|
||||||
|
-
|
||||||
|
- QDataStream str_read{&icon_arr, QIODevice::ReadOnly};
|
||||||
|
- str_read.setVersion(QDataStream::Qt_4_4);
|
||||||
|
-
|
||||||
|
- str_read >> svgIcon;
|
||||||
|
+
|
||||||
|
+ // Do not use this pixmap directly but first get the icon
|
||||||
|
+ // for QIcon::pixmap() to handle states and modes,
|
||||||
|
+ // especially the disabled mode.
|
||||||
|
+ svgIcon = QIcon(pm);
|
||||||
|
if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||||
|
pm = engine->pixmap(size, mode, state);
|
||||||
|
-
|
||||||
|
- // load the icon directly from file, if still null
|
||||||
|
- if (pm.isNull())
|
||||||
|
- {
|
||||||
|
- svgIcon = QIcon(filename);
|
||||||
|
- if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||||
|
- pm = engine->pixmap(size, mode, state);
|
||||||
|
- }
|
||||||
|
+ QPixmapCache::insert(key, pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pm;
|
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Mar 31 10:02:43 UTC 2021 - Michael Vetter <mvetter@suse.com>
|
||||||
|
|
||||||
|
- bsc#1183834: Fix displaying of icons by using QSvgRenderer
|
||||||
|
* Add libqt5xdg-svg-render.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Nov 4 13:17:31 UTC 2020 - Michael Vetter <mvetter@suse.com>
|
Wed Nov 4 13:17:31 UTC 2020 - Michael Vetter <mvetter@suse.com>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# spec file for package libqt5xdg
|
# spec file for package libqt5xdg
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 SUSE LLC
|
# Copyright (c) 2021 SUSE LLC
|
||||||
#
|
#
|
||||||
# All modifications and additions to the file contributed by third parties
|
# All modifications and additions to the file contributed by third parties
|
||||||
# remain the property of their copyright owners, unless otherwise agreed
|
# remain the property of their copyright owners, unless otherwise agreed
|
||||||
@ -27,6 +27,7 @@ URL: https://lxqt.org
|
|||||||
Source: https://github.com/lxqt/libqtxdg/releases/download/%{version}/%{_name}-%{version}.tar.xz
|
Source: https://github.com/lxqt/libqtxdg/releases/download/%{version}/%{_name}-%{version}.tar.xz
|
||||||
Source1: https://github.com/lxqt/libqtxdg/releases/download/%{version}/%{_name}-%{version}.tar.xz.asc
|
Source1: https://github.com/lxqt/libqtxdg/releases/download/%{version}/%{_name}-%{version}.tar.xz.asc
|
||||||
Source2: %{name}.keyring
|
Source2: %{name}.keyring
|
||||||
|
Patch0: libqt5xdg-svg-render.patch
|
||||||
BuildRequires: cmake >= 3.1.0
|
BuildRequires: cmake >= 3.1.0
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
@ -88,6 +89,7 @@ Tools for QtXdg.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{_name}-%{version}
|
%setup -q -n %{_name}-%{version}
|
||||||
|
%patch0 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%cmake
|
%cmake
|
||||||
|
Loading…
Reference in New Issue
Block a user