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