update dev300-m58
[ooovba.git] / vcl / source / gdi / impimagetree.cxx
blobd407cb483ca2147276c6c64e03b25877a06d0d08
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
8 * $RCSfile: code,v $
10 * $Revision: 1.4 $
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"
33 #include <list>
34 #include <memory>
35 #include <utility>
36 #include <vector>
38 #include <hash_map>
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/diagnose.h"
50 #include "rtl/bootstrap.hxx"
51 #include "rtl/string.h"
52 #include "rtl/textenc.h"
53 #include "rtl/ustrbuf.hxx"
54 #include "rtl/ustring.h"
55 #include "rtl/ustring.hxx"
56 #include "sal/types.h"
57 #include "tools/stream.hxx"
58 #include "tools/urlobj.hxx"
59 #include "vcl/bitmapex.hxx"
60 #include "vcl/impimagetree.hxx"
61 #include "vcl/pngread.hxx"
62 #include "vcl/settings.hxx"
63 #include "vcl/svapp.hxx"
65 namespace {
67 namespace css = com::sun::star;
69 rtl::OUString createPath(
70 rtl::OUString const & name, sal_Int32 pos, rtl::OUString const & locale)
72 rtl::OUStringBuffer b(name.copy(0, pos + 1));
73 b.append(locale);
74 b.append(name.copy(pos));
75 return b.makeStringAndClear();
78 std::auto_ptr< SvStream > wrapStream(
79 css::uno::Reference< css::io::XInputStream > const & stream)
81 // This could use SvInputStream instead if that did not have a broken
82 // SeekPos implementation for an XInputStream that is not also XSeekable
83 // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
84 // l. 593):
85 OSL_ASSERT(stream.is());
86 std::auto_ptr< SvStream > s(new SvMemoryStream);
87 for (;;) {
88 css::uno::Sequence< sal_Int8 > data;
89 sal_Int32 const size = 30000;
90 sal_Int32 n = stream->readBytes(data, size);
91 s->Write(data.getConstArray(), n);
92 if (n < size) {
93 break;
96 s->Seek(0);
97 return s;
100 void loadFromStream(
101 css::uno::Reference< css::io::XInputStream > const & stream,
102 rtl::OUString const & path, BitmapEx & bitmap)
104 std::auto_ptr< SvStream > s(wrapStream(stream));
105 if (path.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".png")))
107 vcl::PNGReader aPNGReader( *s );
108 aPNGReader.SetIgnoreGammaChunk( sal_True );
109 bitmap = aPNGReader.Read();
110 } else {
111 *s >> bitmap;
117 ImplImageTree::ImplImageTree()
119 m_datadir = ::rtl::OUString::createFromAscii ( "/usr/share/" );
120 #ifdef X86_64
121 m_libdir = ::rtl::OUString::createFromAscii ( "/usr/lib64/" );
122 #else
123 m_libdir = ::rtl::OUString::createFromAscii ( "/usr/lib/" );
124 #endif
127 ImplImageTree::~ImplImageTree() {}
129 bool ImplImageTree::loadImage(
130 rtl::OUString const & name, rtl::OUString const & style, BitmapEx & bitmap,
131 bool localized)
133 setStyle(style);
134 if (cacheLookup(name, localized, bitmap)) {
135 return true;
137 if (!bitmap.IsEmpty()) {
138 bitmap.SetEmpty();
140 std::vector< rtl::OUString > paths;
141 paths.push_back(name);
142 if (localized) {
143 sal_Int32 pos = name.lastIndexOf('/');
144 if (pos != -1) {
145 css::lang::Locale const & loc =
146 Application::GetSettings().GetUILocale();
147 paths.push_back(createPath(name, pos, loc.Language));
148 if (loc.Country.getLength() != 0) {
149 rtl::OUStringBuffer b(loc.Language);
150 b.append(sal_Unicode('-'));
151 b.append(loc.Country);
152 rtl::OUString p(createPath(name, pos, b.makeStringAndClear()));
153 paths.push_back(p);
154 if (loc.Variant.getLength() != 0) {
155 b.append(p);
156 b.append(sal_Unicode('-'));
157 b.append(loc.Variant);
158 paths.push_back(
159 createPath(name, pos, b.makeStringAndClear()));
164 bool found = false;
165 try {
166 found = find(paths, bitmap);
167 } catch (css::uno::RuntimeException &) {
168 throw;
169 } catch (css::uno::Exception & e) {
170 OSL_TRACE(
171 "ImplImageTree::loadImage exception \"%s\"",
172 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
174 if (found) {
175 m_cache[name.intern()] = std::make_pair(localized, bitmap);
177 return found;
180 void ImplImageTree::shutDown() {
181 m_style = rtl::OUString();
182 // for safety; empty m_style means "not initialized"
183 m_zips.clear();
184 m_cache.clear();
187 void ImplImageTree::setStyle(rtl::OUString const & style) {
188 OSL_ASSERT(style.getLength() != 0); // empty m_style means "not initialized"
189 if (style != m_style) {
190 m_style = style;
191 resetZips();
192 m_cache.clear();
196 void ImplImageTree::addUrlToZips(const rtl::OUString &url) {
197 if ( url.getLength() == 0 )
198 return;
199 m_zips.push_back(
200 std::make_pair(
201 url,
202 css::uno::Reference< css::container::XNameAccess >()));
203 sal_Int32 nLibDirPos = url.indexOf( m_libdir );
204 if ( nLibDirPos >= 0 ) {
205 m_zips.push_back(
206 std::make_pair(
207 url.replaceAt( nLibDirPos, m_libdir.getLength(), m_datadir ),
208 css::uno::Reference< css::container::XNameAccess >()));
212 void ImplImageTree::resetZips() {
213 m_zips.clear();
215 rtl::OUString url(
216 RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/edition/images.zip"));
217 rtl::Bootstrap::expandMacros(url);
218 INetURLObject u(url);
219 OSL_ASSERT(!u.HasError());
220 m_zips.push_back(
221 std::make_pair(
222 u.GetMainURL(INetURLObject::NO_DECODE),
223 css::uno::Reference< css::container::XNameAccess >()));
226 rtl::OUString url(
227 RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/share/config"));
228 rtl::Bootstrap::expandMacros(url);
229 INetURLObject u(url);
230 OSL_ASSERT(!u.HasError());
231 rtl::OUStringBuffer b;
232 b.appendAscii(RTL_CONSTASCII_STRINGPARAM("images_"));
233 b.append(m_style);
234 b.appendAscii(RTL_CONSTASCII_STRINGPARAM("_brand.zip"));
235 bool ok = u.Append(b.makeStringAndClear(), INetURLObject::ENCODE_ALL);
236 OSL_ASSERT(ok); (void) ok;
237 addUrlToZips(u.GetMainURL(INetURLObject::NO_DECODE));
240 rtl::OUString url(
241 RTL_CONSTASCII_USTRINGPARAM(
242 "$BRAND_BASE_DIR/share/config/images_brand.zip"));
243 rtl::Bootstrap::expandMacros(url);
244 addUrlToZips(url);
247 rtl::OUString url(
248 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/config"));
249 rtl::Bootstrap::expandMacros(url);
250 INetURLObject u(url);
251 OSL_ASSERT(!u.HasError());
252 rtl::OUStringBuffer b;
253 b.appendAscii(RTL_CONSTASCII_STRINGPARAM("images_"));
254 b.append(m_style);
255 b.appendAscii(RTL_CONSTASCII_STRINGPARAM(".zip"));
256 bool ok = u.Append(b.makeStringAndClear(), INetURLObject::ENCODE_ALL);
257 OSL_ASSERT(ok); (void) ok;
258 addUrlToZips(u.GetMainURL(INetURLObject::NO_DECODE));
261 rtl::OUString url(
262 RTL_CONSTASCII_USTRINGPARAM(
263 "$OOO_BASE_DIR/share/config/images.zip"));
264 rtl::Bootstrap::expandMacros(url);
265 addUrlToZips(url);
269 bool ImplImageTree::cacheLookup(
270 rtl::OUString const & name, bool localized, BitmapEx & bitmap)
272 Cache::iterator i(m_cache.find(name));
273 if (i != m_cache.end() && i->second.first == localized) {
274 bitmap = i->second.second;
275 return true;
276 } else {
277 return false;
281 bool ImplImageTree::find(
282 std::vector< rtl::OUString > const & paths, BitmapEx & bitmap)
284 for (Zips::iterator i(m_zips.begin()); i != m_zips.end();) {
285 if (!i->second.is()) {
286 css::uno::Sequence< css::uno::Any > args(1);
287 args[0] <<= i->first;
288 try {
289 i->second.set(
290 comphelper::createProcessComponentWithArguments(
291 rtl::OUString(
292 RTL_CONSTASCII_USTRINGPARAM(
293 "com.sun.star.packages.zip.ZipFileAccess")),
294 args),
295 css::uno::UNO_QUERY_THROW);
296 } catch (css::uno::RuntimeException &) {
297 throw;
298 } catch (css::uno::Exception & e) {
299 OSL_TRACE(
300 "ImplImageTree::find exception \"%s\"",
301 rtl::OUStringToOString(
302 e.Message, RTL_TEXTENCODING_UTF8).getStr());
303 i = m_zips.erase(i);
304 continue;
307 for (std::vector< rtl::OUString >::const_reverse_iterator j(
308 paths.rbegin());
309 j != paths.rend(); ++j)
311 if (i->second->hasByName(*j)) {
312 css::uno::Reference< css::io::XInputStream > s;
313 bool ok = i->second->getByName(*j) >>= s;
314 OSL_ASSERT(ok); (void) ok;
315 loadFromStream(s, *j, bitmap);
316 return true;
319 ++i;
321 return false;