/src/libreoffice/xmloff/source/style/impastpl.cxx
Line | Count | Source |
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 <algorithm> |
21 | | |
22 | | #include <rtl/ustrbuf.hxx> |
23 | | #include <sal/log.hxx> |
24 | | #include <PageMasterStyleMap.hxx> |
25 | | #include <utility> |
26 | | #include <xmloff/families.hxx> |
27 | | #include <xmloff/xmlaustp.hxx> |
28 | | #include <xmloff/xmlexp.hxx> |
29 | | #include <xmloff/xmlexppr.hxx> |
30 | | #include <xmloff/xmlnamespace.hxx> |
31 | | #include <xmloff/xmlprmap.hxx> |
32 | | #include <xmloff/xmltoken.hxx> |
33 | | |
34 | | #include "impastpl.hxx" |
35 | | |
36 | | using namespace ::com::sun::star; |
37 | | using namespace ::xmloff::token; |
38 | | |
39 | | // Class XMLAutoStyleFamily |
40 | | // ctor/dtor class XMLAutoStyleFamily |
41 | | |
42 | | XMLAutoStyleFamily::XMLAutoStyleFamily( |
43 | | XmlStyleFamily nFamily, |
44 | | OUString aStrName, |
45 | | rtl::Reference < SvXMLExportPropertyMapper > xMapper, |
46 | | OUString aStrPrefix, |
47 | | bool bAsFamily ) : |
48 | 42 | mnFamily( nFamily ), maStrFamilyName(std::move( aStrName)), mxMapper(std::move( xMapper )), |
49 | 42 | mnCount( 0 ), mnName( 0 ), maStrPrefix(std::move( aStrPrefix )), mbAsFamily( bAsFamily ) |
50 | 42 | {} |
51 | | |
52 | | XMLAutoStyleFamily::XMLAutoStyleFamily( XmlStyleFamily nFamily ) : |
53 | 57 | mnFamily(nFamily), mnCount(0), mnName(0), mbAsFamily(false) {} |
54 | | |
55 | | void XMLAutoStyleFamily::ClearEntries() |
56 | 0 | { |
57 | 0 | m_ParentSet.clear(); |
58 | 0 | } |
59 | | |
60 | | static OUString |
61 | | data2string(void *data, |
62 | | const typelib_TypeDescriptionReference *type); |
63 | | |
64 | | static OUString |
65 | | struct2string(void *data, |
66 | | const typelib_TypeDescription *type) |
67 | 0 | { |
68 | 0 | assert(type->eTypeClass == typelib_TypeClass_STRUCT); |
69 | |
|
70 | 0 | OUStringBuffer result("{"); |
71 | |
|
72 | 0 | const typelib_CompoundTypeDescription *compoundType = |
73 | 0 | &reinterpret_cast<const typelib_StructTypeDescription*>(type)->aBase; |
74 | |
|
75 | 0 | for (int i = 0; i < compoundType->nMembers; i++) |
76 | 0 | { |
77 | 0 | if (i > 0) |
78 | 0 | result.append(":"); |
79 | 0 | result.append( |
80 | 0 | OUString::unacquired(&compoundType->ppMemberNames[i]) |
81 | 0 | + "=" |
82 | 0 | + data2string(static_cast<char *>(data)+compoundType->pMemberOffsets[i], |
83 | 0 | compoundType->ppTypeRefs[i])); |
84 | 0 | } |
85 | |
|
86 | 0 | result.append("}"); |
87 | |
|
88 | 0 | return result.makeStringAndClear(); |
89 | 0 | } |
90 | | |
91 | | static OUString |
92 | | data2string(void *data, |
93 | | const typelib_TypeDescriptionReference *type) |
94 | 0 | { |
95 | 0 | switch (type->eTypeClass) |
96 | 0 | { |
97 | 0 | case typelib_TypeClass_VOID: |
98 | 0 | return u""_ustr; |
99 | 0 | case typelib_TypeClass_BOOLEAN: |
100 | 0 | return *static_cast<const sal_Bool*>(data) ? u"true"_ustr : u"false"_ustr; |
101 | 0 | case typelib_TypeClass_BYTE: |
102 | 0 | return OUString::number(*static_cast<const sal_Int8*>(data)); |
103 | 0 | case typelib_TypeClass_SHORT: |
104 | 0 | return OUString::number(*static_cast<const sal_Int16*>(data)); |
105 | 0 | case typelib_TypeClass_LONG: |
106 | 0 | return OUString::number(*static_cast<const sal_Int32*>(data)); |
107 | 0 | case typelib_TypeClass_HYPER: |
108 | 0 | return OUString::number(*static_cast<const sal_Int64*>(data)); |
109 | 0 | case typelib_TypeClass_UNSIGNED_SHORT: |
110 | 0 | return OUString::number(*static_cast<const sal_uInt16*>(data)); |
111 | 0 | case typelib_TypeClass_UNSIGNED_LONG: |
112 | 0 | return OUString::number((*static_cast<const sal_uInt32*>(data)), 16); |
113 | 0 | case typelib_TypeClass_UNSIGNED_HYPER: |
114 | 0 | return OUString::number((*static_cast<const sal_uInt64*>(data)), 16); |
115 | 0 | case typelib_TypeClass_FLOAT: |
116 | 0 | return OUString::number(*static_cast<const float*>(data)); |
117 | 0 | case typelib_TypeClass_DOUBLE: |
118 | 0 | return OUString::number(*static_cast<const double*>(data)); |
119 | 0 | case typelib_TypeClass_CHAR: |
120 | 0 | return ("U+" + OUString::number(*static_cast<const sal_uInt16*>(data))); |
121 | 0 | case typelib_TypeClass_STRING: |
122 | 0 | return *static_cast<OUString*>(data); |
123 | 0 | case typelib_TypeClass_TYPE: |
124 | 0 | case typelib_TypeClass_SEQUENCE: |
125 | 0 | case typelib_TypeClass_EXCEPTION: |
126 | 0 | case typelib_TypeClass_INTERFACE: |
127 | 0 | return u"wtf"_ustr; |
128 | 0 | case typelib_TypeClass_STRUCT: |
129 | 0 | return struct2string(data, type->pType); |
130 | 0 | case typelib_TypeClass_ENUM: |
131 | 0 | return OUString::number(*static_cast<const sal_Int32*>(data)); |
132 | 0 | default: |
133 | 0 | assert(false); // this cannot happen I hope |
134 | 0 | break; |
135 | 0 | } |
136 | 0 | return u""_ustr; |
137 | 0 | } |
138 | | |
139 | | static OUString any2string(const uno::Any& any) |
140 | 0 | { |
141 | 0 | return data2string(const_cast<void*>(any.getValue()), any.pType); |
142 | 0 | } |
143 | | |
144 | | // Class SvXMLAutoStylePoolProperties_Impl |
145 | | // ctor class SvXMLAutoStylePoolProperties_Impl |
146 | | |
147 | | XMLAutoStylePoolProperties::XMLAutoStylePoolProperties( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString const & rParentName ) |
148 | 9 | : maProperties( std::move(rProperties) ), |
149 | 9 | mnPos ( rFamilyData.mnCount ) |
150 | 9 | { |
151 | 9 | static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr); |
152 | | |
153 | 9 | if (bHack) |
154 | 0 | { |
155 | 0 | OUStringBuffer aStemBuffer(32); |
156 | 0 | aStemBuffer.append( rFamilyData.maStrPrefix ); |
157 | |
|
158 | 0 | if (!rParentName.isEmpty()) |
159 | 0 | { |
160 | 0 | aStemBuffer.append("-" + rParentName); |
161 | 0 | } |
162 | | |
163 | | // Create a name based on the properties used |
164 | 0 | for(XMLPropertyState const & rState : maProperties) |
165 | 0 | { |
166 | 0 | if (rState.mnIndex == -1) |
167 | 0 | continue; |
168 | 0 | OUString sXMLName(rFamilyData.mxMapper->getPropertySetMapper()->GetEntryXMLName(rState.mnIndex)); |
169 | 0 | if (sXMLName.isEmpty()) |
170 | 0 | continue; |
171 | 0 | aStemBuffer.append( |
172 | 0 | "-" |
173 | 0 | + OUString::number(static_cast<sal_Int32>(rFamilyData.mxMapper->getPropertySetMapper()->GetEntryNameSpace(rState.mnIndex))) |
174 | 0 | + ":" |
175 | 0 | + sXMLName |
176 | 0 | + "=" |
177 | 0 | + any2string(rState.maValue)); |
178 | 0 | } |
179 | |
|
180 | | #if 0 |
181 | | // Finally append an incremental counter in an attempt to make identical |
182 | | // styles always come out in the same order. Will see if this works. |
183 | | aStemBuffer.append("-z"); |
184 | | static sal_Int32 nCounter = 0; |
185 | | aStemBuffer.append(nCounter++)); |
186 | | #endif |
187 | | |
188 | | // create a name that hasn't been used before. The created name has not |
189 | | // to be added to the array, because it will never tried again |
190 | |
|
191 | 0 | msName = aStemBuffer; |
192 | 0 | bool bWarned = false; |
193 | 0 | while (rFamilyData.maNameSet.find(msName) != |
194 | 0 | rFamilyData.maNameSet.end()) |
195 | 0 | { |
196 | 0 | if (!bWarned) |
197 | 0 | SAL_WARN("xmloff", "Overlapping style name for " << msName); |
198 | 0 | bWarned = true; |
199 | 0 | rFamilyData.mnName++; |
200 | 0 | msName = aStemBuffer + "-" + OUString::number( static_cast<sal_Int64>(rFamilyData.mnName) ); |
201 | 0 | } |
202 | 0 | rFamilyData.maNameSet.insert(msName); |
203 | 0 | } |
204 | 9 | else |
205 | 9 | { |
206 | | // create a name that hasn't been used before. The created name has not |
207 | | // to be added to the array, because it will never tried again |
208 | 9 | do |
209 | 9 | { |
210 | 9 | rFamilyData.mnName++; |
211 | 9 | msName = rFamilyData.maStrPrefix + OUString::number( static_cast<sal_Int64>(rFamilyData.mnName) ); |
212 | 9 | } |
213 | 9 | while (rFamilyData.maNameSet.find(msName) != rFamilyData.maNameSet.end() || rFamilyData.maReservedNameSet.find(msName) != rFamilyData.maReservedNameSet.end()); |
214 | 9 | } |
215 | | |
216 | | #if OSL_DEBUG_LEVEL > 0 |
217 | | std::set<sal_Int32> DebugProperties; |
218 | | for (XMLPropertyState const & rPropState : maProperties) |
219 | | { |
220 | | sal_Int32 const property(rPropState.mnIndex); |
221 | | // serious bug: will cause duplicate attributes to be exported |
222 | | assert(DebugProperties.find(property) == DebugProperties.end()); |
223 | | if (-1 != property) |
224 | | { |
225 | | DebugProperties.insert(property); |
226 | | } |
227 | | } |
228 | | #endif |
229 | 9 | } |
230 | | |
231 | | bool operator<( const XMLAutoStyleFamily& r1, const XMLAutoStyleFamily& r2) |
232 | 524 | { |
233 | 524 | return r1.mnFamily < r2.mnFamily; |
234 | 524 | } |
235 | | |
236 | | |
237 | | XMLAutoStylePoolParent::~XMLAutoStylePoolParent() |
238 | 18 | { |
239 | 18 | } |
240 | | |
241 | | namespace { |
242 | | |
243 | | struct ComparePartial |
244 | | { |
245 | | const XMLAutoStyleFamily& rFamilyData; |
246 | | |
247 | | bool operator()(const std::vector< XMLPropertyState >& lhs, |
248 | | const XMLAutoStylePoolProperties& rhs) const |
249 | 8 | { |
250 | 8 | return rFamilyData.mxMapper->LessPartial(lhs, rhs.GetProperties()); |
251 | 8 | } |
252 | | bool operator()(const XMLAutoStylePoolProperties& lhs, |
253 | | const std::vector< XMLPropertyState >& rhs ) const |
254 | 10 | { |
255 | 10 | return rFamilyData.mxMapper->LessPartial(lhs.GetProperties(), rhs); |
256 | 10 | } |
257 | | }; |
258 | | |
259 | | } |
260 | | |
261 | | // Adds an array of XMLPropertyState ( std::vector< XMLPropertyState > ) to list |
262 | | // if not added, yet. |
263 | | |
264 | | bool XMLAutoStylePoolParent::Add( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, OUString& rName, bool bDontSeek ) |
265 | 9 | { |
266 | 9 | PropertiesListType::iterator pProperties = m_PropertiesList.end();; |
267 | 9 | auto [itBegin, itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData}); |
268 | 9 | if (!bDontSeek) |
269 | 9 | for (auto it = itBegin; it != itEnd; ++it) |
270 | 0 | if (rFamilyData.mxMapper->Equals(it->GetProperties(), rProperties)) |
271 | 0 | pProperties = it; |
272 | | |
273 | 9 | bool bAdded = false; |
274 | 9 | if( bDontSeek || pProperties == m_PropertiesList.end() ) |
275 | 9 | { |
276 | 9 | pProperties = m_PropertiesList.emplace(itBegin, rFamilyData, std::move(rProperties), msParent); |
277 | 9 | bAdded = true; |
278 | 9 | } |
279 | | |
280 | 9 | rName = pProperties->GetName(); |
281 | | |
282 | 9 | return bAdded; |
283 | 9 | } |
284 | | |
285 | | |
286 | | // Adds an array of XMLPropertyState ( std::vector< XMLPropertyState > ) with a given name. |
287 | | // If the name exists already, nothing is done. If a style with a different name and |
288 | | // the same properties exists, a new one is added (like with bDontSeek). |
289 | | |
290 | | |
291 | | bool XMLAutoStylePoolParent::AddNamed( XMLAutoStyleFamily& rFamilyData, std::vector< XMLPropertyState >&& rProperties, const OUString& rName ) |
292 | 0 | { |
293 | 0 | if (rFamilyData.maNameSet.find(rName) != rFamilyData.maNameSet.end()) |
294 | 0 | return false; |
295 | | |
296 | 0 | auto it = std::lower_bound(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData}); |
297 | |
|
298 | 0 | it = m_PropertiesList.emplace(it, rFamilyData, std::move(rProperties), msParent); |
299 | | // ignore the generated name |
300 | 0 | it->SetName( rName ); |
301 | 0 | return true; |
302 | 0 | } |
303 | | |
304 | | |
305 | | // Search for an array of XMLPropertyState ( std::vector< XMLPropertyState > ) in list |
306 | | |
307 | | |
308 | | OUString XMLAutoStylePoolParent::Find( const XMLAutoStyleFamily& rFamilyData, const std::vector< XMLPropertyState >& rProperties ) const |
309 | 5 | { |
310 | 5 | OUString sName; |
311 | 5 | auto [itBegin,itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData}); |
312 | 6 | for (auto it = itBegin; it != itEnd; ++it) |
313 | 1 | if (rFamilyData.mxMapper->Equals(it->GetProperties(), rProperties)) |
314 | 1 | sName = it->GetName(); |
315 | | |
316 | 5 | return sName; |
317 | 5 | } |
318 | | |
319 | | bool XMLAutoStylePoolParent::operator< (const XMLAutoStylePoolParent& rOther) const |
320 | 18 | { |
321 | 18 | return msParent < rOther.msParent; |
322 | 18 | } |
323 | | |
324 | | // Class SvXMLAutoStylePool_Impl |
325 | | // ctor/dtor class SvXMLAutoStylePool_Impl |
326 | | |
327 | | SvXMLAutoStylePoolP_Impl::SvXMLAutoStylePoolP_Impl( SvXMLExport& rExp) |
328 | 3 | : rExport( rExp ) |
329 | 3 | { |
330 | 3 | } |
331 | | |
332 | | SvXMLAutoStylePoolP_Impl::~SvXMLAutoStylePoolP_Impl() |
333 | 3 | { |
334 | 3 | } |
335 | | |
336 | | // Adds stylefamily-information to sorted list |
337 | | |
338 | | void SvXMLAutoStylePoolP_Impl::AddFamily( |
339 | | XmlStyleFamily nFamily, |
340 | | const OUString& rStrName, |
341 | | const rtl::Reference < SvXMLExportPropertyMapper > & rMapper, |
342 | | const OUString& rStrPrefix, |
343 | | bool bAsFamily ) |
344 | 42 | { |
345 | | // store family in a list if not already stored |
346 | 42 | SvXMLExportFlags nExportFlags = GetExport().getExportFlags(); |
347 | 42 | bool bStylesOnly = (nExportFlags & SvXMLExportFlags::STYLES) && !(nExportFlags & SvXMLExportFlags::CONTENT); |
348 | | |
349 | 42 | OUString aPrefix( rStrPrefix ); |
350 | 42 | if( bStylesOnly ) |
351 | 0 | { |
352 | 0 | aPrefix = "M" + rStrPrefix; |
353 | 0 | } |
354 | | |
355 | | #if OSL_DEBUG_LEVEL > 0 |
356 | | XMLAutoStyleFamily aTemp(nFamily); |
357 | | auto const iter = m_FamilySet.find(aTemp); |
358 | | if (iter != m_FamilySet.end()) |
359 | | { |
360 | | // FIXME: do we really intend to replace the previous nFamily |
361 | | // entry in this case ? |
362 | | SAL_WARN_IF( iter->mxMapper != rMapper, "xmloff", |
363 | | "Adding duplicate family " << rStrName << |
364 | | " with mismatching mapper ! " << |
365 | | typeid(iter->mxMapper.get()).name() << " " << |
366 | | typeid(*rMapper).name() ); |
367 | | } |
368 | | #endif |
369 | | |
370 | 42 | m_FamilySet.emplace(nFamily, rStrName, rMapper, aPrefix, bAsFamily); |
371 | 42 | } |
372 | | |
373 | | void SvXMLAutoStylePoolP_Impl::SetFamilyPropSetMapper( |
374 | | XmlStyleFamily nFamily, |
375 | | const rtl::Reference < SvXMLExportPropertyMapper > & rMapper ) |
376 | 0 | { |
377 | 0 | XMLAutoStyleFamily aTemp(nFamily); |
378 | 0 | auto const iter = m_FamilySet.find(aTemp); |
379 | 0 | if (iter != m_FamilySet.end()) |
380 | 0 | const_cast<XMLAutoStyleFamily&>(*iter).mxMapper = rMapper; |
381 | 0 | } |
382 | | |
383 | | // Adds a name to list |
384 | | void SvXMLAutoStylePoolP_Impl::RegisterName( XmlStyleFamily nFamily, const OUString& rName ) |
385 | 27 | { |
386 | 27 | XMLAutoStyleFamily aTemp(nFamily); |
387 | 27 | auto const iter = m_FamilySet.find(aTemp); |
388 | 27 | assert(iter != m_FamilySet.end()); // family must be known |
389 | 27 | const_cast<XMLAutoStyleFamily&>(*iter).maNameSet.insert(rName); |
390 | 27 | } |
391 | | |
392 | | // Adds a name to list |
393 | | void SvXMLAutoStylePoolP_Impl::RegisterDefinedName( XmlStyleFamily nFamily, const OUString& rName ) |
394 | 0 | { |
395 | 0 | XMLAutoStyleFamily aTemp(nFamily); |
396 | 0 | auto const iter = m_FamilySet.find(aTemp); |
397 | 0 | assert(iter != m_FamilySet.end()); // family must be known |
398 | 0 | const_cast<XMLAutoStyleFamily&>(*iter).maReservedNameSet.insert(rName); |
399 | 0 | } |
400 | | |
401 | | |
402 | | // Retrieve the list of registered names |
403 | | |
404 | | |
405 | | void SvXMLAutoStylePoolP_Impl::GetRegisteredNames( |
406 | | uno::Sequence<sal_Int32>& rFamilies, |
407 | | uno::Sequence<OUString>& rNames ) |
408 | 0 | { |
409 | | // collect registered names + families |
410 | 0 | std::vector<sal_Int32> aFamilies; |
411 | 0 | std::vector<OUString> aNames; |
412 | | |
413 | | // iterate over families |
414 | 0 | for (XMLAutoStyleFamily const & rFamily : m_FamilySet) |
415 | 0 | { |
416 | | // iterate over names |
417 | 0 | for (const auto& rName : rFamily.maNameSet) |
418 | 0 | { |
419 | 0 | aFamilies.push_back( static_cast<sal_Int32>(rFamily.mnFamily) ); |
420 | 0 | aNames.push_back( rName ); |
421 | 0 | } |
422 | 0 | } |
423 | | |
424 | | // copy the families + names into the sequence types |
425 | 0 | assert(aFamilies.size() == aNames.size()); |
426 | |
|
427 | 0 | rFamilies.realloc( aFamilies.size() ); |
428 | 0 | std::copy( aFamilies.begin(), aFamilies.end(), rFamilies.getArray() ); |
429 | |
|
430 | 0 | rNames.realloc( aNames.size() ); |
431 | 0 | std::copy( aNames.begin(), aNames.end(), rNames.getArray() ); |
432 | 0 | } |
433 | | |
434 | | // Adds an array of XMLPropertyState ( vector< XMLPropertyState > ) to list |
435 | | // if not added, yet. |
436 | | |
437 | | bool SvXMLAutoStylePoolP_Impl::Add( |
438 | | OUString& rName, XmlStyleFamily nFamily, const OUString& rParentName, |
439 | | ::std::vector< XMLPropertyState >&& rProperties, bool bDontSeek ) |
440 | 9 | { |
441 | 9 | XMLAutoStyleFamily aTemp(nFamily); |
442 | 9 | auto const iter = m_FamilySet.find(aTemp); |
443 | 9 | assert(iter != m_FamilySet.end()); // family must be known |
444 | | |
445 | 9 | XMLAutoStyleFamily &rFamily = const_cast<XMLAutoStyleFamily&>(*iter); |
446 | | |
447 | 9 | auto itPair = rFamily.m_ParentSet.emplace(rParentName); |
448 | 9 | XMLAutoStylePoolParent& rParent = const_cast<XMLAutoStylePoolParent&>(*itPair.first); |
449 | | |
450 | 9 | bool bRet = false; |
451 | 9 | if (rParent.Add(rFamily, std::move(rProperties), rName, bDontSeek)) |
452 | 9 | { |
453 | 9 | rFamily.mnCount++; |
454 | 9 | bRet = true; |
455 | 9 | } |
456 | | |
457 | 9 | return bRet; |
458 | 9 | } |
459 | | |
460 | | bool SvXMLAutoStylePoolP_Impl::AddNamed( |
461 | | const OUString& rName, XmlStyleFamily nFamily, const OUString& rParentName, |
462 | | std::vector< XMLPropertyState >&& rProperties ) |
463 | 0 | { |
464 | | // get family and parent the same way as in Add() |
465 | |
|
466 | 0 | XMLAutoStyleFamily aTemp(nFamily); |
467 | 0 | auto const iter = m_FamilySet.find(aTemp); |
468 | 0 | assert(iter != m_FamilySet.end()); // family must be known |
469 | |
|
470 | 0 | XMLAutoStyleFamily &rFamily = const_cast<XMLAutoStyleFamily&>(*iter); |
471 | |
|
472 | 0 | auto itPair = rFamily.m_ParentSet.emplace(rParentName); |
473 | 0 | XMLAutoStylePoolParent& rParent = const_cast<XMLAutoStylePoolParent&>(*itPair.first); |
474 | |
|
475 | 0 | bool bRet = false; |
476 | 0 | if (rParent.AddNamed(rFamily, std::move(rProperties), rName)) |
477 | 0 | { |
478 | 0 | rFamily.mnCount++; |
479 | 0 | bRet = true; |
480 | 0 | } |
481 | |
|
482 | 0 | return bRet; |
483 | 0 | } |
484 | | |
485 | | |
486 | | // Search for an array of XMLPropertyState ( std::vector< XMLPropertyState > ) in list |
487 | | |
488 | | |
489 | | OUString SvXMLAutoStylePoolP_Impl::Find( XmlStyleFamily nFamily, |
490 | | const OUString& rParent, |
491 | | const std::vector< XMLPropertyState >& rProperties ) const |
492 | 9 | { |
493 | 9 | OUString sName; |
494 | | |
495 | 9 | XMLAutoStyleFamily aTemp(nFamily); |
496 | 9 | auto const iter = m_FamilySet.find(aTemp); |
497 | 9 | assert(iter != m_FamilySet.end()); // family must be known |
498 | | |
499 | 9 | XMLAutoStyleFamily const& rFamily = *iter; |
500 | 9 | XMLAutoStylePoolParent aTmp(rParent); |
501 | 9 | auto const it2 = rFamily.m_ParentSet.find(aTmp); |
502 | 9 | if (it2 != rFamily.m_ParentSet.end()) |
503 | 5 | { |
504 | 5 | sName = it2->Find(rFamily, rProperties); |
505 | 5 | } |
506 | | |
507 | 9 | return sName; |
508 | 9 | } |
509 | | |
510 | | std::vector<xmloff::AutoStyleEntry> SvXMLAutoStylePoolP_Impl::GetAutoStyleEntries() const |
511 | 1 | { |
512 | 1 | std::vector<xmloff::AutoStyleEntry> rReturnVector; |
513 | | |
514 | 1 | for (XMLAutoStyleFamily const & rFamily : m_FamilySet) |
515 | 12 | { |
516 | 12 | rtl::Reference<XMLPropertySetMapper> aPropertyMapper = rFamily.mxMapper->getPropertySetMapper(); |
517 | 12 | for (XMLAutoStylePoolParent const & rParent : rFamily.m_ParentSet) |
518 | 3 | { |
519 | 3 | for (XMLAutoStylePoolProperties const & rProperty : rParent.GetPropertiesList()) |
520 | 5 | { |
521 | 5 | rReturnVector.emplace_back(); |
522 | 5 | xmloff::AutoStyleEntry & rEntry = rReturnVector.back(); |
523 | 5 | for (XMLPropertyState const & rPropertyState : rProperty.GetProperties()) |
524 | 113 | { |
525 | 113 | if (rPropertyState.mnIndex >= 0) |
526 | 77 | { |
527 | 77 | OUString sXmlName = aPropertyMapper->GetEntryXMLName(rPropertyState.mnIndex); |
528 | 77 | rEntry.m_aXmlProperties.emplace_back(sXmlName, rPropertyState.maValue); |
529 | 77 | } |
530 | 113 | } |
531 | 5 | } |
532 | 3 | } |
533 | 12 | } |
534 | 1 | return rReturnVector; |
535 | 1 | } |
536 | | |
537 | | namespace { |
538 | | |
539 | | struct AutoStylePoolExport |
540 | | { |
541 | | const OUString* mpParent; |
542 | | XMLAutoStylePoolProperties* mpProperties; |
543 | | |
544 | 5 | AutoStylePoolExport() : mpParent(nullptr), mpProperties(nullptr) {} |
545 | | }; |
546 | | |
547 | | struct StyleComparator |
548 | | { |
549 | | bool operator() (const AutoStylePoolExport& a, const AutoStylePoolExport& b) |
550 | 0 | { |
551 | 0 | return (a.mpProperties->GetName() < b.mpProperties->GetName() || |
552 | 0 | (a.mpProperties->GetName() == b.mpProperties->GetName() && *a.mpParent < *b.mpParent)); |
553 | 0 | } |
554 | | }; |
555 | | |
556 | | } |
557 | | |
558 | | void SvXMLAutoStylePoolP_Impl::exportXML( |
559 | | XmlStyleFamily nFamily, |
560 | | const SvXMLAutoStylePoolP *pAntiImpl) const |
561 | 12 | { |
562 | | // Get list of parents for current family (nFamily) |
563 | 12 | XMLAutoStyleFamily aTemp(nFamily); |
564 | 12 | auto const iter = m_FamilySet.find(aTemp); |
565 | 12 | assert(iter != m_FamilySet.end()); // family must be known |
566 | | |
567 | 12 | const XMLAutoStyleFamily &rFamily = *iter; |
568 | 12 | sal_uInt32 nCount = rFamily.mnCount; |
569 | | |
570 | 12 | if (!nCount) |
571 | 9 | return; |
572 | | |
573 | | // create, initialize and fill helper-structure (SvXMLAutoStylePoolProperties_Impl) |
574 | | // which contains a parent-name and a SvXMLAutoStylePoolProperties_Impl |
575 | 3 | std::vector<AutoStylePoolExport> aExpStyles(nCount); |
576 | | |
577 | 3 | for (XMLAutoStylePoolParent const& rParent : rFamily.m_ParentSet) |
578 | 3 | { |
579 | 3 | size_t nProperties = rParent.GetPropertiesList().size(); |
580 | 8 | for( size_t j = 0; j < nProperties; j++ ) |
581 | 5 | { |
582 | 5 | const XMLAutoStylePoolProperties & rProperties = |
583 | 5 | rParent.GetPropertiesList()[j]; |
584 | 5 | sal_uInt32 nPos = rProperties.GetPos(); |
585 | 5 | assert(nPos < nCount); |
586 | 5 | assert(!aExpStyles[nPos].mpProperties); |
587 | 5 | aExpStyles[nPos].mpProperties = &const_cast<XMLAutoStylePoolProperties&>(rProperties); |
588 | 5 | aExpStyles[nPos].mpParent = &rParent.GetParent(); |
589 | 5 | } |
590 | 3 | } |
591 | | |
592 | 3 | static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr); |
593 | | |
594 | 3 | if (bHack) |
595 | 0 | { |
596 | |
|
597 | 0 | std::sort(aExpStyles.begin(), aExpStyles.end(), StyleComparator()); |
598 | |
|
599 | 0 | for (size_t i = 0; i < nCount; i++) |
600 | 0 | { |
601 | 0 | OUString oldName = aExpStyles[i].mpProperties->GetName(); |
602 | 0 | sal_Int32 dashIx = oldName.indexOf('-'); |
603 | 0 | OUString newName = (dashIx > 0 ? oldName.copy(0, dashIx) : oldName) + OUString::number(i); |
604 | 0 | aExpStyles[i].mpProperties->SetName(newName); |
605 | 0 | } |
606 | 0 | } |
607 | | |
608 | | |
609 | | // create string to export for each XML-style. That means for each property-list |
610 | | |
611 | 3 | OUString aStrFamilyName = rFamily.maStrFamilyName; |
612 | | |
613 | 8 | for( size_t i = 0; i < nCount; i++ ) |
614 | 5 | { |
615 | 5 | assert(aExpStyles[i].mpProperties); |
616 | | |
617 | 5 | if( aExpStyles[i].mpProperties ) |
618 | 5 | { |
619 | 5 | GetExport().AddAttribute( |
620 | 5 | XML_NAMESPACE_STYLE, XML_NAME, |
621 | 5 | aExpStyles[i].mpProperties->GetName() ); |
622 | | |
623 | 5 | bool bExtensionNamespace = false; |
624 | 5 | if( rFamily.mbAsFamily ) |
625 | 5 | { |
626 | 5 | GetExport().AddAttribute( |
627 | 5 | XML_NAMESPACE_STYLE, XML_FAMILY, aStrFamilyName ); |
628 | 5 | if(aStrFamilyName != "graphic" && |
629 | 4 | aStrFamilyName != "drawing-page" && |
630 | 2 | aStrFamilyName != "presentation" && |
631 | 2 | aStrFamilyName != "chart" ) |
632 | 2 | bExtensionNamespace = true; |
633 | 5 | } |
634 | | |
635 | 5 | if( !aExpStyles[i].mpParent->isEmpty() ) |
636 | 1 | { |
637 | 1 | GetExport().AddAttribute( |
638 | 1 | XML_NAMESPACE_STYLE, XML_PARENT_STYLE_NAME, |
639 | 1 | GetExport().EncodeStyleName( |
640 | 1 | *aExpStyles[i].mpParent ) ); |
641 | 1 | } |
642 | | |
643 | 5 | OUString sName; |
644 | 5 | if( rFamily.mbAsFamily ) |
645 | 5 | sName = GetXMLToken(XML_STYLE); |
646 | 0 | else |
647 | 0 | sName = rFamily.maStrFamilyName; |
648 | | |
649 | 5 | pAntiImpl->exportStyleAttributes(GetExport().GetAttrList(), nFamily, |
650 | 5 | aExpStyles[i].mpProperties->GetProperties(), |
651 | 5 | *rFamily.mxMapper, GetExport().GetMM100UnitConverter(), |
652 | 5 | GetExport().GetNamespaceMap()); |
653 | | |
654 | 5 | SvXMLElementExport aElem( GetExport(), |
655 | 5 | XML_NAMESPACE_STYLE, sName, |
656 | 5 | true, true ); |
657 | | |
658 | 5 | sal_Int32 nStart(-1); |
659 | 5 | sal_Int32 nEnd(-1); |
660 | 5 | if (nFamily == XmlStyleFamily::PAGE_MASTER) |
661 | 0 | { |
662 | 0 | nStart = 0; |
663 | 0 | sal_Int32 nIndex = 0; |
664 | 0 | rtl::Reference< XMLPropertySetMapper > aPropMapper = |
665 | 0 | rFamily.mxMapper->getPropertySetMapper(); |
666 | 0 | sal_Int16 nContextID; |
667 | 0 | while(nIndex < aPropMapper->GetEntryCount() && nEnd == -1) |
668 | 0 | { |
669 | 0 | nContextID = aPropMapper->GetEntryContextId( nIndex ); |
670 | 0 | if (nContextID && ((nContextID & CTF_PM_FLAGMASK) != XML_PM_CTF_START)) |
671 | 0 | nEnd = nIndex; |
672 | 0 | nIndex++; |
673 | 0 | } |
674 | 0 | if (nEnd == -1) |
675 | 0 | nEnd = nIndex; |
676 | 0 | } |
677 | | |
678 | 5 | rFamily.mxMapper->exportXML( |
679 | 5 | GetExport(), |
680 | 5 | aExpStyles[i].mpProperties->GetProperties(), |
681 | 5 | nStart, nEnd, SvXmlExportFlags::IGN_WS, bExtensionNamespace ); |
682 | | |
683 | 5 | pAntiImpl->exportStyleContent(GetExport().GetDocHandler(), nFamily, |
684 | 5 | aExpStyles[i].mpProperties->GetProperties(), |
685 | 5 | *rFamily.mxMapper, GetExport().GetMM100UnitConverter(), |
686 | 5 | GetExport().GetNamespaceMap()); |
687 | 5 | } |
688 | 5 | } |
689 | 3 | } |
690 | | |
691 | | void SvXMLAutoStylePoolP_Impl::ClearEntries() |
692 | 0 | { |
693 | 0 | for (auto & aI : m_FamilySet) |
694 | 0 | const_cast<XMLAutoStyleFamily&>(aI).ClearEntries(); |
695 | 0 | } |
696 | | |
697 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |