1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_canvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <osl/mutex.hxx>
32*cdf0e10cSrcweir #include <osl/process.h>
33*cdf0e10cSrcweir #include <cppuhelper/implementationentry.hxx>
34*cdf0e10cSrcweir #include <cppuhelper/factory.hxx>
35*cdf0e10cSrcweir #include <cppuhelper/implbase3.hxx>
36*cdf0e10cSrcweir #include <vcl/configsettings.hxx>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <com/sun/star/uno/XComponentContext.hpp>
39*cdf0e10cSrcweir #include <com/sun/star/lang/XServiceInfo.hpp>
40*cdf0e10cSrcweir #include <com/sun/star/lang/XSingleComponentFactory.hpp>
41*cdf0e10cSrcweir #include <com/sun/star/container/XContentEnumerationAccess.hpp>
42*cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp>
43*cdf0e10cSrcweir #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
44*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp>
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir #include <boost/bind.hpp>
47*cdf0e10cSrcweir #include <vector>
48*cdf0e10cSrcweir #include <utility>
49*cdf0e10cSrcweir #include <functional>
50*cdf0e10cSrcweir #include <algorithm>
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
53*cdf0e10cSrcweir #define ARLEN(x) (sizeof (x) / sizeof *(x))
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir using namespace ::com::sun::star;
57*cdf0e10cSrcweir using namespace ::com::sun::star::uno;
58*cdf0e10cSrcweir using ::rtl::OUString;
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir namespace
61*cdf0e10cSrcweir {
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir OUString SAL_CALL getImplName()
64*cdf0e10cSrcweir {
65*cdf0e10cSrcweir     return OUSTR("com.sun.star.comp.rendering.CanvasFactory");
66*cdf0e10cSrcweir }
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir Sequence<OUString> SAL_CALL getSuppServices()
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir     OUString name = OUSTR("com.sun.star.rendering.CanvasFactory");
71*cdf0e10cSrcweir     return Sequence<OUString>(&name, 1);
72*cdf0e10cSrcweir }
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir //==============================================================================
75*cdf0e10cSrcweir class CanvasFactory
76*cdf0e10cSrcweir     : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
77*cdf0e10cSrcweir                                       lang::XMultiComponentFactory,
78*cdf0e10cSrcweir                                       lang::XMultiServiceFactory >
79*cdf0e10cSrcweir {
80*cdf0e10cSrcweir     typedef std::pair<OUString,Sequence<OUString> > AvailPair;
81*cdf0e10cSrcweir     typedef std::pair<OUString,OUString>            CachePair;
82*cdf0e10cSrcweir     typedef std::vector< AvailPair >                AvailVector;
83*cdf0e10cSrcweir     typedef std::vector< CachePair >                CacheVector;
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir     mutable ::osl::Mutex              m_mutex;
87*cdf0e10cSrcweir     Reference<XComponentContext>      m_xContext;
88*cdf0e10cSrcweir     Reference<container::XNameAccess> m_xCanvasConfigNameAccess;
89*cdf0e10cSrcweir     AvailVector                       m_aAvailableImplementations;
90*cdf0e10cSrcweir     AvailVector                       m_aAcceleratedImplementations;
91*cdf0e10cSrcweir     AvailVector                       m_aAAImplementations;
92*cdf0e10cSrcweir     mutable CacheVector               m_aCachedImplementations;
93*cdf0e10cSrcweir     mutable bool                      m_bCacheHasForcedLastImpl;
94*cdf0e10cSrcweir     mutable bool                      m_bCacheHasUseAcceleratedEntry;
95*cdf0e10cSrcweir     mutable bool                      m_bCacheHasUseAAEntry;
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir     void checkConfigFlag( bool& r_bFlag,
98*cdf0e10cSrcweir                           bool& r_CacheFlag,
99*cdf0e10cSrcweir                           const OUString& nodeName ) const;
100*cdf0e10cSrcweir     Reference<XInterface> use(
101*cdf0e10cSrcweir         OUString const & serviceName,
102*cdf0e10cSrcweir         Sequence<Any> const & args,
103*cdf0e10cSrcweir         Reference<XComponentContext> const & xContext ) const;
104*cdf0e10cSrcweir     Reference<XInterface> lookupAndUse(
105*cdf0e10cSrcweir         OUString const & serviceName, Sequence<Any> const & args,
106*cdf0e10cSrcweir         Reference<XComponentContext> const & xContext ) const;
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir public:
109*cdf0e10cSrcweir     virtual ~CanvasFactory();
110*cdf0e10cSrcweir     CanvasFactory( Reference<XComponentContext> const & xContext );
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir     // XServiceInfo
113*cdf0e10cSrcweir     virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
114*cdf0e10cSrcweir     virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
115*cdf0e10cSrcweir         throw (RuntimeException);
116*cdf0e10cSrcweir     virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
117*cdf0e10cSrcweir         throw (RuntimeException);
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir     // XMultiComponentFactory
120*cdf0e10cSrcweir     virtual Sequence<OUString> SAL_CALL getAvailableServiceNames()
121*cdf0e10cSrcweir         throw (RuntimeException);
122*cdf0e10cSrcweir     virtual Reference<XInterface> SAL_CALL createInstanceWithContext(
123*cdf0e10cSrcweir         OUString const & name,
124*cdf0e10cSrcweir         Reference<XComponentContext> const & xContext ) throw (Exception);
125*cdf0e10cSrcweir     virtual Reference<XInterface> SAL_CALL
126*cdf0e10cSrcweir     createInstanceWithArgumentsAndContext(
127*cdf0e10cSrcweir         OUString const & name,
128*cdf0e10cSrcweir         Sequence<Any> const & args,
129*cdf0e10cSrcweir         Reference<XComponentContext> const & xContext ) throw (Exception);
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir     // XMultiServiceFactory
132*cdf0e10cSrcweir     virtual Reference<XInterface> SAL_CALL createInstance(
133*cdf0e10cSrcweir         OUString const & name )
134*cdf0e10cSrcweir         throw (Exception);
135*cdf0e10cSrcweir     virtual Reference<XInterface> SAL_CALL createInstanceWithArguments(
136*cdf0e10cSrcweir         OUString const & name, Sequence<Any> const & args )
137*cdf0e10cSrcweir         throw (Exception);
138*cdf0e10cSrcweir };
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir CanvasFactory::CanvasFactory( Reference<XComponentContext> const & xContext ) :
141*cdf0e10cSrcweir     m_mutex(),
142*cdf0e10cSrcweir     m_xContext(xContext),
143*cdf0e10cSrcweir     m_xCanvasConfigNameAccess(),
144*cdf0e10cSrcweir     m_aAvailableImplementations(),
145*cdf0e10cSrcweir     m_aAcceleratedImplementations(),
146*cdf0e10cSrcweir     m_aAAImplementations(),
147*cdf0e10cSrcweir     m_aCachedImplementations(),
148*cdf0e10cSrcweir     m_bCacheHasForcedLastImpl(),
149*cdf0e10cSrcweir     m_bCacheHasUseAcceleratedEntry(),
150*cdf0e10cSrcweir     m_bCacheHasUseAAEntry()
151*cdf0e10cSrcweir {
152*cdf0e10cSrcweir     try
153*cdf0e10cSrcweir     {
154*cdf0e10cSrcweir         // read out configuration for preferred services:
155*cdf0e10cSrcweir         Reference<lang::XMultiServiceFactory> xConfigProvider(
156*cdf0e10cSrcweir             m_xContext->getServiceManager()->createInstanceWithContext(
157*cdf0e10cSrcweir                 OUSTR("com.sun.star.configuration.ConfigurationProvider"),
158*cdf0e10cSrcweir                 m_xContext ), UNO_QUERY_THROW );
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir         Any propValue(
161*cdf0e10cSrcweir             makeAny( beans::PropertyValue(
162*cdf0e10cSrcweir                          OUSTR("nodepath"), -1,
163*cdf0e10cSrcweir                          makeAny( OUSTR("/org.openoffice.Office.Canvas") ),
164*cdf0e10cSrcweir                          beans::PropertyState_DIRECT_VALUE ) ) );
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir         m_xCanvasConfigNameAccess.set(
167*cdf0e10cSrcweir             xConfigProvider->createInstanceWithArguments(
168*cdf0e10cSrcweir                 OUSTR("com.sun.star.configuration.ConfigurationAccess"),
169*cdf0e10cSrcweir                 Sequence<Any>( &propValue, 1 ) ),
170*cdf0e10cSrcweir             UNO_QUERY_THROW );
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir         propValue = makeAny(
173*cdf0e10cSrcweir             beans::PropertyValue(
174*cdf0e10cSrcweir                 OUSTR("nodepath"), -1,
175*cdf0e10cSrcweir                 makeAny( OUSTR("/org.openoffice.Office.Canvas/CanvasServiceList") ),
176*cdf0e10cSrcweir                 beans::PropertyState_DIRECT_VALUE ) );
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir         Reference<container::XNameAccess> xNameAccess(
179*cdf0e10cSrcweir             xConfigProvider->createInstanceWithArguments(
180*cdf0e10cSrcweir                 OUSTR("com.sun.star.configuration.ConfigurationAccess"),
181*cdf0e10cSrcweir                 Sequence<Any>( &propValue, 1 ) ), UNO_QUERY_THROW );
182*cdf0e10cSrcweir         Reference<container::XHierarchicalNameAccess> xHierarchicalNameAccess(
183*cdf0e10cSrcweir             xNameAccess, UNO_QUERY_THROW);
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir         Sequence<OUString> serviceNames = xNameAccess->getElementNames();
186*cdf0e10cSrcweir         const OUString* pCurr = serviceNames.getConstArray();
187*cdf0e10cSrcweir         const OUString* const pEnd = pCurr + serviceNames.getLength();
188*cdf0e10cSrcweir         while( pCurr != pEnd )
189*cdf0e10cSrcweir         {
190*cdf0e10cSrcweir             Reference<container::XNameAccess> xEntryNameAccess(
191*cdf0e10cSrcweir                 xHierarchicalNameAccess->getByHierarchicalName(*pCurr),
192*cdf0e10cSrcweir                 UNO_QUERY );
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir             if( xEntryNameAccess.is() )
195*cdf0e10cSrcweir             {
196*cdf0e10cSrcweir                 Sequence<OUString> implementationList;
197*cdf0e10cSrcweir                 if( (xEntryNameAccess->getByName( OUSTR("PreferredImplementations") ) >>= implementationList) )
198*cdf0e10cSrcweir                     m_aAvailableImplementations.push_back( std::make_pair(*pCurr,implementationList) );
199*cdf0e10cSrcweir                 if( (xEntryNameAccess->getByName( OUSTR("AcceleratedImplementations") ) >>= implementationList) )
200*cdf0e10cSrcweir                     m_aAcceleratedImplementations.push_back( std::make_pair(*pCurr,implementationList) );
201*cdf0e10cSrcweir                 if( (xEntryNameAccess->getByName( OUSTR("AntialiasingImplementations") ) >>= implementationList) )
202*cdf0e10cSrcweir                     m_aAAImplementations.push_back( std::make_pair(*pCurr,implementationList) );
203*cdf0e10cSrcweir             }
204*cdf0e10cSrcweir 
205*cdf0e10cSrcweir             ++pCurr;
206*cdf0e10cSrcweir         }
207*cdf0e10cSrcweir     }
208*cdf0e10cSrcweir     catch (RuntimeException &)
209*cdf0e10cSrcweir     {
210*cdf0e10cSrcweir         throw;
211*cdf0e10cSrcweir     }
212*cdf0e10cSrcweir     catch (Exception&)
213*cdf0e10cSrcweir     {
214*cdf0e10cSrcweir     }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir     if( m_aAvailableImplementations.empty() )
217*cdf0e10cSrcweir     {
218*cdf0e10cSrcweir         // Ugh. Looks like configuration is borked. Fake minimal
219*cdf0e10cSrcweir         // setup.
220*cdf0e10cSrcweir         Sequence<OUString> aServices(1);
221*cdf0e10cSrcweir         aServices[0] = OUSTR("com.sun.star.comp.rendering.Canvas.VCL");
222*cdf0e10cSrcweir         m_aAvailableImplementations.push_back( std::make_pair(OUSTR("com.sun.star.rendering.Canvas"),
223*cdf0e10cSrcweir                                                               aServices) );
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir         aServices[0] = OUSTR("com.sun.star.comp.rendering.SpriteCanvas.VCL");
226*cdf0e10cSrcweir         m_aAvailableImplementations.push_back( std::make_pair(OUSTR("com.sun.star.rendering.SpriteCanvas"),
227*cdf0e10cSrcweir                                                               aServices) );
228*cdf0e10cSrcweir     }
229*cdf0e10cSrcweir }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir CanvasFactory::~CanvasFactory()
232*cdf0e10cSrcweir {
233*cdf0e10cSrcweir }
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir //------------------------------------------------------------------------------
236*cdf0e10cSrcweir Reference<XInterface> create( Reference<XComponentContext> const & xContext )
237*cdf0e10cSrcweir {
238*cdf0e10cSrcweir     return static_cast< ::cppu::OWeakObject * >(
239*cdf0e10cSrcweir         new CanvasFactory( xContext ) );
240*cdf0e10cSrcweir }
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir // XServiceInfo
243*cdf0e10cSrcweir //______________________________________________________________________________
244*cdf0e10cSrcweir OUString CanvasFactory::getImplementationName() throw (RuntimeException)
245*cdf0e10cSrcweir {
246*cdf0e10cSrcweir     return getImplName();
247*cdf0e10cSrcweir }
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir //______________________________________________________________________________
250*cdf0e10cSrcweir sal_Bool CanvasFactory::supportsService( OUString const & serviceName )
251*cdf0e10cSrcweir     throw (RuntimeException)
252*cdf0e10cSrcweir {
253*cdf0e10cSrcweir     return serviceName.equals(getSuppServices()[0]);
254*cdf0e10cSrcweir }
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir //______________________________________________________________________________
257*cdf0e10cSrcweir Sequence<OUString> CanvasFactory::getSupportedServiceNames()
258*cdf0e10cSrcweir     throw (RuntimeException)
259*cdf0e10cSrcweir {
260*cdf0e10cSrcweir     return getSuppServices();
261*cdf0e10cSrcweir }
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir // XMultiComponentFactory
264*cdf0e10cSrcweir //______________________________________________________________________________
265*cdf0e10cSrcweir Sequence<OUString> CanvasFactory::getAvailableServiceNames()
266*cdf0e10cSrcweir     throw (RuntimeException)
267*cdf0e10cSrcweir {
268*cdf0e10cSrcweir     Sequence<OUString> aServiceNames(m_aAvailableImplementations.size());
269*cdf0e10cSrcweir     std::transform(m_aAvailableImplementations.begin(),
270*cdf0e10cSrcweir                    m_aAvailableImplementations.end(),
271*cdf0e10cSrcweir                    aServiceNames.getArray(),
272*cdf0e10cSrcweir                    std::select1st<AvailPair>());
273*cdf0e10cSrcweir     return aServiceNames;
274*cdf0e10cSrcweir }
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir //______________________________________________________________________________
277*cdf0e10cSrcweir Reference<XInterface> CanvasFactory::createInstanceWithContext(
278*cdf0e10cSrcweir     OUString const & name, Reference<XComponentContext> const & xContext )
279*cdf0e10cSrcweir     throw (Exception)
280*cdf0e10cSrcweir {
281*cdf0e10cSrcweir     return createInstanceWithArgumentsAndContext(
282*cdf0e10cSrcweir         name, Sequence<Any>(), xContext );
283*cdf0e10cSrcweir }
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir //______________________________________________________________________________
286*cdf0e10cSrcweir Reference<XInterface> CanvasFactory::use(
287*cdf0e10cSrcweir     OUString const & serviceName,
288*cdf0e10cSrcweir     Sequence<Any> const & args,
289*cdf0e10cSrcweir     Reference<XComponentContext> const & xContext ) const
290*cdf0e10cSrcweir {
291*cdf0e10cSrcweir     try {
292*cdf0e10cSrcweir         return m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
293*cdf0e10cSrcweir             serviceName, args, xContext);
294*cdf0e10cSrcweir     }
295*cdf0e10cSrcweir     catch (RuntimeException &)
296*cdf0e10cSrcweir     {
297*cdf0e10cSrcweir         throw;
298*cdf0e10cSrcweir     }
299*cdf0e10cSrcweir     catch (Exception &)
300*cdf0e10cSrcweir     {
301*cdf0e10cSrcweir         return Reference<XInterface>();
302*cdf0e10cSrcweir     }
303*cdf0e10cSrcweir }
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir //______________________________________________________________________________
306*cdf0e10cSrcweir void CanvasFactory::checkConfigFlag( bool& r_bFlag,
307*cdf0e10cSrcweir                                      bool& r_CacheFlag,
308*cdf0e10cSrcweir                                      const OUString& nodeName ) const
309*cdf0e10cSrcweir {
310*cdf0e10cSrcweir     if( m_xCanvasConfigNameAccess.is() )
311*cdf0e10cSrcweir     {
312*cdf0e10cSrcweir         m_xCanvasConfigNameAccess->getByName( nodeName ) >>= r_bFlag;
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir         if( r_CacheFlag != r_bFlag )
315*cdf0e10cSrcweir         {
316*cdf0e10cSrcweir             // cache is invalid, because of different order of
317*cdf0e10cSrcweir             // elements
318*cdf0e10cSrcweir             r_CacheFlag = r_bFlag;
319*cdf0e10cSrcweir             m_aCachedImplementations.clear();
320*cdf0e10cSrcweir         }
321*cdf0e10cSrcweir     }
322*cdf0e10cSrcweir }
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir //______________________________________________________________________________
325*cdf0e10cSrcweir Reference<XInterface> CanvasFactory::lookupAndUse(
326*cdf0e10cSrcweir     OUString const & serviceName, Sequence<Any> const & args,
327*cdf0e10cSrcweir     Reference<XComponentContext> const & xContext ) const
328*cdf0e10cSrcweir {
329*cdf0e10cSrcweir     ::osl::MutexGuard guard(m_mutex);
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir     // forcing last entry from impl list, if config flag set
332*cdf0e10cSrcweir     bool bForceLastEntry(false);
333*cdf0e10cSrcweir     checkConfigFlag( bForceLastEntry,
334*cdf0e10cSrcweir                      m_bCacheHasForcedLastImpl,
335*cdf0e10cSrcweir                      OUSTR("ForceSafeServiceImpl") );
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir     // use anti-aliasing canvas, if config flag set (or not existing)
338*cdf0e10cSrcweir     bool bUseAAEntry(true);
339*cdf0e10cSrcweir     checkConfigFlag( bUseAAEntry,
340*cdf0e10cSrcweir                      m_bCacheHasUseAAEntry,
341*cdf0e10cSrcweir                      OUSTR("UseAntialiasingCanvas") );
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir     // use accelerated canvas, if config flag set (or not existing)
344*cdf0e10cSrcweir     bool bUseAcceleratedEntry(true);
345*cdf0e10cSrcweir     checkConfigFlag( bUseAcceleratedEntry,
346*cdf0e10cSrcweir                      m_bCacheHasUseAcceleratedEntry,
347*cdf0e10cSrcweir                      OUSTR("UseAcceleratedCanvas") );
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir     // try to reuse last working implementation for given service name
350*cdf0e10cSrcweir     const CacheVector::iterator aEnd(m_aCachedImplementations.end());
351*cdf0e10cSrcweir     CacheVector::iterator aMatch;
352*cdf0e10cSrcweir     if( (aMatch=std::find_if(m_aCachedImplementations.begin(),
353*cdf0e10cSrcweir                              aEnd,
354*cdf0e10cSrcweir                              boost::bind(&OUString::equals,
355*cdf0e10cSrcweir                                          boost::cref(serviceName),
356*cdf0e10cSrcweir                                          boost::bind(
357*cdf0e10cSrcweir                                              std::select1st<CachePair>(),
358*cdf0e10cSrcweir                                              _1)))) != aEnd )
359*cdf0e10cSrcweir     {
360*cdf0e10cSrcweir         Reference<XInterface> xCanvas( use( aMatch->second, args, xContext ) );
361*cdf0e10cSrcweir         if(xCanvas.is())
362*cdf0e10cSrcweir             return xCanvas;
363*cdf0e10cSrcweir     }
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir     // lookup in available service list
366*cdf0e10cSrcweir     const AvailVector::const_iterator aAvailEnd(m_aAvailableImplementations.end());
367*cdf0e10cSrcweir     AvailVector::const_iterator aAvailImplsMatch;
368*cdf0e10cSrcweir     if( (aAvailImplsMatch=std::find_if(m_aAvailableImplementations.begin(),
369*cdf0e10cSrcweir                                        aAvailEnd,
370*cdf0e10cSrcweir                                        boost::bind(&OUString::equals,
371*cdf0e10cSrcweir                                                    boost::cref(serviceName),
372*cdf0e10cSrcweir                                                    boost::bind(
373*cdf0e10cSrcweir                                                        std::select1st<AvailPair>(),
374*cdf0e10cSrcweir                                                        _1)))) == aAvailEnd )
375*cdf0e10cSrcweir     {
376*cdf0e10cSrcweir         return Reference<XInterface>();
377*cdf0e10cSrcweir     }
378*cdf0e10cSrcweir 
379*cdf0e10cSrcweir     const AvailVector::const_iterator aAAEnd(m_aAAImplementations.end());
380*cdf0e10cSrcweir     AvailVector::const_iterator aAAImplsMatch;
381*cdf0e10cSrcweir     if( (aAAImplsMatch=std::find_if(m_aAAImplementations.begin(),
382*cdf0e10cSrcweir                                     aAAEnd,
383*cdf0e10cSrcweir                                     boost::bind(&OUString::equals,
384*cdf0e10cSrcweir                                                 boost::cref(serviceName),
385*cdf0e10cSrcweir                                                 boost::bind(
386*cdf0e10cSrcweir                                                     std::select1st<AvailPair>(),
387*cdf0e10cSrcweir                                                     _1)))) == aAAEnd )
388*cdf0e10cSrcweir     {
389*cdf0e10cSrcweir         return Reference<XInterface>();
390*cdf0e10cSrcweir     }
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir     const AvailVector::const_iterator aAccelEnd(m_aAcceleratedImplementations.end());
393*cdf0e10cSrcweir     AvailVector::const_iterator aAccelImplsMatch;
394*cdf0e10cSrcweir     if( (aAccelImplsMatch=std::find_if(m_aAcceleratedImplementations.begin(),
395*cdf0e10cSrcweir                                        aAccelEnd,
396*cdf0e10cSrcweir                                        boost::bind(&OUString::equals,
397*cdf0e10cSrcweir                                                    boost::cref(serviceName),
398*cdf0e10cSrcweir                                                    boost::bind(
399*cdf0e10cSrcweir                                                        std::select1st<AvailPair>(),
400*cdf0e10cSrcweir                                                        _1)))) == aAccelEnd )
401*cdf0e10cSrcweir     {
402*cdf0e10cSrcweir         return Reference<XInterface>();
403*cdf0e10cSrcweir     }
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir     const Sequence<OUString> aPreferredImpls( aAvailImplsMatch->second );
406*cdf0e10cSrcweir     const OUString* pCurrImpl = aPreferredImpls.getConstArray();
407*cdf0e10cSrcweir     const OUString* const pEndImpl = pCurrImpl + aPreferredImpls.getLength();
408*cdf0e10cSrcweir 
409*cdf0e10cSrcweir     const Sequence<OUString> aAAImpls( aAAImplsMatch->second );
410*cdf0e10cSrcweir     const OUString* const pFirstAAImpl = aAAImpls.getConstArray();
411*cdf0e10cSrcweir     const OUString* const pEndAAImpl = pFirstAAImpl + aAAImpls.getLength();
412*cdf0e10cSrcweir 
413*cdf0e10cSrcweir     const Sequence<OUString> aAccelImpls( aAccelImplsMatch->second );
414*cdf0e10cSrcweir     const OUString* const pFirstAccelImpl = aAccelImpls.getConstArray();
415*cdf0e10cSrcweir     const OUString* const pEndAccelImpl = pFirstAccelImpl + aAccelImpls.getLength();
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir     // force last entry from impl list, if config flag set
418*cdf0e10cSrcweir     if( bForceLastEntry )
419*cdf0e10cSrcweir         pCurrImpl = pEndImpl-1;
420*cdf0e10cSrcweir 
421*cdf0e10cSrcweir     while( pCurrImpl != pEndImpl )
422*cdf0e10cSrcweir     {
423*cdf0e10cSrcweir         const OUString aCurrName(pCurrImpl->trim());
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir         // check whether given canvas service is listed in the
426*cdf0e10cSrcweir         // sequence of "accelerated canvas implementations"
427*cdf0e10cSrcweir         const bool bIsAcceleratedImpl(
428*cdf0e10cSrcweir             std::find_if(pFirstAccelImpl,
429*cdf0e10cSrcweir                          pEndAccelImpl,
430*cdf0e10cSrcweir                          boost::bind(&OUString::equals,
431*cdf0e10cSrcweir                                      boost::cref(aCurrName),
432*cdf0e10cSrcweir                                      boost::bind(
433*cdf0e10cSrcweir                                          &OUString::trim,
434*cdf0e10cSrcweir                                          _1))) != pEndAccelImpl );
435*cdf0e10cSrcweir 
436*cdf0e10cSrcweir         // check whether given canvas service is listed in the
437*cdf0e10cSrcweir         // sequence of "antialiasing canvas implementations"
438*cdf0e10cSrcweir         const bool bIsAAImpl(
439*cdf0e10cSrcweir             std::find_if(pFirstAAImpl,
440*cdf0e10cSrcweir                          pEndAAImpl,
441*cdf0e10cSrcweir                          boost::bind(&OUString::equals,
442*cdf0e10cSrcweir                                      boost::cref(aCurrName),
443*cdf0e10cSrcweir                                      boost::bind(
444*cdf0e10cSrcweir                                          &OUString::trim,
445*cdf0e10cSrcweir                                          _1))) != pEndAAImpl );
446*cdf0e10cSrcweir 
447*cdf0e10cSrcweir         // try to instantiate canvas *only* if either accel and AA
448*cdf0e10cSrcweir         // property match preference, *or*, if there's a mismatch, only
449*cdf0e10cSrcweir         // go for a less capable canvas (that effectively let those
450*cdf0e10cSrcweir         // pour canvas impls still work as fallbacks, should an
451*cdf0e10cSrcweir         // accelerated/AA one fail). Property implies configuration:
452*cdf0e10cSrcweir         // http://en.wikipedia.org/wiki/Truth_table#Logical_implication
453*cdf0e10cSrcweir         if( (!bIsAAImpl || bUseAAEntry) && (!bIsAcceleratedImpl || bUseAcceleratedEntry) )
454*cdf0e10cSrcweir         {
455*cdf0e10cSrcweir             Reference<XInterface> xCanvas(
456*cdf0e10cSrcweir                 use( pCurrImpl->trim(), args, xContext ) );
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir             if(xCanvas.is())
459*cdf0e10cSrcweir             {
460*cdf0e10cSrcweir                 if( aMatch != aEnd )
461*cdf0e10cSrcweir                 {
462*cdf0e10cSrcweir                     // cache entry exists, replace dysfunctional
463*cdf0e10cSrcweir                     // implementation name
464*cdf0e10cSrcweir                     aMatch->second = pCurrImpl->trim();
465*cdf0e10cSrcweir                 }
466*cdf0e10cSrcweir                 else
467*cdf0e10cSrcweir                 {
468*cdf0e10cSrcweir                     // new service name, add new cache entry
469*cdf0e10cSrcweir                     m_aCachedImplementations.push_back(std::make_pair(serviceName,
470*cdf0e10cSrcweir                                                                       pCurrImpl->trim()));
471*cdf0e10cSrcweir                 }
472*cdf0e10cSrcweir 
473*cdf0e10cSrcweir                 return xCanvas;
474*cdf0e10cSrcweir             }
475*cdf0e10cSrcweir         }
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir         ++pCurrImpl;
478*cdf0e10cSrcweir     }
479*cdf0e10cSrcweir 
480*cdf0e10cSrcweir     return Reference<XInterface>();
481*cdf0e10cSrcweir }
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir //______________________________________________________________________________
484*cdf0e10cSrcweir Reference<XInterface> CanvasFactory::createInstanceWithArgumentsAndContext(
485*cdf0e10cSrcweir     OUString const & preferredOne, Sequence<Any> const & args,
486*cdf0e10cSrcweir     Reference<XComponentContext> const & xContext ) throw (Exception)
487*cdf0e10cSrcweir {
488*cdf0e10cSrcweir     Reference<XInterface> xCanvas(
489*cdf0e10cSrcweir         lookupAndUse( preferredOne, args, xContext ) );
490*cdf0e10cSrcweir     if(xCanvas.is())
491*cdf0e10cSrcweir         return xCanvas;
492*cdf0e10cSrcweir 
493*cdf0e10cSrcweir     // last resort: try service name directly
494*cdf0e10cSrcweir     return use( preferredOne, args, xContext );
495*cdf0e10cSrcweir }
496*cdf0e10cSrcweir 
497*cdf0e10cSrcweir // XMultiServiceFactory
498*cdf0e10cSrcweir //______________________________________________________________________________
499*cdf0e10cSrcweir Reference<XInterface> CanvasFactory::createInstance( OUString const & name )
500*cdf0e10cSrcweir     throw (Exception)
501*cdf0e10cSrcweir {
502*cdf0e10cSrcweir     return createInstanceWithArgumentsAndContext(
503*cdf0e10cSrcweir         name, Sequence<Any>(), m_xContext );
504*cdf0e10cSrcweir }
505*cdf0e10cSrcweir 
506*cdf0e10cSrcweir //______________________________________________________________________________
507*cdf0e10cSrcweir Reference<XInterface> CanvasFactory::createInstanceWithArguments(
508*cdf0e10cSrcweir     OUString const & name, Sequence<Any> const & args ) throw (Exception)
509*cdf0e10cSrcweir {
510*cdf0e10cSrcweir     return createInstanceWithArgumentsAndContext(
511*cdf0e10cSrcweir         name, args, m_xContext );
512*cdf0e10cSrcweir }
513*cdf0e10cSrcweir 
514*cdf0e10cSrcweir const ::cppu::ImplementationEntry s_entries [] = {
515*cdf0e10cSrcweir     {
516*cdf0e10cSrcweir         create,
517*cdf0e10cSrcweir         getImplName,
518*cdf0e10cSrcweir         getSuppServices,
519*cdf0e10cSrcweir         ::cppu::createSingleComponentFactory,
520*cdf0e10cSrcweir         0, 0
521*cdf0e10cSrcweir     },
522*cdf0e10cSrcweir     { 0, 0, 0, 0, 0, 0 }
523*cdf0e10cSrcweir };
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir } // anon namespace
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir extern "C" {
528*cdf0e10cSrcweir 
529*cdf0e10cSrcweir void SAL_CALL component_getImplementationEnvironment(
530*cdf0e10cSrcweir     const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
531*cdf0e10cSrcweir {
532*cdf0e10cSrcweir     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
533*cdf0e10cSrcweir }
534*cdf0e10cSrcweir 
535*cdf0e10cSrcweir void * SAL_CALL component_getFactory(
536*cdf0e10cSrcweir     sal_Char const * pImplName,
537*cdf0e10cSrcweir     lang::XMultiServiceFactory * pServiceManager,
538*cdf0e10cSrcweir     registry::XRegistryKey * pRegistryKey )
539*cdf0e10cSrcweir {
540*cdf0e10cSrcweir     return ::cppu::component_getFactoryHelper(
541*cdf0e10cSrcweir         pImplName, pServiceManager, pRegistryKey, s_entries );
542*cdf0e10cSrcweir }
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir }
545*cdf0e10cSrcweir 
546