diff options
author | Caolán McNamara <caolanm@redhat.com> | 2022-11-09 21:30:34 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-11-10 09:40:47 +0100 |
commit | 397f5daa850e59f0f4d3881cb99d110b50e34e3d (patch) | |
tree | 487beb6a38c22094d4cbe8857918b92cee64c2ee | |
parent | 2a26f136a36791c06caa895d5a25f4633fd10651 (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.hxx | 7 | ||||
-rw-r--r-- | vcl/inc/implimagetree.hxx | 7 | ||||
-rw-r--r-- | vcl/source/image/ImageTree.cxx | 5 | ||||
-rw-r--r-- | vcl/source/image/ImplImageTree.cxx | 12 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtkinst.cxx | 67 |
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); } |