1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2008 by Sun Microsystems, Inc.
6 * OpenOffice.org - a multi-platform office productivity suite
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
28 ************************************************************************/
30 #include "precompiled_vcl.hxx"
31 #include "sal/config.h"
40 #include "com/sun/star/container/XNameAccess.hpp"
41 #include "com/sun/star/io/XInputStream.hpp"
42 #include "com/sun/star/lang/Locale.hpp"
43 #include "com/sun/star/uno/Any.hxx"
44 #include "com/sun/star/uno/Exception.hpp"
45 #include "com/sun/star/uno/Reference.hxx"
46 #include "com/sun/star/uno/RuntimeException.hpp"
47 #include "com/sun/star/uno/Sequence.hxx"
48 #include "comphelper/processfactory.hxx"
49 #include "osl/file.hxx"
50 #include "osl/diagnose.h"
51 #include "rtl/bootstrap.hxx"
52 #include "rtl/string.h"
53 #include "rtl/textenc.h"
54 #include "rtl/ustrbuf.hxx"
55 #include "rtl/ustring.h"
56 #include "rtl/ustring.hxx"
57 #include "sal/types.h"
58 #include "tools/stream.hxx"
59 #include "tools/urlobj.hxx"
60 #include "vcl/bitmapex.hxx"
61 #include "vcl/impimagetree.hxx"
62 #include "vcl/pngread.hxx"
63 #include "vcl/settings.hxx"
64 #include "vcl/svapp.hxx"
68 namespace css
= com::sun::star
;
70 rtl::OUString
createPath(
71 rtl::OUString
const & name
, sal_Int32 pos
, rtl::OUString
const & locale
)
73 rtl::OUStringBuffer
b(name
.copy(0, pos
+ 1));
75 b
.append(name
.copy(pos
));
76 return b
.makeStringAndClear();
79 std::auto_ptr
< SvStream
> wrapStream(
80 css::uno::Reference
< css::io::XInputStream
> const & stream
)
82 // This could use SvInputStream instead if that did not have a broken
83 // SeekPos implementation for an XInputStream that is not also XSeekable
84 // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
86 OSL_ASSERT(stream
.is());
87 std::auto_ptr
< SvStream
> s(new SvMemoryStream
);
89 css::uno::Sequence
< sal_Int8
> data
;
90 sal_Int32
const size
= 30000;
91 sal_Int32 n
= stream
->readBytes(data
, size
);
92 s
->Write(data
.getConstArray(), n
);
102 css::uno::Reference
< css::io::XInputStream
> const & stream
,
103 rtl::OUString
const & path
, BitmapEx
& bitmap
)
105 std::auto_ptr
< SvStream
> s(wrapStream(stream
));
106 if (path
.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".png")))
108 vcl::PNGReader
aPNGReader( *s
);
109 aPNGReader
.SetIgnoreGammaChunk( sal_True
);
110 bitmap
= aPNGReader
.Read();
118 ImplImageTree::ImplImageTree()
120 m_datadir
= ::rtl::OUString::createFromAscii ( "/usr/share/" );
122 m_libdir
= ::rtl::OUString::createFromAscii ( "/usr/lib64/" );
124 m_libdir
= ::rtl::OUString::createFromAscii ( "/usr/lib/" );
128 ImplImageTree::~ImplImageTree() {}
130 bool ImplImageTree::checkStyle(rtl::OUString
const & style
)
134 // using cache because setStyle is an expensive operation
135 // setStyle calls resetZips => closes any opened zip files with icons, cleans the icon cache, ...
136 if (checkStyleCacheLookup(style
, exists
)) {
143 const rtl::OUString
sBrandURLSuffix(RTL_CONSTASCII_USTRINGPARAM("_brand.zip"));
144 for (Zips::iterator
i(m_zips
.begin()); i
!= m_zips
.end() && !exists
;) {
145 ::rtl::OUString aZipURL
= i
->first
;
146 sal_Int32 nFromIndex
= aZipURL
.getLength() - sBrandURLSuffix
.getLength();
147 // skip brand-specific icon themes; they are incomplete and thus not useful for this check
148 if (nFromIndex
< 0 || !aZipURL
.match(sBrandURLSuffix
, nFromIndex
)) {
149 osl::File
aZip(aZipURL
);
150 if (aZip
.open(OpenFlag_Read
) == ::osl::FileBase::E_None
) {
157 m_checkStyleCache
[style
] = exists
;
161 bool ImplImageTree::loadImage(
162 rtl::OUString
const & name
, rtl::OUString
const & style
, BitmapEx
& bitmap
,
166 if (iconCacheLookup(name
, localized
, bitmap
)) {
169 if (!bitmap
.IsEmpty()) {
172 std::vector
< rtl::OUString
> paths
;
173 paths
.push_back(name
);
175 sal_Int32 pos
= name
.lastIndexOf('/');
177 css::lang::Locale
const & loc
=
178 Application::GetSettings().GetUILocale();
179 paths
.push_back(createPath(name
, pos
, loc
.Language
));
180 if (loc
.Country
.getLength() != 0) {
181 rtl::OUStringBuffer
b(loc
.Language
);
182 b
.append(sal_Unicode('-'));
183 b
.append(loc
.Country
);
184 rtl::OUString
p(createPath(name
, pos
, b
.makeStringAndClear()));
186 if (loc
.Variant
.getLength() != 0) {
188 b
.append(sal_Unicode('-'));
189 b
.append(loc
.Variant
);
191 createPath(name
, pos
, b
.makeStringAndClear()));
198 found
= find(paths
, bitmap
);
199 } catch (css::uno::RuntimeException
&) {
201 } catch (css::uno::Exception
& e
) {
203 "ImplImageTree::loadImage exception \"%s\"",
204 rtl::OUStringToOString(e
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
207 m_iconCache
[name
.intern()] = std::make_pair(localized
, bitmap
);
212 void ImplImageTree::shutDown() {
213 m_style
= rtl::OUString();
214 // for safety; empty m_style means "not initialized"
217 m_checkStyleCache
.clear();
220 void ImplImageTree::setStyle(rtl::OUString
const & style
) {
221 OSL_ASSERT(style
.getLength() != 0); // empty m_style means "not initialized"
222 if (style
!= m_style
) {
229 void ImplImageTree::addUrlToZips(const rtl::OUString
&url
) {
230 if ( url
.getLength() == 0 )
235 css::uno::Reference
< css::container::XNameAccess
>()));
236 sal_Int32 nLibDirPos
= url
.indexOf( m_libdir
);
237 if ( nLibDirPos
>= 0 ) {
240 url
.replaceAt( nLibDirPos
, m_libdir
.getLength(), m_datadir
),
241 css::uno::Reference
< css::container::XNameAccess
>()));
245 void ImplImageTree::resetZips() {
249 RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/edition/images.zip"));
250 rtl::Bootstrap::expandMacros(url
);
251 INetURLObject
u(url
);
252 OSL_ASSERT(!u
.HasError());
255 u
.GetMainURL(INetURLObject::NO_DECODE
),
256 css::uno::Reference
< css::container::XNameAccess
>()));
260 RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/share/config"));
261 rtl::Bootstrap::expandMacros(url
);
262 INetURLObject
u(url
);
263 OSL_ASSERT(!u
.HasError());
264 rtl::OUStringBuffer b
;
265 b
.appendAscii(RTL_CONSTASCII_STRINGPARAM("images_"));
267 b
.appendAscii(RTL_CONSTASCII_STRINGPARAM("_brand.zip"));
268 bool ok
= u
.Append(b
.makeStringAndClear(), INetURLObject::ENCODE_ALL
);
269 OSL_ASSERT(ok
); (void) ok
;
270 addUrlToZips(u
.GetMainURL(INetURLObject::NO_DECODE
));
274 RTL_CONSTASCII_USTRINGPARAM(
275 "$BRAND_BASE_DIR/share/config/images_brand.zip"));
276 rtl::Bootstrap::expandMacros(url
);
281 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/config"));
282 rtl::Bootstrap::expandMacros(url
);
283 INetURLObject
u(url
);
284 OSL_ASSERT(!u
.HasError());
285 rtl::OUStringBuffer b
;
286 b
.appendAscii(RTL_CONSTASCII_STRINGPARAM("images_"));
288 b
.appendAscii(RTL_CONSTASCII_STRINGPARAM(".zip"));
289 bool ok
= u
.Append(b
.makeStringAndClear(), INetURLObject::ENCODE_ALL
);
290 OSL_ASSERT(ok
); (void) ok
;
291 addUrlToZips(u
.GetMainURL(INetURLObject::NO_DECODE
));
293 if ( m_style
.equals(::rtl::OUString::createFromAscii("default")) )
296 RTL_CONSTASCII_USTRINGPARAM(
297 "$OOO_BASE_DIR/share/config/images.zip"));
298 rtl::Bootstrap::expandMacros(url
);
303 bool ImplImageTree::checkStyleCacheLookup(
304 rtl::OUString
const & style
, bool &exists
)
306 CheckStyleCache::iterator
i(m_checkStyleCache
.find(style
));
307 if (i
!= m_checkStyleCache
.end()) {
315 bool ImplImageTree::iconCacheLookup(
316 rtl::OUString
const & name
, bool localized
, BitmapEx
& bitmap
)
318 IconCache::iterator
i(m_iconCache
.find(name
));
319 if (i
!= m_iconCache
.end() && i
->second
.first
== localized
) {
320 bitmap
= i
->second
.second
;
327 bool ImplImageTree::find(
328 std::vector
< rtl::OUString
> const & paths
, BitmapEx
& bitmap
)
330 for (Zips::iterator
i(m_zips
.begin()); i
!= m_zips
.end();) {
331 if (!i
->second
.is()) {
332 css::uno::Sequence
< css::uno::Any
> args(1);
333 args
[0] <<= i
->first
;
336 comphelper::createProcessComponentWithArguments(
338 RTL_CONSTASCII_USTRINGPARAM(
339 "com.sun.star.packages.zip.ZipFileAccess")),
341 css::uno::UNO_QUERY_THROW
);
342 } catch (css::uno::RuntimeException
&) {
344 } catch (css::uno::Exception
& e
) {
346 "ImplImageTree::find exception \"%s\"",
347 rtl::OUStringToOString(
348 e
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
353 for (std::vector
< rtl::OUString
>::const_reverse_iterator
j(
355 j
!= paths
.rend(); ++j
)
357 if (i
->second
->hasByName(*j
)) {
358 css::uno::Reference
< css::io::XInputStream
> s
;
359 bool ok
= i
->second
->getByName(*j
) >>= s
;
360 OSL_ASSERT(ok
); (void) ok
;
361 loadFromStream(s
, *j
, bitmap
);