20#include <config_folders.h>
28#include <com/sun/star/container/XNameAccess.hpp>
29#include <com/sun/star/io/XInputStream.hpp>
30#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
31#include <com/sun/star/ucb/SimpleFileAccess.hpp>
32#include <com/sun/star/uno/Exception.hpp>
33#include <com/sun/star/uno/RuntimeException.hpp>
34#include <com/sun/star/uno/Sequence.hxx>
37#include <osl/file.hxx>
38#include <osl/diagnose.h>
39#include <osl/process.h>
40#include <rtl/bootstrap.hxx>
42#include <rtl/strbuf.hxx>
66 static bool bIconsForDarkTheme = !!getenv(
"VCL_ICONS_FOR_DARK_THEME");
68 bool bConvertToDarkTheme =
false;
70 bConvertToDarkTheme = bIconsForDarkTheme;
72 return bConvertToDarkTheme;
77 sal_Int32 aScalePercentage = 100;
83 return aScalePercentage;
89OUString convertLcTo32Path(std::u16string_view rPath)
92 size_t nSlashPos = rPath.rfind(
'/');
93 if (nSlashPos != std::u16string_view::npos)
95 sal_Int32 nCopyFrom = nSlashPos + 1;
96 std::u16string_view sFile = rPath.substr(nCopyFrom);
97 std::u16string_view sDir = rPath.substr(0, nSlashPos);
100 aResult = OUString::Concat(sDir) +
"/32/" + sFile.substr(3);
106OUString createPath(std::u16string_view name, sal_Int32 pos, std::u16string_view locale)
108 return OUString::Concat(
name.substr(0, pos + 1)) + locale +
name.substr(pos);
114 static OUString CACHE_DIR = []()
116 OUString sDir =
"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"bootstrap")
":UserInstallation}/cache/";
117 rtl::Bootstrap::expandMacros(sDir);
120 return CACHE_DIR + rParameters.
msStyle +
"/" + sVariant +
"/" + rParameters.
msName;
123OUString createIconCacheUrl(
126 OUString sUrl(getIconCacheUrl(sVariant, rParameters));
127 OUString sDir = sUrl.copy(0, sUrl.lastIndexOf(
'/'));
128 osl::Directory::createPath(sDir);
132bool urlExists(OUString
const & sUrl)
134 osl::File aFile(sUrl);
135 osl::FileBase::RC eRC = aFile.open(osl_File_OpenFlag_Read);
136 return osl::FileBase::E_None == eRC;
139OUString getNameNoExtension(std::u16string_view sName)
141 size_t nDotPosition =
sName.rfind(
'.');
142 return OUString(
sName.substr(0, nDotPosition));
145std::shared_ptr<SvMemoryStream> wrapStream(uno::Reference<io::XInputStream>
const & rInputStream)
152 std::shared_ptr<SvMemoryStream> aMemoryStream(std::make_shared<SvMemoryStream>());
155 const sal_Int32 nSize(2048);
156 uno::Sequence<sal_Int8>
aData(nSize);
157 sal_Int32 nRead =
rInputStream->readBytes(aData, nSize);
158 aMemoryStream->WriteBytes(
aData.getConstArray(), nRead);
162 aMemoryStream->Seek(0);
164 return aMemoryStream;
167void loadImageFromStream(std::shared_ptr<SvStream>
const & xStream, OUString
const & rPath,
ImageRequestParameters& rParameters)
172 if (rPath.endsWith(
".png"))
175 aPNGReader.read(rParameters.
mrBitmap);
177 else if (rPath.endsWith(
".svg"))
182 if (bConvertToDarkTheme)
192 if (bConvertToDarkTheme)
198 if (aScalePercentage > 100)
201 double aScaleFactor(aScalePercentage / 100.0);
220 std::vector<OUString> sPaths;
222 sal_Int32
pos =
name.lastIndexOf(
'/');
228 sPaths.emplace_back(aFallbackName +
".png");
229 sPaths.emplace_back(aFallbackName +
".svg");
234 sPaths.emplace_back(aRealName +
".png");
235 sPaths.emplace_back(aRealName +
".svg");
242 OUString aStyle(rStyle);
244 while (!aStyle.isEmpty())
253 const uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.
maNameAccess;
257 for (
const OUString& rPath:
getPaths(rName, aLanguageTag))
259 if (rNameAccess->hasByName(rPath))
261 return "vnd.sun.star.zip://"
262 + rtl::Uri::encode(rIconSet.
maURL, rtl_UriCharClassRegName,
263 rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8)
269 catch (
const uno::Exception &)
281 OUString aStyle(rStyle);
283 while (!aStyle.isEmpty())
292 const uno::Reference<container::XNameAccess>& rNameAccess = rIconSet.
maNameAccess;
296 for (
const OUString& rPath:
getPaths(rName, aLanguageTag))
298 if (rNameAccess->hasByName(rPath))
300 uno::Reference<io::XInputStream> aStream;
301 bool ok = rNameAccess->getByName(rPath) >>= aStream;
309 catch (
const uno::Exception &)
324 return std::shared_ptr<SvMemoryStream>();
331 if (rsStyle ==
u"colibre" || rsStyle ==
u"helpimg")
333 else if (rsStyle ==
u"sifr" || rsStyle ==
u"breeze_dark")
335 else if (rsStyle ==
u"sifr_dark" )
336 sResult =
"breeze_dark";
346 OUString aCurrentStyle(rStyle);
347 while (!aCurrentStyle.isEmpty())
355 catch (uno::RuntimeException &)
371 OUString aVariant = OUString::number(aScalePercentage);
373 if (bConvertToDarkTheme)
381 OUString sUrl(getIconCacheUrl(sVariant, rParameters));
382 if (!urlExists(sUrl))
386 aPNGReader.read(rParameters.
mrBitmap);
392 OUString sUrl(createIconCacheUrl(sVariant, rParameters));
397 aWriter.write(rParameters.
mrBitmap);
413 OUString aVariant = createVariant(rParameters);
414 if (loadDiskCachedVersion(aVariant, rParameters))
422 std::vector<OUString> aPaths =
getPaths(rParameters.
msName, aLanguageTag);
430 catch (uno::RuntimeException&)
434 catch (
const uno::Exception&)
443 cacheBitmapToDisk(aVariant, rParameters);
459 assert(!style.isEmpty());
473 static const bool bVclDemoOverride = std::getenv(
"LIBO_VCL_DEMO") !=
nullptr;
474 return bVclDemoOverride;
487 sThemeUrl =
"file://" SRC_ROOT
"/icon-themes/colibre-svg";
494 std::deque<OUString> aPaths;
498 aPaths.push_front(paths.getToken(0,
';',
nIndex));
502 for (
const auto& path : aPaths)
510 if (urlExists(sThemeUrl))
515 if (sThemeUrl.isEmpty())
520 sThemeUrl +=
"images";
521 if (!urlExists(sThemeUrl))
535 if ( it !=
rSet.maScaledIconCaches.end() )
546 if (
i != rIconCache.end() &&
i->second.first == rParameters.
mbLocalized)
562 for (OUString
const & rPath : rPaths)
564 if (rNameAccess->hasByName(rPath))
566 uno::Reference<io::XInputStream> aStream;
567 bool ok = rNameAccess->getByName(rPath) >>= aStream;
571 loadImageFromStream(wrapStream(aStream), rPath, rParameters);
581 static constexpr OUStringLiteral aLinkFilename(
u"links.txt");
588 if (rNameAccess->hasByName(aLinkFilename))
590 uno::Reference<io::XInputStream>
xStream;
591 bool ok = rNameAccess->getByName(aLinkFilename) >>=
xStream;
603 OUString aLink, aOriginal;
605 while (
xStream->ReadLine(aLine))
616 if (aLink.isEmpty() || aLink[0] ==
'#' || aOriginal.isEmpty())
618 if (aLink.isEmpty() || aOriginal.isEmpty())
619 SAL_WARN(
"vcl",
"ImplImageTree::parseLinkFile: icon links.txt parse error, incomplete link at line " << nLineNo);
625 OUString aOriginal32 = convertLcTo32Path(aOriginal);
626 OUString aLink32 = convertLcTo32Path(aLink);
628 if (!aOriginal32.isEmpty() && !aLink32.isEmpty())
637 OUString sNameWithNoExtension = getNameNoExtension(rIconName);
640 auto it = rLinkHash.find(sNameWithNoExtension +
".png");
641 if (it != rLinkHash.end())
645 it = rLinkHash.find(sNameWithNoExtension +
".svg");
646 if (it != rLinkHash.end())
655class FolderFileAccess :
public ::cppu::WeakImplHelper<css::container::XNameAccess>
658 uno::Reference< uno::XComponentContext >
mxContext;
660 FolderFileAccess(uno::Reference< uno::XComponentContext > context, OUString url)
664 virtual sal_Bool SAL_CALL hasElements()
override {
return true; }
666 virtual css::uno::Any SAL_CALL getByName(
const OUString& aName )
override
668 uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(mxContext)->openFileRead( maURL +
"/" + aName );
669 return css::uno::Any(xInputStream);
671 virtual css::uno::Sequence< OUString > SAL_CALL getElementNames()
override
675 virtual sal_Bool SAL_CALL hasByName(
const OUString& aName )
override
677 osl::File aBaseFile(maURL +
"/" + aName);
678 return osl::File::E_None == aBaseFile.open(osl_File_OpenFlag_Read);
687 uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.
maNameAccess;
688 if (rNameAccess.is())
698 catch (
const uno::RuntimeException &)
702 catch (
const uno::Exception &)
707 return rNameAccess.is();
static bool isVclDemo()
The vcldemo app doesn't set up all the config stuff that the main app does, so we need another way of...
const LanguageTag & GetUILanguageTag() const
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
static const AllSettings & GetSettings()
Gets the application's settings.
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
bool Convert(BmpConversion eConversion)
Convert bitmap format.
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool Append(std::u16string_view rTheSegment, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
std::unordered_map< OUString, OUString > IconLinkHash
std::shared_ptr< SvMemoryStream > getImageStream(OUString const &rName, OUString const &rStyle, OUString const &rLang)
bool iconCacheLookup(ImageRequestParameters &rParameters)
OUString getImageUrl(OUString const &name, OUString const &style, OUString const &lang)
bool doLoadImage(ImageRequestParameters &rParameters)
OUString maCurrentStyle
Style used for the current operations; switches switch several times during fallback search.
void shutdown()
a crude form of life cycle control (called from DeInitVCL; otherwise, if the ImplImageTree singleton ...
OUString const & getRealImageName(OUString const &rName)
Return name of a real .png according to links.txt.
std::vector< OUString > getPaths(OUString const &name, LanguageTag const &rLanguageTag)
std::unordered_map< OUString, IconSet > maIconSets
Remember all the (used) icon styles and individual icons in them.
IconSet & getCurrentIconSet()
css::uno::Reference< css::container::XNameAccess > const & getNameAccess()
IconCache & getIconCache(const ImageRequestParameters &rParameters)
Find an icon cache for the right scale factor.
static OUString fallbackStyle(std::u16string_view rStyle)
Return name of the fallback style for the provided one.
css::uno::Reference< css::io::XInputStream > getImageXInputStream(OUString const &rName, OUString const &rStyle, OUString const &rLang)
std::unordered_map< OUString, std::pair< bool, BitmapEx > > IconCache
bool loadImage(OUString const &name, OUString const &style, BitmapEx &bitmap, bool localized, const ImageLoadFlags eFlags, sal_Int32 nScalePercentage=-1)
void setStyle(OUString const &rStyle)
bool findImage(std::vector< OUString > const &rPaths, ImageRequestParameters &rParameters)
void parseLinkFile(std::shared_ptr< SvStream > const &aStream)
::std::vector< OUString > getFallbackStrings(bool bIncludeFullBcp47) const
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
sal_Int32 GetDPIScalePercentage() const
css::uno::Type const & get()
static OUString GetStandardIconThemePath()
This method will return the standard path where icon themes are located.
#define SAL_CONFIGFILE(name)
#define TOOLS_INFO_EXCEPTION(area, stream)
Reference< XInputStream > rInputStream
#define SAL_WARN(area, stream)
constexpr OUStringLiteral aData
Reference< XComponentContext > getProcessComponentContext()
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
void loadFromSvg(SvStream &rStream, const OUString &sPath, BitmapEx &rBitmapEx, double fScalingFactor)
sal_Int32 scalePercentage()
bool convertToDarkTheme()
sal_Int32 mnScalePercentage
css::uno::Reference< css::container::XNameAccess > maNameAccess