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;
82 return aScalePercentage;
88OUString convertLcTo32Path(std::u16string_view rPath)
91 size_t nSlashPos = rPath.rfind(
'/');
92 if (nSlashPos != std::u16string_view::npos)
94 sal_Int32 nCopyFrom = nSlashPos + 1;
95 std::u16string_view sFile = rPath.substr(nCopyFrom);
96 std::u16string_view sDir = rPath.substr(0, nSlashPos);
99 aResult = OUString::Concat(sDir) +
"/32/" + sFile.substr(3);
105OUString createPath(std::u16string_view name, sal_Int32 pos, std::u16string_view locale)
107 return OUString::Concat(
name.substr(0, pos + 1)) + locale +
name.substr(pos);
113 static OUString CACHE_DIR = []()
115 OUString sDir =
"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"bootstrap")
":UserInstallation}/cache/";
116 rtl::Bootstrap::expandMacros(sDir);
119 return CACHE_DIR + rParameters.
msStyle +
"/" + sVariant +
"/" + rParameters.
msName;
122OUString createIconCacheUrl(
125 OUString sUrl(getIconCacheUrl(sVariant, rParameters));
126 OUString sDir = sUrl.copy(0, sUrl.lastIndexOf(
'/'));
127 osl::Directory::createPath(sDir);
131bool urlExists(OUString
const & sUrl)
133 osl::File aFile(sUrl);
134 osl::FileBase::RC eRC = aFile.open(osl_File_OpenFlag_Read);
135 return osl::FileBase::E_None == eRC;
138OUString getNameNoExtension(std::u16string_view sName)
140 size_t nDotPosition =
sName.rfind(
'.');
141 return OUString(
sName.substr(0, nDotPosition));
144std::shared_ptr<SvMemoryStream> wrapStream(uno::Reference<io::XInputStream>
const & rInputStream)
151 std::shared_ptr<SvMemoryStream> aMemoryStream(std::make_shared<SvMemoryStream>());
154 const sal_Int32 nSize(2048);
155 uno::Sequence<sal_Int8>
aData(nSize);
156 sal_Int32 nRead =
rInputStream->readBytes(aData, nSize);
157 aMemoryStream->WriteBytes(
aData.getConstArray(), nRead);
161 aMemoryStream->Seek(0);
163 return aMemoryStream;
166void loadImageFromStream(std::shared_ptr<SvStream>
const & xStream, OUString
const & rPath,
ImageRequestParameters& rParameters)
171 if (rPath.endsWith(
".png"))
174 aPNGReader.read(rParameters.
mrBitmap);
176 else if (rPath.endsWith(
".svg"))
181 if (bConvertToDarkTheme)
191 if (bConvertToDarkTheme)
197 if (aScalePercentage > 100)
200 double aScaleFactor(aScalePercentage / 100.0);
219 std::vector<OUString> sPaths;
221 sal_Int32
pos =
name.lastIndexOf(
'/');
227 sPaths.emplace_back(aFallbackName +
".png");
228 sPaths.emplace_back(aFallbackName +
".svg");
233 sPaths.emplace_back(aRealName +
".png");
234 sPaths.emplace_back(aRealName +
".svg");
241 OUString aStyle(rStyle);
243 while (!aStyle.isEmpty())
252 const uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.
maNameAccess;
256 for (
const OUString& rPath:
getPaths(rName, aLanguageTag))
258 if (rNameAccess->hasByName(rPath))
260 return "vnd.sun.star.zip://"
261 + rtl::Uri::encode(rIconSet.
maURL, rtl_UriCharClassRegName,
262 rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8)
268 catch (
const uno::Exception &)
280 OUString aStyle(rStyle);
282 while (!aStyle.isEmpty())
291 const uno::Reference<container::XNameAccess>& rNameAccess = rIconSet.
maNameAccess;
295 for (
const OUString& rPath:
getPaths(rName, aLanguageTag))
297 if (rNameAccess->hasByName(rPath))
299 uno::Reference<io::XInputStream> aStream;
300 bool ok = rNameAccess->getByName(rPath) >>= aStream;
303 return wrapStream(aStream);
308 catch (
const uno::Exception &)
315 return std::shared_ptr<SvMemoryStream>();
322 if (rsStyle ==
u"colibre" || rsStyle ==
u"helpimg")
324 else if (rsStyle ==
u"sifr" || rsStyle ==
u"breeze_dark")
326 else if (rsStyle ==
u"sifr_dark" )
327 sResult =
"breeze_dark";
337 OUString aCurrentStyle(rStyle);
338 while (!aCurrentStyle.isEmpty())
346 catch (uno::RuntimeException &)
362 OUString aVariant = OUString::number(aScalePercentage);
364 if (bConvertToDarkTheme)
372 OUString sUrl(getIconCacheUrl(sVariant, rParameters));
373 if (!urlExists(sUrl))
377 aPNGReader.read(rParameters.
mrBitmap);
383 OUString sUrl(createIconCacheUrl(sVariant, rParameters));
388 aWriter.write(rParameters.
mrBitmap);
404 OUString aVariant = createVariant(rParameters);
405 if (loadDiskCachedVersion(aVariant, rParameters))
413 std::vector<OUString> aPaths =
getPaths(rParameters.
msName, aLanguageTag);
421 catch (uno::RuntimeException&)
425 catch (
const uno::Exception&)
434 cacheBitmapToDisk(aVariant, rParameters);
450 assert(!style.isEmpty());
464 static const bool bVclDemoOverride = std::getenv(
"LIBO_VCL_DEMO") !=
nullptr;
465 return bVclDemoOverride;
478 sThemeUrl =
"file://" SRC_ROOT
"/icon-themes/colibre-svg";
485 std::deque<OUString> aPaths;
489 aPaths.push_front(paths.getToken(0,
';',
nIndex));
493 for (
const auto& path : aPaths)
501 if (urlExists(sThemeUrl))
506 if (sThemeUrl.isEmpty())
511 sThemeUrl +=
"images";
512 if (!urlExists(sThemeUrl))
526 if ( it !=
rSet.maScaledIconCaches.end() )
537 if (
i != rIconCache.end() &&
i->second.first == rParameters.
mbLocalized)
553 for (OUString
const & rPath : rPaths)
555 if (rNameAccess->hasByName(rPath))
557 uno::Reference<io::XInputStream> aStream;
558 bool ok = rNameAccess->getByName(rPath) >>= aStream;
562 loadImageFromStream(wrapStream(aStream), rPath, rParameters);
572 static const OUStringLiteral aLinkFilename(
u"links.txt");
579 if (rNameAccess->hasByName(aLinkFilename))
581 uno::Reference<io::XInputStream>
xStream;
582 bool ok = rNameAccess->getByName(aLinkFilename) >>=
xStream;
594 OUString aLink, aOriginal;
596 while (
xStream->ReadLine(aLine))
607 if (aLink.isEmpty() || aLink[0] ==
'#' || aOriginal.isEmpty())
609 if (aLink.isEmpty() || aOriginal.isEmpty())
610 SAL_WARN(
"vcl",
"ImplImageTree::parseLinkFile: icon links.txt parse error, incomplete link at line " << nLineNo);
616 OUString aOriginal32 = convertLcTo32Path(aOriginal);
617 OUString aLink32 = convertLcTo32Path(aLink);
619 if (!aOriginal32.isEmpty() && !aLink32.isEmpty())
628 OUString sNameWithNoExtension = getNameNoExtension(rIconName);
631 auto it = rLinkHash.find(sNameWithNoExtension +
".png");
632 if (it != rLinkHash.end())
636 it = rLinkHash.find(sNameWithNoExtension +
".svg");
637 if (it != rLinkHash.end())
646class FolderFileAccess :
public ::cppu::WeakImplHelper<css::container::XNameAccess>
649 uno::Reference< uno::XComponentContext >
mxContext;
651 FolderFileAccess(uno::Reference< uno::XComponentContext > context, OUString url)
655 virtual sal_Bool SAL_CALL hasElements()
override {
return true; }
657 virtual css::uno::Any SAL_CALL getByName(
const OUString& aName )
override
659 uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(mxContext)->openFileRead( maURL +
"/" + aName );
660 return css::uno::Any(xInputStream);
662 virtual css::uno::Sequence< OUString > SAL_CALL getElementNames()
override
666 virtual sal_Bool SAL_CALL hasByName(
const OUString& aName )
override
668 osl::File aBaseFile(maURL +
"/" + aName);
669 return osl::File::E_None == aBaseFile.open(osl_File_OpenFlag_Read);
678 uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.
maNameAccess;
679 if (rNameAccess.is())
689 catch (
const uno::RuntimeException &)
693 catch (
const uno::Exception &)
698 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.
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
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