1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <set>
21 
22 #include <com/sun/star/animations/XTransitionFilter.hpp>
23 #include <com/sun/star/container/XEnumerationAccess.hpp>
24 #include <com/sun/star/container/XNameAccess.hpp>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <com/sun/star/animations/AnimationNodeType.hpp>
28 #include <com/sun/star/animations/TransitionType.hpp>
29 #include <com/sun/star/animations/TransitionSubType.hpp>
30 #include <unotools/configmgr.hxx>
31 #include <comphelper/getexpandeduri.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/propertysequence.hxx>
34 #include <comphelper/lok.hxx>
35 #include <unotools/syslocaleoptions.hxx>
36 #include <officecfg/Office/UI/Effects.hxx>
37 
38 #include <sal/log.hxx>
39 #include <osl/diagnose.h>
40 #include <vcl/svapp.hxx>
41 
42 #include <CustomAnimationPreset.hxx>
43 #include <TransitionPreset.hxx>
44 
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::animations;
47 
48 using ::com::sun::star::uno::UNO_QUERY_THROW;
49 using ::com::sun::star::uno::Any;
50 using ::com::sun::star::uno::Sequence;
51 using ::com::sun::star::uno::Reference;
52 using ::com::sun::star::uno::Exception;
53 using ::com::sun::star::lang::XMultiServiceFactory;
54 using ::com::sun::star::container::XEnumerationAccess;
55 using ::com::sun::star::container::XEnumeration;
56 using ::com::sun::star::beans::NamedValue;
57 
58 namespace sd {
59 
TransitionPreset(const css::uno::Reference<css::animations::XAnimationNode> & xNode)60 TransitionPreset::TransitionPreset( const css::uno::Reference< css::animations::XAnimationNode >& xNode )
61 {
62     // first locate preset id
63     Sequence< NamedValue > aUserData( xNode->getUserData() );
64     const NamedValue* pProp = std::find_if(aUserData.begin(), aUserData.end(),
65         [](const NamedValue& rProp) { return rProp.Name == "preset-id"; });
66     if (pProp != aUserData.end())
67         pProp->Value >>= maPresetId;
68 
69     // second, locate transition filter element
70     Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW );
71     Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW );
72     Reference< XTransitionFilter > xTransition( xEnumeration->nextElement(), UNO_QUERY_THROW );
73 
74     mnTransition = xTransition->getTransition();
75     mnSubtype = xTransition->getSubtype();
76     mbDirection = xTransition->getDirection();
77     mnFadeColor = xTransition->getFadeColor();
78 }
79 
importTransitionsFile(TransitionPresetList & rList,Reference<XMultiServiceFactory> const & xServiceFactory,const OUString & aURL)80 bool TransitionPreset::importTransitionsFile( TransitionPresetList& rList,
81                                               Reference< XMultiServiceFactory > const & xServiceFactory,
82                                               const OUString& aURL )
83 {
84     SAL_INFO("sd.transitions", "Importing " << aURL);
85 
86     Reference< container::XNameAccess > xTransitionSets( officecfg::Office::UI::Effects::UserInterface::TransitionSets::get() );
87     Reference< container::XNameAccess > xTransitionGroups( officecfg::Office::UI::Effects::UserInterface::TransitionGroups::get() );
88     Reference< container::XNameAccess > xTransitionVariants( officecfg::Office::UI::Effects::UserInterface::TransitionVariants::get() );
89     Reference< container::XNameAccess > xTransitions( officecfg::Office::UI::Effects::UserInterface::Transitions::get() );
90 
91     // import transition presets
92     Reference< XAnimationNode > xAnimationNode;
93 
94     const std::set<sal_Int16> LOKSupportedTransitionTypes = {
95             TransitionType::BARWIPE,
96             TransitionType::BOXWIPE,
97             TransitionType::FOURBOXWIPE,
98             TransitionType::ELLIPSEWIPE,
99             TransitionType::CLOCKWIPE,
100             TransitionType::PINWHEELWIPE,
101             TransitionType::PUSHWIPE,
102             TransitionType::SLIDEWIPE,
103             TransitionType::FADE,
104             TransitionType::RANDOMBARWIPE,
105             TransitionType::CHECKERBOARDWIPE,
106             TransitionType::DISSOLVE,
107             TransitionType::SNAKEWIPE,
108             TransitionType::PARALLELSNAKESWIPE,
109             TransitionType::IRISWIPE,
110             TransitionType::BARNDOORWIPE,
111             TransitionType::VEEWIPE,
112             TransitionType::ZIGZAGWIPE,
113             TransitionType::BARNZIGZAGWIPE,
114             TransitionType::FANWIPE,
115             TransitionType::SINGLESWEEPWIPE,
116             TransitionType::WATERFALLWIPE,
117             TransitionType::SPIRALWIPE,
118             TransitionType::MISCDIAGONALWIPE,
119             TransitionType::BOXSNAKESWIPE
120     };
121 
122     const std::set<sal_Int16> LOKSupportedTransitionSubTypes = {
123             TransitionSubType::DEFAULT,
124             TransitionSubType::LEFTTORIGHT,
125             TransitionSubType::TOPTOBOTTOM,
126             TransitionSubType::CORNERSIN,
127             TransitionSubType::CORNERSOUT,
128             TransitionSubType::VERTICAL,
129             TransitionSubType::HORIZONTAL,
130             TransitionSubType::DOWN,
131             TransitionSubType::CIRCLE,
132             TransitionSubType::CLOCKWISETWELVE,
133             TransitionSubType::CLOCKWISETHREE,
134             TransitionSubType::CLOCKWISESIX,
135             TransitionSubType::CLOCKWISENINE,
136             TransitionSubType::TWOBLADEVERTICAL,
137             TransitionSubType::TWOBLADEHORIZONTAL,
138             TransitionSubType::FOURBLADE,
139             TransitionSubType::FROMLEFT,
140             TransitionSubType::FROMTOP,
141             TransitionSubType::FROMRIGHT,
142             TransitionSubType::FROMBOTTOM,
143             TransitionSubType::CROSSFADE,
144             TransitionSubType::FADETOCOLOR,
145             TransitionSubType::FADEFROMCOLOR,
146             TransitionSubType::FADEOVERCOLOR,
147             TransitionSubType::THREEBLADE,
148             TransitionSubType::EIGHTBLADE,
149             TransitionSubType::ONEBLADE,
150             TransitionSubType::ACROSS,
151             TransitionSubType::TOPLEFTVERTICAL,
152             TransitionSubType::TOPLEFTHORIZONTAL,
153             TransitionSubType::TOPLEFTDIAGONAL,
154             TransitionSubType::TOPRIGHTDIAGONAL,
155             TransitionSubType::BOTTOMRIGHTDIAGONAL,
156             TransitionSubType::BOTTOMLEFTDIAGONAL,
157             TransitionSubType::RECTANGLE,
158             TransitionSubType::DIAMOND,
159             TransitionSubType::TOPLEFT,
160             TransitionSubType::TOPRIGHT,
161             TransitionSubType::BOTTOMRIGHT,
162             TransitionSubType::BOTTOMLEFT,
163             TransitionSubType::TOPCENTER,
164             TransitionSubType::RIGHTCENTER,
165             TransitionSubType::BOTTOMCENTER,
166             TransitionSubType::LEFTCENTER,
167             TransitionSubType::LEFT,
168             TransitionSubType::UP,
169             TransitionSubType::RIGHT,
170             TransitionSubType::DIAGONALBOTTOMLEFT,
171             TransitionSubType::DIAGONALTOPLEFT,
172             TransitionSubType::CENTERTOP,
173             TransitionSubType::CENTERRIGHT,
174             TransitionSubType::TOP,
175             TransitionSubType::BOTTOM,
176             TransitionSubType::CLOCKWISETOP,
177             TransitionSubType::CLOCKWISERIGHT,
178             TransitionSubType::CLOCKWISEBOTTOM,
179             TransitionSubType::CLOCKWISELEFT,
180             TransitionSubType::CLOCKWISETOPLEFT,
181             TransitionSubType::COUNTERCLOCKWISEBOTTOMLEFT,
182             TransitionSubType::CLOCKWISEBOTTOMRIGHT,
183             TransitionSubType::COUNTERCLOCKWISETOPRIGHT,
184             TransitionSubType::VERTICALLEFT,
185             TransitionSubType::VERTICALRIGHT,
186             TransitionSubType::HORIZONTALLEFT,
187             TransitionSubType::HORIZONTALRIGHT,
188             TransitionSubType::TOPLEFTCLOCKWISE,
189             TransitionSubType::TOPRIGHTCLOCKWISE,
190             TransitionSubType::BOTTOMRIGHTCLOCKWISE,
191             TransitionSubType::BOTTOMLEFTCLOCKWISE,
192             TransitionSubType::TOPLEFTCOUNTERCLOCKWISE,
193             TransitionSubType::TOPRIGHTCOUNTERCLOCKWISE,
194             TransitionSubType::BOTTOMRIGHTCOUNTERCLOCKWISE,
195             TransitionSubType::BOTTOMLEFTCOUNTERCLOCKWISE,
196             TransitionSubType::DOUBLEBARNDOOR,
197             TransitionSubType::DOUBLEDIAMOND,
198             TransitionSubType::VERTICALTOPSAME,
199             TransitionSubType::VERTICALBOTTOMSAME,
200             TransitionSubType::VERTICALTOPLEFTOPPOSITE,
201             TransitionSubType::VERTICALBOTTOMLEFTOPPOSITE,
202             TransitionSubType::HORIZONTALLEFTSAME,
203             TransitionSubType::HORIZONTALRIGHTSAME,
204             TransitionSubType::HORIZONTALTOPLEFTOPPOSITE,
205             TransitionSubType::HORIZONTALTOPRIGHTOPPOSITE,
206             TransitionSubType::DIAGONALBOTTOMLEFTOPPOSITE,
207             TransitionSubType::DIAGONALTOPLEFTOPPOSITE,
208             TransitionSubType::TWOBOXTOP,
209             TransitionSubType::TWOBOXBOTTOM,
210             TransitionSubType::TWOBOXLEFT,
211             TransitionSubType::TWOBOXRIGHT,
212             TransitionSubType::FOURBOXVERTICAL,
213             TransitionSubType::FOURBOXHORIZONTAL
214     };
215 
216     try {
217         xAnimationNode = implImportEffects( xServiceFactory, aURL );
218         Reference< XEnumerationAccess > xEnumerationAccess( xAnimationNode, UNO_QUERY_THROW );
219         Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW );
220 
221         while( xEnumeration->hasMoreElements() )
222         {
223             Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
224             if( xChildNode->getType() == AnimationNodeType::PAR )
225             {
226                 TransitionPresetPtr pPreset( new TransitionPreset( xChildNode ) );
227 
228                 if( comphelper::LibreOfficeKit::isActive() )
229                 {
230                     sal_Int16 eTransitionType = pPreset->getTransition();
231                     sal_Int16 eTransitionSubType = pPreset->getSubtype();
232                     if( LOKSupportedTransitionTypes.find(eTransitionType) == LOKSupportedTransitionTypes.end()
233                             || LOKSupportedTransitionSubTypes.find(eTransitionSubType) == LOKSupportedTransitionSubTypes.end() )
234                     {
235                         continue;
236                     }
237                 }
238 
239                 OUString aPresetId( pPreset->getPresetId() );
240 
241                 if( !aPresetId.isEmpty() )
242                 {
243                     Reference< container::XNameAccess > xTransitionNode;
244 
245                     if (xTransitions->hasByName( aPresetId ) &&
246                         (xTransitions->getByName( aPresetId ) >>= xTransitionNode) &&
247                         xTransitionNode.is() )
248                     {
249                         OUString sSet;
250                         OUString sVariant;
251 
252                         xTransitionNode->getByName( "Set" ) >>= sSet;
253                         xTransitionNode->getByName( "Variant" ) >>= sVariant;
254 
255                         Reference< container::XNameAccess > xSetNode;
256 
257                         xTransitionSets->getByName( sSet ) >>= xSetNode;
258                         if( xSetNode.is() )
259                         {
260                             pPreset->maSetId = sSet;
261                             xSetNode->getByName( "Label" ) >>= sSet;
262                             pPreset->maSetLabel = sSet;
263 
264                             OUString sGroup;
265 
266                             xSetNode->getByName( "Group" ) >>= sGroup;
267 
268                             Reference< container::XNameAccess > xGroupNode;
269                             xTransitionGroups->getByName( sGroup ) >>= xGroupNode;
270 
271                             if( xGroupNode.is() )
272                             {
273                                 xGroupNode->getByName( "Label" ) >>= sGroup;
274                                 if( !sVariant.isEmpty() )
275                                 {
276                                     Reference< container::XNameAccess > xVariantNode;
277                                     xTransitionVariants->getByName( sVariant ) >>= xVariantNode;
278                                     if( xVariantNode.is() )
279                                     {
280                                         xVariantNode->getByName( "Label" ) >>= sVariant;
281                                         pPreset->maVariantLabel = sVariant;
282                                     }
283                                 }
284 
285                                 pPreset->maSetLabel = sSet;
286                                 SAL_INFO("sd.transitions", aPresetId << ": " << sGroup << "/" << sSet << (sVariant.isEmpty() ? OUString() : OUString("/" + sVariant)));
287 
288                                 rList.push_back( pPreset );
289                             }
290                             else
291                                 SAL_WARN("sd.transitions", "group node " << sGroup << " not found");
292                         }
293                         else
294                             SAL_WARN("sd.transitions", "set node " << sSet << " not found");
295                     }
296                     else
297                         SAL_WARN("sd.transitions", "transition node " << aPresetId << " not found");
298                 }
299             }
300             else
301             {
302                 SAL_WARN("sd.transitions", " malformed xml configuration file " << aURL );
303                 break;
304             }
305         }
306     } catch( Exception& ) {
307         return false;
308     }
309 
310     return true;
311 }
312 
importTransitionPresetList(TransitionPresetList & rList)313 bool TransitionPreset::importTransitionPresetList( TransitionPresetList& rList )
314 {
315     if (utl::ConfigManager::IsFuzzing())
316         return false;
317 
318     bool bRet = false;
319 
320     try
321     {
322         uno::Reference< uno::XComponentContext > xContext(
323             comphelper::getProcessComponentContext() );
324         Reference< XMultiServiceFactory > xServiceFactory(
325             xContext->getServiceManager(), UNO_QUERY_THROW );
326 
327         // import ui strings
328         Reference< XMultiServiceFactory > xConfigProvider =
329             configuration::theDefaultProvider::get( xContext );
330 
331         // read path to transition effects files from config
332         uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
333         {
334             {"nodepath", uno::Any(OUString("/org.openoffice.Office.Impress/Misc"))}
335         }));
336         Reference<container::XNameAccess> xNameAccess(
337             xConfigProvider->createInstanceWithArguments(
338                 "com.sun.star.configuration.ConfigurationAccess",
339                 aArgs),
340                 UNO_QUERY_THROW );
341         uno::Sequence< OUString > aFiles;
342         xNameAccess->getByName("TransitionFiles") >>= aFiles;
343 
344         for( const auto& rFile : std::as_const(aFiles) )
345         {
346             OUString aURL = comphelper::getExpandedUri(xContext, rFile);
347 
348             bRet |= importTransitionsFile( rList,
349                                            xServiceFactory,
350                                            aURL );
351         }
352 
353         return bRet;
354     }
355     catch( Exception& )
356     {
357         OSL_FAIL( "sd::TransitionPreset::importResources(), exception caught!" );
358     }
359 
360     return bRet;
361 }
362 
363 std::map<OUString, TransitionPresetList> sd::TransitionPreset::mPresetsMap;
364 
getTransitionPresetList()365 const TransitionPresetList& TransitionPreset::getTransitionPresetList()
366 {
367     // Support localization per-view. Currently not useful for Desktop
368     // but very much critical for LOK. The cache now is per-language.
369     const OUString aLang = comphelper::LibreOfficeKit::isActive()
370                                ? comphelper::LibreOfficeKit::getLanguageTag().getLanguage()
371                                : SvtSysLocaleOptions().GetLanguageTag().getLanguage();
372 
373     SolarMutexGuard aGuard;
374     const auto it = mPresetsMap.find(aLang);
375     if (it != mPresetsMap.end())
376         return it->second;
377 
378     TransitionPresetList& rList = mPresetsMap[aLang];
379     sd::TransitionPreset::importTransitionPresetList(rList);
380     return rList;
381 }
382 
383 }
384 
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
386