summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2022-11-09 21:30:34 +0000
committerCaolán McNamara <caolanm@redhat.com>2022-11-10 09:40:47 +0100
commit397f5daa850e59f0f4d3881cb99d110b50e34e3d (patch)
tree487beb6a38c22094d4cbe8857918b92cee64c2ee
parent2a26f136a36791c06caa895d5a25f4633fd10651 (diff)
tdf#151898 if svgs are used in hidpi get a high quality GtkImage
this gets nice sidebar icons in this case as far as I can see only gtk_image_new_from_file (or gtk_image_new_from_resource) can support the use of a scaleable input format to create a hidpi GtkImage, rather than an upscaled lodpi one so forced to go via a file here Change-Id: I665cd5be2c87f6fe8e264640be228263cdfc1fba Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142504 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--include/vcl/ImageTree.hxx7
-rw-r--r--vcl/inc/implimagetree.hxx7
-rw-r--r--vcl/source/image/ImageTree.cxx5
-rw-r--r--vcl/source/image/ImplImageTree.cxx12
-rw-r--r--vcl/unx/gtk3/gtkinst.cxx67
5 files changed, 92 insertions, 6 deletions
diff --git a/include/vcl/ImageTree.hxx b/include/vcl/ImageTree.hxx
index 85f05d774cd5..4de20d74e935 100644
--- a/include/vcl/ImageTree.hxx
+++ b/include/vcl/ImageTree.hxx
@@ -43,6 +43,10 @@ namespace com::sun::star::container {
class XNameAccess;
}
+namespace com::sun::star::io {
+ class XInputStream;
+}
+
class ImplImageTree;
class BitmapEx;
class SvMemoryStream;
@@ -63,6 +67,9 @@ public:
VCL_DLLPUBLIC std::shared_ptr<SvMemoryStream> getImageStream(
OUString const & rName, OUString const & rStyle, OUString const & rLang);
+ VCL_DLLPUBLIC css::uno::Reference<css::io::XInputStream> getImageXInputStream(OUString const & rName,
+ OUString const & rStyle, OUString const & rLang);
+
VCL_DLLPUBLIC bool loadImage(
OUString const & name, OUString const & style,
BitmapEx & bitmap, bool localized,
diff --git a/vcl/inc/implimagetree.hxx b/vcl/inc/implimagetree.hxx
index d02e5652971f..beecb233e1d9 100644
--- a/vcl/inc/implimagetree.hxx
+++ b/vcl/inc/implimagetree.hxx
@@ -37,6 +37,10 @@ namespace com::sun::star::container {
class XNameAccess;
}
+namespace com::sun::star::io {
+ class XInputStream;
+}
+
struct ImageRequestParameters
{
OUString msName;
@@ -71,6 +75,9 @@ public:
OUString getImageUrl(
OUString const & name, OUString const & style, OUString const & lang);
+ css::uno::Reference<css::io::XInputStream> getImageXInputStream(OUString const & rName,
+ OUString const & rStyle, OUString const & rLang);
+
std::shared_ptr<SvMemoryStream> getImageStream(
OUString const & rName, OUString const & rStyle, OUString const & rLang);
diff --git a/vcl/source/image/ImageTree.cxx b/vcl/source/image/ImageTree.cxx
index 83e2962cbf8e..fdc47cbfe700 100644
--- a/vcl/source/image/ImageTree.cxx
+++ b/vcl/source/image/ImageTree.cxx
@@ -34,6 +34,11 @@ std::shared_ptr<SvMemoryStream> ImageTree::getImageStream(OUString const & rName
return mpImplImageTree->getImageStream(rName, rStyle, rLang);
}
+css::uno::Reference<css::io::XInputStream> ImageTree::getImageXInputStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
+{
+ return mpImplImageTree->getImageXInputStream(rName, rStyle, rLang);
+}
+
bool ImageTree::loadImage(OUString const & rName, OUString const & rStyle,
BitmapEx & rBitmap, bool bLocalized,
sal_Int32 nScalePercentage,
diff --git a/vcl/source/image/ImplImageTree.cxx b/vcl/source/image/ImplImageTree.cxx
index 7294d82e74e2..549d0739139b 100644
--- a/vcl/source/image/ImplImageTree.cxx
+++ b/vcl/source/image/ImplImageTree.cxx
@@ -275,7 +275,7 @@ OUString ImplImageTree::getImageUrl(OUString const & rName, OUString const & rSt
return OUString();
}
-std::shared_ptr<SvMemoryStream> ImplImageTree::getImageStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
+uno::Reference<io::XInputStream> ImplImageTree::getImageXInputStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
{
OUString aStyle(rStyle);
@@ -300,7 +300,7 @@ std::shared_ptr<SvMemoryStream> ImplImageTree::getImageStream(OUString const & r
bool ok = rNameAccess->getByName(rPath) >>= aStream;
assert(ok);
(void)ok; // prevent unused warning in release build
- return wrapStream(aStream);
+ return aStream;
}
}
}
@@ -312,6 +312,14 @@ std::shared_ptr<SvMemoryStream> ImplImageTree::getImageStream(OUString const & r
aStyle = fallbackStyle(aStyle);
}
+ return nullptr;
+}
+
+std::shared_ptr<SvMemoryStream> ImplImageTree::getImageStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
+{
+ uno::Reference<io::XInputStream> xStream = getImageXInputStream(rName, rStyle, rLang);
+ if (xStream)
+ return wrapStream(xStream);
return std::shared_ptr<SvMemoryStream>();
}
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 82bd0e724483..ef3d509ea2ef 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -79,6 +79,7 @@
#include <tools/fract.hxx>
#include <tools/stream.hxx>
#include <unotools/resmgr.hxx>
+#include <unotools/tempfile.hxx>
#include <unx/gstsink.hxx>
#include <vcl/ImageTree.hxx>
#include <vcl/abstdlg.hxx>
@@ -4783,13 +4784,44 @@ namespace
return pixbuf;
}
+ std::shared_ptr<SvMemoryStream> get_icon_stream_by_name_theme_lang(const OUString& rIconName, const OUString& rIconTheme, const OUString& rUILang)
+ {
+ return ImageTree::get().getImageStream(rIconName, rIconTheme, rUILang);
+ }
+
GdkPixbuf* load_icon_by_name_theme_lang(const OUString& rIconName, const OUString& rIconTheme, const OUString& rUILang)
{
- auto xMemStm = ImageTree::get().getImageStream(rIconName, rIconTheme, rUILang);
+ auto xMemStm = get_icon_stream_by_name_theme_lang(rIconName, rIconTheme, rUILang);
if (!xMemStm)
return nullptr;
return load_icon_from_stream(*xMemStm);
}
+
+ std::unique_ptr<utl::TempFileNamed> get_icon_stream_as_file(const OUString& rIconName)
+ {
+ OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
+ OUString sUILang = Application::GetSettings().GetUILanguageTag().getBcp47();
+ uno::Reference<io::XInputStream> xInputStream = ImageTree::get().getImageXInputStream(rIconName, sIconTheme, sUILang);
+ if (!xInputStream)
+ return nullptr;
+
+ std::unique_ptr<utl::TempFileNamed> xRet(new utl::TempFileNamed);
+ xRet->EnableKillingFile(true);
+ SvStream* pStream = xRet->GetStream(StreamMode::WRITE);
+
+ for (;;)
+ {
+ const sal_Int32 nSize(2048);
+ uno::Sequence<sal_Int8> aData(nSize);
+ sal_Int32 nRead = xInputStream->readBytes(aData, nSize);
+ pStream->WriteBytes(aData.getConstArray(), nRead);
+ if (nRead < nSize)
+ break;
+ }
+ xRet->CloseStream();
+
+ return xRet;
+ }
}
GdkPixbuf* load_icon_by_name(const OUString& rIconName)
@@ -4831,6 +4863,34 @@ namespace
return load_icon_from_stream(aMemStm);
}
+ // tdf#151898 as far as I can see only gtk_image_new_from_file (or gtk_image_new_from_resource) can support the use of a
+ // scaleable input format to create a hidpi GtkImage, rather than an upscaled lodpi one so forced to go via a file here
+ std::unique_ptr<utl::TempFileNamed> getImageFile(const css::uno::Reference<css::graphic::XGraphic>& rImage, bool bMirror = false)
+ {
+ Image aImage(rImage);
+ if (bMirror)
+ aImage = mirrorImage(aImage);
+
+ OUString sStock(aImage.GetStock());
+ if (!sStock.isEmpty())
+ return get_icon_stream_as_file(sStock);
+
+ std::unique_ptr<utl::TempFileNamed> xRet(new utl::TempFileNamed);
+ xRet->EnableKillingFile(true);
+ SvStream* pStream = xRet->GetStream(StreamMode::WRITE);
+
+ // We "know" that this gets passed to zlib's deflateInit2_(). 1 means best speed.
+ css::uno::Sequence<css::beans::PropertyValue> aFilterData{ comphelper::makePropertyValue(
+ "Compression", sal_Int32(1)) };
+ auto aBitmapEx = aImage.GetBitmapEx();
+ vcl::PngImageWriter aWriter(*pStream);
+ aWriter.setParameters(aFilterData);
+ aWriter.write(aBitmapEx);
+
+ xRet->CloseStream();
+ return xRet;
+ }
+
GdkPixbuf* getPixbuf(const VirtualDevice& rDevice)
{
Size aSize(rDevice.GetOutputSizePixel());
@@ -11834,10 +11894,9 @@ private:
{
GtkWidget* pImage = nullptr;
- if (GdkPixbuf* pixbuf = getPixbuf(rIcon, bMirror))
+ if (auto xTempFile = getImageFile(rIcon, bMirror))
{
- pImage = gtk_image_new_from_pixbuf(pixbuf);
- g_object_unref(pixbuf);
+ pImage = gtk_image_new_from_file(OUStringToOString(xTempFile->GetFileName(), osl_getThreadTextEncoding()).getStr());
gtk_widget_show(pImage);
}