From 6948c546fdc00dddec7d58e03150dcc87921d6b2 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Mon, 26 Oct 2015 17:55:14 +0100 Subject: tdf#75637: Resolve help images via a vnd.libreoffice.image UCP ...which uses the logic already available in VCL's ImplImageTree to locate the image zip files and find fallbacks for incomplete themes and for localized images. Change-Id: Ic1c15fcacb6596a27a2b051093232902202bf472 --- vcl/inc/impimagetree.hxx | 117 ------------------------------------- vcl/osx/vclnsapp.mm | 4 +- vcl/source/app/settings.cxx | 2 +- vcl/source/app/svmain.cxx | 4 +- vcl/source/control/fixed.cxx | 6 +- vcl/source/gdi/bitmapex.cxx | 6 +- vcl/source/gdi/image.cxx | 6 +- vcl/source/gdi/imagerepository.cxx | 8 +-- vcl/source/gdi/impimagetree.cxx | 71 ++++++++++++++++++++-- 9 files changed, 82 insertions(+), 142 deletions(-) delete mode 100644 vcl/inc/impimagetree.hxx (limited to 'vcl') diff --git a/vcl/inc/impimagetree.hxx b/vcl/inc/impimagetree.hxx deleted file mode 100644 index 2ee52c8dd917..000000000000 --- a/vcl/inc/impimagetree.hxx +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_VCL_INC_IMPIMAGETREE_HXX -#define INCLUDED_VCL_INC_IMPIMAGETREE_HXX - -#include "sal/config.h" - -#include -#include -#include - -#include "com/sun/star/uno/Reference.hxx" -#include "rtl/ustring.hxx" -#include "salhelper/singletonref.hxx" - -namespace com { namespace sun { namespace star { namespace container { - class XNameAccess; -} } } } -class BitmapEx; - -class ImplImageTree { -public: - ImplImageTree(); - - ~ImplImageTree(); - - bool loadImage( - OUString const & name, OUString const & style, - BitmapEx & bitmap, bool localized = false, bool loadMissing = false ); - - bool loadDefaultImage( - OUString const & style, - BitmapEx& bitmap); - - /** a crude form of life cycle control (called from DeInitVCL; otherwise, - * if the ImplImageTree singleton were destroyed during exit that would - * be too late for the destructors of the bitmaps in maIconCache)*/ - void shutDown(); - - css::uno::Reference< css::container::XNameAccess > getNameAccess(); - -private: - ImplImageTree(const ImplImageTree&) = delete; - ImplImageTree& operator=(const ImplImageTree&) = delete; - - typedef std::unordered_map, OUStringHash> IconCache; - typedef std::unordered_map IconLinkHash; - - struct IconSet { - OUString maURL; - css::uno::Reference maNameAccess; - IconCache maIconCache; - IconLinkHash maLinkHash; - - IconSet() {} - IconSet(const OUString &aURL) : maURL(aURL) {} - }; - - /// Map between the theme name(s) and the content. - typedef std::unordered_map StyleIconSet; - - /// Remember all the (used) icon styles and individual icons in them. - StyleIconSet maIconSet; - - /// Style used for the current operations; switches switch several times during fallback search. - OUString maCurrentStyle; - - bool doLoadImage( - OUString const & name, OUString const & style, - BitmapEx & bitmap, bool localized); - - bool checkPathAccess(); - - void setStyle(OUString const & style ); - - void createStyle(); - - bool iconCacheLookup( OUString const & name, bool localized, BitmapEx & bitmap ); - - bool findImage(std::vector< OUString > const & paths, BitmapEx & bitmap ); - - void loadImageLinks(); - - void parseLinkFile(std::shared_ptr stream); - - /// Return name of a real .png according to links.txt. - OUString const & getRealImageName(OUString const & name); - - /** Return name of the fallback style for the provided one. - - Must not be cyclic :-) The last theme in the chain returns an empty string. - */ - static OUString fallbackStyle(const OUString &style); -}; - -typedef salhelper::SingletonRef< ImplImageTree > ImplImageTreeSingletonRef; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm index 2614754cf4ce..fd0d58333b57 100644 --- a/vcl/osx/vclnsapp.mm +++ b/vcl/osx/vclnsapp.mm @@ -24,10 +24,10 @@ #include #include +#include #include #include -#include "impimagetree.hxx" #include "osx/saldata.hxx" #include "osx/salframe.h" #include "osx/salframeview.h" @@ -412,7 +412,7 @@ { ApplicationEvent aEv(ApplicationEvent::TYPE_PRIVATE_DOSHUTDOWN); GetpApp()->AppEvent( aEv ); - ImplImageTreeSingletonRef()->shutDown(); + ImplImageTree::get().shutDown(); // DeInitVCL should be called in ImplSVMain - unless someon _exits first which // can occur in Desktop::doShutdown for example } diff --git a/vcl/source/app/settings.cxx b/vcl/source/app/settings.cxx index a8fb56a9633d..2fd759794732 100644 --- a/vcl/source/app/settings.cxx +++ b/vcl/source/app/settings.cxx @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,6 @@ using namespace ::com::sun::star; #include "svdata.hxx" -#include "impimagetree.hxx" struct ImplMouseData { diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index d2fe69a171ee..684546f430e0 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -35,6 +35,7 @@ #include "vcl/cvtgrf.hxx" #include "vcl/scheduler.hxx" #include "vcl/image.hxx" +#include "vcl/implimagetree.hxx" #include "vcl/settings.hxx" #include "vcl/unowrap.hxx" #include "vcl/configsettings.hxx" @@ -68,7 +69,6 @@ #include "salsys.hxx" #include "saltimer.hxx" #include "salimestatus.hxx" -#include "impimagetree.hxx" #include "xconnection.hxx" #include "vcl/opengl/OpenGLContext.hxx" @@ -368,7 +368,7 @@ void DeInitVCL() DBG_ASSERT( nBadTopWindows==0, aBuf.getStr() ); #endif - ImplImageTreeSingletonRef()->shutDown(); + ImplImageTree::get().shutDown(); osl_removeSignalHandler( pExceptionHandler); pExceptionHandler = NULL; diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx index 990f1a6cf2d3..9502c08e97fc 100644 --- a/vcl/source/control/fixed.cxx +++ b/vcl/source/control/fixed.cxx @@ -23,12 +23,12 @@ #include "vcl/dialog.hxx" #include "vcl/event.hxx" #include "vcl/fixed.hxx" +#include "vcl/implimagetree.hxx" #include "vcl/svapp.hxx" #include "vcl/settings.hxx" #include #include "controldata.hxx" -#include "impimagetree.hxx" #include "window.h" #define FIXEDLINE_TEXT_BORDER 4 @@ -1035,12 +1035,12 @@ bool FixedImage::SetModeImage( const Image& rImage ) Image FixedImage::loadThemeImage(const OString &rFileName) { - static ImplImageTreeSingletonRef aImageTree; OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); const OUString sFileName(OStringToOUString(rFileName, RTL_TEXTENCODING_UTF8)); BitmapEx aBitmap; - bool bSuccess = aImageTree->loadImage(sFileName, sIconTheme, aBitmap, true); + bool bSuccess = ImplImageTree::get().loadImage( + sFileName, sIconTheme, aBitmap, true); SAL_WARN_IF(!bSuccess, "vcl.layout", "Unable to load " << sFileName << " from theme " << sIconTheme); return Image(aBitmap); diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index 804e64616757..8fa1211498c5 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include -#include #include // BitmapEx::Create @@ -107,11 +107,9 @@ BitmapEx::BitmapEx( const ResId& rResId ) : void BitmapEx::loadFromIconTheme( const OUString& rIconName ) { - static ImplImageTreeSingletonRef aImageTree; - OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); - if( !aImageTree->loadImage( rIconName, aIconTheme, *this, true ) ) + if( !ImplImageTree::get().loadImage( rIconName, aIconTheme, *this, true ) ) { #ifdef DBG_UTIL OStringBuffer aErrorStr( diff --git a/vcl/source/gdi/image.cxx b/vcl/source/gdi/image.cxx index adfec173cfd5..f6e70cf78799 100644 --- a/vcl/source/gdi/image.cxx +++ b/vcl/source/gdi/image.cxx @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #if OSL_DEBUG_LEVEL > 0 @@ -370,8 +370,6 @@ void ImageList::ImplInit( sal_uInt16 nItems, const Size &rSize ) void ImageAryData::Load(const OUString &rPrefix) { - static ImplImageTreeSingletonRef aImageTree; - OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); OUString aFileName = rPrefix; @@ -379,7 +377,7 @@ void ImageAryData::Load(const OUString &rPrefix) #if OSL_DEBUG_LEVEL > 0 bool bSuccess = #endif - aImageTree->loadImage( aFileName, aIconTheme, maBitmapEx, true ); + ImplImageTree::get().loadImage(aFileName, aIconTheme, maBitmapEx, true); #if OSL_DEBUG_LEVEL > 0 if ( !bSuccess ) { diff --git a/vcl/source/gdi/imagerepository.cxx b/vcl/source/gdi/imagerepository.cxx index 66398d972328..dadc622cdcce 100644 --- a/vcl/source/gdi/imagerepository.cxx +++ b/vcl/source/gdi/imagerepository.cxx @@ -19,9 +19,9 @@ #include #include +#include #include #include -#include "impimagetree.hxx" namespace vcl { @@ -29,15 +29,13 @@ namespace vcl { OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); - ImplImageTreeSingletonRef aImplImageTree; - return aImplImageTree->loadImage( _rName, sIconTheme, _out_rImage, _bSearchLanguageDependent, loadMissing ); + return ImplImageTree::get().loadImage( _rName, sIconTheme, _out_rImage, _bSearchLanguageDependent, loadMissing ); } bool ImageRepository::loadDefaultImage( BitmapEx& _out_rImage) { OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme(); - ImplImageTreeSingletonRef aImplImageTree; - return aImplImageTree->loadDefaultImage( sIconTheme,_out_rImage); + return ImplImageTree::get().loadDefaultImage( sIconTheme,_out_rImage); } } // namespace vcl diff --git a/vcl/source/gdi/impimagetree.cxx b/vcl/source/gdi/impimagetree.cxx index 38cfefdb14fe..9bec5dcfe83f 100644 --- a/vcl/source/gdi/impimagetree.cxx +++ b/vcl/source/gdi/impimagetree.cxx @@ -34,15 +34,16 @@ #include "osl/file.hxx" #include "osl/diagnose.h" #include "rtl/bootstrap.hxx" +#include "rtl/uri.hxx" #include "tools/stream.hxx" #include "tools/urlobj.hxx" #include "vcl/bitmapex.hxx" #include +#include #include "vcl/pngread.hxx" #include "vcl/settings.hxx" #include "vcl/svapp.hxx" -#include "impimagetree.hxx" #include #include @@ -93,6 +94,11 @@ static void loadImageFromStream(std::shared_ptr xStream, OUString cons } +ImplImageTree & ImplImageTree::get() { + static ImplImageTree instance; + return instance; +} + ImplImageTree::ImplImageTree() { } @@ -101,6 +107,65 @@ ImplImageTree::~ImplImageTree() { } +OUString ImplImageTree::getImageUrl( + OUString const & name, OUString const & style, OUString const & lang) +{ + OUString aStyle(style); + while (!aStyle.isEmpty()) + { + try { + setStyle(aStyle); + + std::vector< OUString > paths; + paths.push_back(getRealImageName(name)); + + if (!lang.isEmpty()) + { + sal_Int32 pos = name.lastIndexOf('/'); + if (pos != -1) + { + std::vector aFallbacks( + LanguageTag(lang).getFallbackStrings(true)); + for (std::vector< OUString >::reverse_iterator it( aFallbacks.rbegin()); + it != aFallbacks.rend(); ++it) + { + paths.push_back( getRealImageName( createPath(name, pos, *it) ) ); + } + } + } + + try { + if (checkPathAccess()) { + const uno::Reference &rNameAccess = maIconSet[maCurrentStyle].maNameAccess; + + for (std::vector::const_reverse_iterator j(paths.rbegin()); j != paths.rend(); ++j) + { + if (rNameAccess->hasByName(*j)) + { + return "vnd.sun.star.zip://" + + rtl::Uri::encode( + maIconSet[maCurrentStyle].maURL + ".zip", + rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8) + + "/" + *j; + // assuming *j contains no problematic chars + } + } + } + } catch (css::uno::RuntimeException &) { + throw; + } catch (const css::uno::Exception & e) { + SAL_INFO("vcl", "exception " << e.Message); + } + } + catch (css::uno::RuntimeException &) {} + + aStyle = fallbackStyle(aStyle); + } + return OUString(); +} + OUString ImplImageTree::fallbackStyle(const OUString &style) { if (style == "galaxy") @@ -361,9 +426,7 @@ css::uno::Reference ImplImageTree::getNameAccess() /// Recursively dump all names ... css::uno::Sequence ImageTree_getAllImageNames() { - static ImplImageTreeSingletonRef aImageTree; - - css::uno::Reference xRef(aImageTree->getNameAccess()); + css::uno::Reference xRef(ImplImageTree::get().getNameAccess()); return xRef->getElementNames(); } -- cgit