Line data Source code
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 :
10 : #include <config_folders.h>
11 : #include <rtl/bootstrap.hxx>
12 : #include <tools/stream.hxx>
13 : #include <comphelper/sequenceasvector.hxx>
14 :
15 : #include "drawingml/customshapeproperties.hxx"
16 : #include "oox/token/tokenmap.hxx"
17 : #include <com/sun/star/awt/Rectangle.hpp>
18 :
19 : using namespace ::com::sun::star;
20 :
21 : namespace
22 : {
23 :
24 : // Parses a string like: Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj"
25 7800 : void lcl_parseAdjustmentValue(comphelper::SequenceAsVector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, const OString& rValue)
26 : {
27 7800 : sal_Int32 nIndex = 0;
28 7800 : drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue;
29 23400 : do
30 : {
31 23400 : OString aToken = rValue.getToken(0, ',', nIndex).trim();
32 23400 : static const OString aNamePrefix("Name = \"");
33 23400 : static const OString aValuePrefix("Value = (any) { (long) ");
34 23400 : if (aToken.startsWith(aNamePrefix))
35 : {
36 7800 : OString aName = aToken.copy(aNamePrefix.getLength(), aToken.getLength() - aNamePrefix.getLength() - strlen("\""));
37 7800 : aAdjustmentValue.Name = OStringToOUString(aName, RTL_TEXTENCODING_UTF8);
38 : }
39 15600 : else if (aToken.startsWith(aValuePrefix))
40 : {
41 7800 : OString aValue = aToken.copy(aValuePrefix.getLength(), aToken.getLength() - aValuePrefix.getLength() - strlen(" }"));
42 7800 : aAdjustmentValue.Value = uno::makeAny(aValue.toInt32());
43 : }
44 7800 : else if (!aToken.startsWith("State = "))
45 23400 : SAL_WARN("oox", "lcl_parseAdjustmentValue: unexpected prefix: " << aToken);
46 : }
47 23400 : while (nIndex >= 0);
48 7800 : rAdjustmentValues.push_back(aAdjustmentValue);
49 7800 : }
50 :
51 : // Parses a string like: { Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj" }, { Value = ..., State = ..., Name = ... }
52 3198 : void lcl_parseAdjustmentValues(comphelper::SequenceAsVector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, const OString& rValue)
53 : {
54 3198 : sal_Int32 nLevel = 0;
55 3198 : sal_Int32 nStart = 0;
56 838786 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
57 : {
58 835588 : if (rValue[i] == '{')
59 : {
60 15600 : if (!nLevel)
61 7800 : nStart = i;
62 15600 : nLevel++;
63 : }
64 819988 : else if (rValue[i] == '}')
65 : {
66 15600 : nLevel--;
67 15600 : if (!nLevel)
68 : {
69 7800 : lcl_parseAdjustmentValue(rAdjustmentValues, rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")));
70 : }
71 : }
72 : }
73 3198 : }
74 :
75 95784 : drawing::EnhancedCustomShapeParameterPair lcl_parseEnhancedCustomShapeParameterPair(const OString& rValue)
76 : {
77 95784 : drawing::EnhancedCustomShapeParameterPair aPair;
78 191568 : OString aToken = rValue;
79 : // We expect the followings here: First.Value, First.Type, Second.Value, Second.Type
80 95784 : static const OString aExpectedFVPrefix = "First = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
81 : assert(aToken.startsWith(aExpectedFVPrefix));
82 95784 : sal_Int32 nIndex = aExpectedFVPrefix.getLength();
83 95784 : aPair.First.Value = uno::makeAny(static_cast<sal_uInt32>(aToken.getToken(0, '}', nIndex).toInt32()));
84 :
85 95784 : static const OString aExpectedFTPrefix = ", Type = (short) ";
86 95784 : aToken = aToken.copy(nIndex);
87 : assert(aToken.startsWith(aExpectedFTPrefix));
88 95784 : nIndex = aExpectedFTPrefix.getLength();
89 95784 : aPair.First.Type = static_cast<sal_uInt16>(aToken.getToken(0, '}', nIndex).toInt32());
90 :
91 95784 : static const OString aExpectedSVPrefix = ", Second = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
92 95784 : aToken = aToken.copy(nIndex);
93 : assert(aToken.startsWith(aExpectedSVPrefix));
94 95784 : nIndex = aExpectedSVPrefix.getLength();
95 95784 : aPair.Second.Value = uno::makeAny(static_cast<sal_uInt32>(aToken.getToken(0, '}', nIndex).toInt32()));
96 :
97 95784 : static const OString aExpectedSTPrefix = ", Type = (short) ";
98 95784 : aToken = aToken.copy(nIndex);
99 : assert(aToken.startsWith(aExpectedSTPrefix));
100 95784 : nIndex = aExpectedSTPrefix.getLength();
101 95784 : aPair.Second.Type = static_cast<sal_uInt16>(aToken.getToken(0, '}', nIndex).toInt32());
102 191568 : return aPair;
103 : }
104 :
105 56420 : drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(const OString& rValue)
106 : {
107 56420 : drawing::EnhancedCustomShapeSegment aSegment;
108 56420 : OString aToken = rValue;
109 : // We expect the followings here: Command, Count
110 56420 : static const OString aExpectedCommandPrefix = "Command = (short) ";
111 : assert(aToken.startsWith(aExpectedCommandPrefix));
112 56420 : sal_Int32 nIndex = aExpectedCommandPrefix.getLength();
113 56420 : aSegment.Command = static_cast<sal_Int16>(aToken.getToken(0, ',', nIndex).toInt32());
114 :
115 56420 : static const OString aExpectedCountPrefix = " Count = (short) ";
116 56420 : aToken = aToken.copy(nIndex);
117 : assert(aToken.startsWith(aExpectedCountPrefix));
118 56420 : nIndex = aExpectedCountPrefix.getLength();
119 56420 : aSegment.Count = static_cast<sal_Int16>(aToken.getToken(0, '}', nIndex).toInt32());
120 56420 : return aSegment;
121 : }
122 :
123 4862 : awt::Rectangle lcl_parseRectangle(const OString& rValue)
124 : {
125 4862 : awt::Rectangle aRectangle;
126 4862 : OString aToken = rValue;
127 : // We expect the followings here: X, Y, Width, Height
128 4862 : static const OString aExpectedXPrefix = "X = (long) ";
129 : assert(aToken.startsWith(aExpectedXPrefix));
130 4862 : sal_Int32 nIndex = aExpectedXPrefix.getLength();
131 4862 : aRectangle.X = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
132 :
133 4862 : static const OString aExpectedYPrefix = " Y = (long) ";
134 4862 : aToken = aToken.copy(nIndex);
135 : assert(aToken.startsWith(aExpectedYPrefix));
136 4862 : nIndex = aExpectedYPrefix.getLength();
137 4862 : aRectangle.Y = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
138 :
139 4862 : static const OString aExpectedWidthPrefix = " Width = (long) ";
140 4862 : aToken = aToken.copy(nIndex);
141 : assert(aToken.startsWith(aExpectedWidthPrefix));
142 4862 : nIndex = aExpectedWidthPrefix.getLength();
143 4862 : aRectangle.Width = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
144 :
145 4862 : static const OString aExpectedHeightPrefix = " Height = (long) ";
146 4862 : aToken = aToken.copy(nIndex);
147 : assert(aToken.startsWith(aExpectedHeightPrefix));
148 4862 : nIndex = aExpectedHeightPrefix.getLength();
149 4862 : aRectangle.Width = static_cast<sal_Int32>(aToken.copy(nIndex).toInt32());
150 :
151 4862 : return aRectangle;
152 : }
153 :
154 1378 : awt::Size lcl_parseSize(const OString& rValue)
155 : {
156 1378 : awt::Size aSize;
157 1378 : OString aToken = rValue;
158 : // We expect the followings here: Width, Height
159 1378 : static const OString aExpectedWidthPrefix = "Width = (long) ";
160 : assert(aToken.startsWith(aExpectedWidthPrefix));
161 1378 : sal_Int32 nIndex = aExpectedWidthPrefix.getLength();
162 1378 : aSize.Width = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
163 :
164 1378 : static const OString aExpectedHeightPrefix = " Height = (long) ";
165 1378 : aToken = aToken.copy(nIndex);
166 : assert(aToken.startsWith(aExpectedHeightPrefix));
167 1378 : nIndex = aExpectedHeightPrefix.getLength();
168 1378 : aSize.Height = static_cast<sal_Int32>(aToken.copy(nIndex).toInt32());
169 :
170 1378 : return aSize;
171 : }
172 :
173 4732 : drawing::EnhancedCustomShapeTextFrame lcl_parseEnhancedCustomShapeTextFrame(const OString& rValue)
174 : {
175 4732 : drawing::EnhancedCustomShapeTextFrame aTextFrame;
176 4732 : sal_Int32 nLevel = 0;
177 4732 : bool bIgnore = false;
178 4732 : sal_Int32 nStart = 0;
179 2776618 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
180 : {
181 2771886 : if (rValue[i] == '{')
182 : {
183 47320 : if (!nLevel)
184 9464 : bIgnore = true;
185 47320 : nLevel++;
186 : }
187 2724566 : else if (rValue[i] == '}')
188 : {
189 47320 : nLevel--;
190 47320 : if (!nLevel)
191 9464 : bIgnore = false;
192 : }
193 2677246 : else if (rValue[i] == ',' && !bIgnore)
194 : {
195 4732 : OString aToken = rValue.copy(nStart, i - nStart);
196 4732 : static const OString aExpectedPrefix("TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
197 4732 : if (aToken.startsWith(aExpectedPrefix))
198 : {
199 4732 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
200 4732 : aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken);
201 : }
202 : else
203 : SAL_WARN("oox", "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken);
204 4732 : nStart = i + strlen(", ");
205 : }
206 : }
207 :
208 9464 : OString aToken = rValue.copy(nStart, rValue.getLength() - nStart);
209 4732 : static const OString aExpectedPrefix("BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
210 4732 : if (aToken.startsWith(aExpectedPrefix))
211 : {
212 4732 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
213 4732 : aTextFrame.BottomRight = lcl_parseEnhancedCustomShapeParameterPair(aToken);
214 : }
215 : else
216 : SAL_WARN("oox", "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken);
217 :
218 9464 : return aTextFrame;
219 : }
220 :
221 : // Parses a string like: Name = "Position", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
222 : // where "{ ... }" may contain "," as well.
223 6318 : void lcl_parseHandlePosition(comphelper::SequenceAsVector<beans::PropertyValue>& rHandle, const OString& rValue)
224 : {
225 6318 : sal_Int32 nLevel = 0;
226 6318 : bool bIgnore = false;
227 6318 : sal_Int32 nStart = 0;
228 2488512 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
229 : {
230 2482194 : if (rValue[i] == '{')
231 : {
232 37908 : if (!nLevel)
233 6318 : bIgnore = true;
234 37908 : nLevel++;
235 : }
236 2444286 : else if (rValue[i] == '}')
237 : {
238 37908 : nLevel--;
239 37908 : if (!nLevel)
240 6318 : bIgnore = false;
241 : }
242 2406378 : else if (rValue[i] == ',' && !bIgnore)
243 : {
244 18954 : OString aToken = rValue.copy(nStart, i - nStart);
245 18954 : static const OString aExpectedPrefix("Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
246 18954 : if (aToken.startsWith(aExpectedPrefix))
247 : {
248 6318 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
249 :
250 6318 : beans::PropertyValue aPropertyValue;
251 6318 : aPropertyValue.Name = "Position";
252 6318 : aPropertyValue.Value = uno::makeAny(lcl_parseEnhancedCustomShapeParameterPair(aToken));
253 6318 : rHandle.push_back(aPropertyValue);
254 : }
255 12636 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
256 : SAL_WARN("oox", "lcl_parseHandlePosition: unexpected token: " << aToken);
257 18954 : nStart = i + strlen(", ");
258 : }
259 : }
260 6318 : }
261 :
262 : // Parses a string like: Name = "RangeYMaximum", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
263 : // where "{ ... }" may contain "," as well.
264 13988 : void lcl_parseHandleRange(comphelper::SequenceAsVector<beans::PropertyValue>& rHandle, const OString& rValue, const OUString& rName)
265 : {
266 13988 : sal_Int32 nLevel = 0;
267 13988 : bool bIgnore = false;
268 13988 : sal_Int32 nStart = 0;
269 3122106 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
270 : {
271 3108118 : if (rValue[i] == '{')
272 : {
273 41964 : if (!nLevel)
274 13988 : bIgnore = true;
275 41964 : nLevel++;
276 : }
277 3066154 : else if (rValue[i] == '}')
278 : {
279 41964 : nLevel--;
280 41964 : if (!nLevel)
281 13988 : bIgnore = false;
282 : }
283 3024190 : else if (rValue[i] == ',' && !bIgnore)
284 : {
285 41964 : OString aToken = rValue.copy(nStart, i - nStart);
286 41964 : static const OString aExpectedPrefix("Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { ");
287 41964 : if (aToken.startsWith(aExpectedPrefix))
288 : {
289 13988 : drawing::EnhancedCustomShapeParameter aParameter;
290 13988 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
291 : // We expect the followings here: Value and Type
292 13988 : static const OString aExpectedVPrefix = "Value = (any) { (long) ";
293 : assert(aToken.startsWith(aExpectedVPrefix));
294 13988 : sal_Int32 nIndex = aExpectedVPrefix.getLength();
295 13988 : aParameter.Value = uno::makeAny(aToken.getToken(0, '}', nIndex).toInt32());
296 :
297 13988 : static const OString aExpectedTPrefix = ", Type = (short) ";
298 13988 : aToken = aToken.copy(nIndex);
299 : assert(aToken.startsWith(aExpectedTPrefix));
300 13988 : nIndex = aExpectedTPrefix.getLength();
301 13988 : aParameter.Type = static_cast<sal_Int16>(aToken.getToken(0, '}', nIndex).toInt32());
302 :
303 27976 : beans::PropertyValue aPropertyValue;
304 13988 : aPropertyValue.Name = rName;
305 13988 : aPropertyValue.Value = uno::makeAny(aParameter);
306 27976 : rHandle.push_back(aPropertyValue);
307 :
308 : }
309 27976 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
310 : SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: " << aToken);
311 41964 : nStart = i + strlen(", ");
312 : }
313 : }
314 13988 : }
315 :
316 : // Parses a string like: Name = "RefY", Handle = (long) 0, Value = (any) { (long) 0 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
317 6760 : void lcl_parseHandleRef(comphelper::SequenceAsVector<beans::PropertyValue>& rHandle, const OString& rValue, const OUString& rName)
318 : {
319 6760 : static const OString aExpectedXPrefix("Name = \"RefX\", Handle = (long) 0, Value = (any) { (long) ");
320 6760 : static const OString aExpectedYPrefix("Name = \"RefY\", Handle = (long) 0, Value = (any) { (long) ");
321 6760 : if (rValue.startsWith(aExpectedXPrefix) || rValue.startsWith(aExpectedYPrefix))
322 : {
323 6760 : sal_Int32 nIndex = aExpectedXPrefix.getLength();
324 6760 : beans::PropertyValue aPropertyValue;
325 6760 : aPropertyValue.Name = rName;
326 : // We only expect a Value here
327 6760 : aPropertyValue.Value = uno::makeAny(rValue.getToken(0, '}', nIndex).toInt32());
328 6760 : rHandle.push_back(aPropertyValue);
329 : }
330 : else
331 : SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue);
332 6760 : }
333 :
334 6318 : uno::Sequence<beans::PropertyValue> lcl_parseHandle(const OString& rValue)
335 : {
336 6318 : comphelper::SequenceAsVector<beans::PropertyValue> aRet;
337 6318 : sal_Int32 nLevel = 0;
338 6318 : sal_Int32 nStart = 0;
339 6537310 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
340 : {
341 6530992 : if (rValue[i] == '{')
342 : {
343 113698 : if (!nLevel)
344 27066 : nStart = i;
345 113698 : nLevel++;
346 : }
347 6417294 : else if (rValue[i] == '}')
348 : {
349 113698 : nLevel--;
350 113698 : if (!nLevel)
351 : {
352 27066 : OString aToken = rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"));
353 27066 : if (aToken.startsWith("Name = \"Position\""))
354 6318 : lcl_parseHandlePosition(aRet, aToken);
355 20748 : else if (aToken.startsWith("Name = \"RangeXMaximum\""))
356 3432 : lcl_parseHandleRange(aRet, aToken, "RangeXMaximum");
357 17316 : else if (aToken.startsWith("Name = \"RangeXMinimum\""))
358 3432 : lcl_parseHandleRange(aRet, aToken, "RangeXMinimum");
359 13884 : else if (aToken.startsWith("Name = \"RangeYMaximum\""))
360 3328 : lcl_parseHandleRange(aRet, aToken, "RangeYMaximum");
361 10556 : else if (aToken.startsWith("Name = \"RangeYMinimum\""))
362 3328 : lcl_parseHandleRange(aRet, aToken, "RangeYMinimum");
363 7228 : else if (aToken.startsWith("Name = \"RadiusRangeMaximum\""))
364 234 : lcl_parseHandleRange(aRet, aToken, "RadiusRangeMaximum");
365 6994 : else if (aToken.startsWith("Name = \"RadiusRangeMinimum\""))
366 234 : lcl_parseHandleRange(aRet, aToken, "RadiusRangeMinimum");
367 6760 : else if (aToken.startsWith("Name = \"RefX\""))
368 3432 : lcl_parseHandleRef(aRet, aToken, "RefX");
369 3328 : else if (aToken.startsWith("Name = \"RefY\""))
370 3328 : lcl_parseHandleRef(aRet, aToken, "RefY");
371 : else
372 27066 : SAL_WARN("oox", "lcl_parseHandle: unexpected token: " << aToken);
373 : }
374 : }
375 : }
376 6318 : return aRet.getAsConstList();
377 : }
378 :
379 3120 : void lcl_parseHandles(comphelper::SequenceAsVector< uno::Sequence<beans::PropertyValue> >& rHandles, const OString& rValue)
380 : {
381 3120 : sal_Int32 nLevel = 0;
382 3120 : sal_Int32 nStart = 0;
383 6565780 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
384 : {
385 6562660 : if (rValue[i] == '{')
386 : {
387 120016 : if (!nLevel)
388 6318 : nStart = i;
389 120016 : nLevel++;
390 : }
391 6442644 : else if (rValue[i] == '}')
392 : {
393 120016 : nLevel--;
394 120016 : if (!nLevel)
395 : {
396 6318 : uno::Sequence<beans::PropertyValue> aHandle = lcl_parseHandle(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")));
397 6318 : rHandles.push_back(aHandle);
398 : }
399 : }
400 : }
401 3120 : }
402 :
403 4784 : void lcl_parseEquations(comphelper::SequenceAsVector<OUString>& rEquations, const OString& rValue)
404 : {
405 4784 : bool bInString = false;
406 4784 : sal_Int32 nStart = 0;
407 2643264 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
408 : {
409 2638480 : if (rValue[i] == '"' && !bInString)
410 : {
411 136500 : nStart = i;
412 136500 : bInString = true;
413 : }
414 2501980 : else if (rValue[i] == '"' && bInString)
415 : {
416 136500 : bInString = false;
417 136500 : rEquations.push_back(OStringToOUString(rValue.copy(nStart + strlen("\""), i - nStart - strlen("\"")), RTL_TEXTENCODING_UTF8));
418 : }
419 : }
420 4784 : }
421 :
422 4862 : void lcl_parsePathCoordinateValues(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
423 : {
424 4862 : comphelper::SequenceAsVector<drawing::EnhancedCustomShapeParameterPair> aPairs;
425 4862 : sal_Int32 nLevel = 0;
426 4862 : sal_Int32 nStart = 0;
427 18117372 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
428 : {
429 18112510 : if (rValue[i] == '{')
430 : {
431 400010 : if (!nLevel)
432 80002 : nStart = i;
433 400010 : nLevel++;
434 : }
435 17712500 : else if (rValue[i] == '}')
436 : {
437 400010 : nLevel--;
438 400010 : if (!nLevel)
439 80002 : aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
440 : }
441 : }
442 :
443 9724 : beans::PropertyValue aPropertyValue;
444 4862 : aPropertyValue.Name = "Coordinates";
445 4862 : aPropertyValue.Value = uno::makeAny(aPairs.getAsConstList());
446 9724 : rPath.push_back(aPropertyValue);
447 4862 : }
448 :
449 : // Parses a string like: Name = "Coordinates", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
450 : // where "{ ... }" may contain "," as well.
451 4862 : void lcl_parsePathCoordinates(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
452 : {
453 4862 : sal_Int32 nLevel = 0;
454 4862 : bool bIgnore = false;
455 4862 : sal_Int32 nStart = 0;
456 18982808 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
457 : {
458 18977946 : if (rValue[i] == '{')
459 : {
460 409734 : if (!nLevel)
461 4862 : bIgnore = true;
462 409734 : nLevel++;
463 : }
464 18568212 : else if (rValue[i] == '}')
465 : {
466 409734 : nLevel--;
467 409734 : if (!nLevel)
468 4862 : bIgnore = false;
469 : }
470 18158478 : else if (rValue[i] == ',' && !bIgnore)
471 : {
472 14586 : OString aToken = rValue.copy(nStart, i - nStart);
473 14586 : static const OString aExpectedPrefix("Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
474 14586 : if (aToken.startsWith(aExpectedPrefix))
475 : {
476 4862 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
477 4862 : lcl_parsePathCoordinateValues(rPath, aToken);
478 : }
479 9724 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
480 : SAL_WARN("oox", "lcl_parsePathCoordinates: unexpected token: " << aToken);
481 14586 : nStart = i + strlen(", ");
482 : }
483 : }
484 4862 : }
485 :
486 4862 : void lcl_parsePathSegmentValues(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
487 : {
488 4862 : comphelper::SequenceAsVector<drawing::EnhancedCustomShapeSegment> aSegments;
489 4862 : sal_Int32 nLevel = 0;
490 4862 : sal_Int32 nStart = 0;
491 2488096 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
492 : {
493 2483234 : if (rValue[i] == '{')
494 : {
495 56420 : if (!nLevel)
496 56420 : nStart = i;
497 56420 : nLevel++;
498 : }
499 2426814 : else if (rValue[i] == '}')
500 : {
501 56420 : nLevel--;
502 56420 : if (!nLevel)
503 56420 : aSegments.push_back(lcl_parseEnhancedCustomShapeSegment(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
504 : }
505 : }
506 :
507 9724 : beans::PropertyValue aPropertyValue;
508 4862 : aPropertyValue.Name = "Segments";
509 4862 : aPropertyValue.Value = uno::makeAny(aSegments.getAsConstList());
510 9724 : rPath.push_back(aPropertyValue);
511 4862 : }
512 :
513 : // Parses a string like: Name = "Segments", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
514 : // where "{ ... }" may contain "," as well.
515 4862 : void lcl_parsePathSegments(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
516 : {
517 4862 : sal_Int32 nLevel = 0;
518 4862 : bool bIgnore = false;
519 4862 : sal_Int32 nStart = 0;
520 3309774 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
521 : {
522 3304912 : if (rValue[i] == '{')
523 : {
524 66144 : if (!nLevel)
525 4862 : bIgnore = true;
526 66144 : nLevel++;
527 : }
528 3238768 : else if (rValue[i] == '}')
529 : {
530 66144 : nLevel--;
531 66144 : if (!nLevel)
532 4862 : bIgnore = false;
533 : }
534 3172624 : else if (rValue[i] == ',' && !bIgnore)
535 : {
536 14586 : OString aToken = rValue.copy(nStart, i - nStart);
537 14586 : static const OString aExpectedPrefix("Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { ");
538 14586 : if (aToken.startsWith(aExpectedPrefix))
539 : {
540 4862 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
541 4862 : lcl_parsePathSegmentValues(rPath, aToken);
542 : }
543 9724 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
544 : SAL_WARN("oox", "lcl_parsePathSegments: unexpected token: " << aToken);
545 14586 : nStart = i + strlen(", ");
546 : }
547 : }
548 4862 : }
549 :
550 4732 : void lcl_parsePathTextFrameValues(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
551 : {
552 4732 : comphelper::SequenceAsVector<drawing::EnhancedCustomShapeTextFrame> aTextFrames;
553 4732 : sal_Int32 nLevel = 0;
554 4732 : sal_Int32 nStart = 0;
555 2795546 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
556 : {
557 2790814 : if (rValue[i] == '{')
558 : {
559 52052 : if (!nLevel)
560 4732 : nStart = i;
561 52052 : nLevel++;
562 : }
563 2738762 : else if (rValue[i] == '}')
564 : {
565 52052 : nLevel--;
566 52052 : if (!nLevel)
567 4732 : aTextFrames.push_back(lcl_parseEnhancedCustomShapeTextFrame(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
568 : }
569 : }
570 :
571 9464 : beans::PropertyValue aPropertyValue;
572 4732 : aPropertyValue.Name = "TextFrames";
573 4732 : aPropertyValue.Value = uno::makeAny(aTextFrames.getAsConstList());
574 9464 : rPath.push_back(aPropertyValue);
575 4732 : }
576 :
577 : // Parses a string like: Name = "TextFrames", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
578 : // where "{ ... }" may contain "," as well.
579 4732 : void lcl_parsePathTextFrames(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
580 : {
581 4732 : sal_Int32 nLevel = 0;
582 4732 : bool bIgnore = false;
583 4732 : sal_Int32 nStart = 0;
584 3614182 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
585 : {
586 3609450 : if (rValue[i] == '{')
587 : {
588 61516 : if (!nLevel)
589 4732 : bIgnore = true;
590 61516 : nLevel++;
591 : }
592 3547934 : else if (rValue[i] == '}')
593 : {
594 61516 : nLevel--;
595 61516 : if (!nLevel)
596 4732 : bIgnore = false;
597 : }
598 3486418 : else if (rValue[i] == ',' && !bIgnore)
599 : {
600 14196 : OString aToken = rValue.copy(nStart, i - nStart);
601 14196 : static const OString aExpectedPrefix("Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { ");
602 14196 : if (aToken.startsWith(aExpectedPrefix))
603 : {
604 4732 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
605 4732 : lcl_parsePathTextFrameValues(rPath, aToken);
606 : }
607 9464 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
608 : SAL_WARN("oox", "lcl_parsePathTextFrames: unexpected token: " << aToken);
609 14196 : nStart = i + strlen(", ");
610 : }
611 : }
612 4732 : }
613 :
614 806 : void lcl_parsePathSubViewSizeValues(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
615 : {
616 806 : comphelper::SequenceAsVector<awt::Size> aSizes;
617 806 : sal_Int32 nLevel = 0;
618 806 : sal_Int32 nStart = 0;
619 58656 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
620 : {
621 57850 : if (rValue[i] == '{')
622 : {
623 1378 : if (!nLevel)
624 1378 : nStart = i;
625 1378 : nLevel++;
626 : }
627 56472 : else if (rValue[i] == '}')
628 : {
629 1378 : nLevel--;
630 1378 : if (!nLevel)
631 1378 : aSizes.push_back(lcl_parseSize(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
632 : }
633 : }
634 :
635 1612 : beans::PropertyValue aPropertyValue;
636 806 : aPropertyValue.Name = "SubViewSize";
637 806 : aPropertyValue.Value = uno::makeAny(aSizes.getAsConstList());
638 1612 : rPath.push_back(aPropertyValue);
639 806 : }
640 :
641 806 : void lcl_parsePathSubViewSize(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
642 : {
643 806 : sal_Int32 nLevel = 0;
644 806 : bool bIgnore = false;
645 806 : sal_Int32 nStart = 0;
646 176332 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
647 : {
648 175526 : if (rValue[i] == '{')
649 : {
650 2990 : if (!nLevel)
651 806 : bIgnore = true;
652 2990 : nLevel++;
653 : }
654 172536 : else if (rValue[i] == '}')
655 : {
656 2990 : nLevel--;
657 2990 : if (!nLevel)
658 806 : bIgnore = false;
659 : }
660 169546 : else if (rValue[i] == ',' && !bIgnore)
661 : {
662 2418 : OString aToken = rValue.copy(nStart, i - nStart);
663 2418 : static const OString aExpectedPrefix("Value = (any) { ([]com.sun.star.awt.Size) { ");
664 2418 : if (aToken.startsWith(aExpectedPrefix))
665 : {
666 806 : aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
667 806 : lcl_parsePathSubViewSizeValues(rPath, aToken);
668 : }
669 1612 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
670 : SAL_WARN("oox", "lcl_parsePathSubViewSize: unexpected token: " << aToken);
671 2418 : nStart = i + strlen(", ");
672 : }
673 : }
674 806 : }
675 :
676 4862 : void lcl_parsePath(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
677 : {
678 4862 : sal_Int32 nLevel = 0;
679 4862 : sal_Int32 nStart = 0;
680 26154544 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
681 : {
682 26149682 : if (rValue[i] == '{')
683 : {
684 555646 : if (!nLevel)
685 15262 : nStart = i;
686 555646 : nLevel++;
687 : }
688 25594036 : else if (rValue[i] == '}')
689 : {
690 555646 : nLevel--;
691 555646 : if (!nLevel)
692 : {
693 15262 : OString aToken = rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"));
694 15262 : if (aToken.startsWith("Name = \"Coordinates\""))
695 4862 : lcl_parsePathCoordinates(rPath, aToken);
696 10400 : else if (aToken.startsWith("Name = \"Segments\""))
697 4862 : lcl_parsePathSegments(rPath, aToken);
698 5538 : else if (aToken.startsWith("Name = \"TextFrames\""))
699 4732 : lcl_parsePathTextFrames(rPath, aToken);
700 806 : else if (aToken.startsWith("Name = \"SubViewSize\""))
701 806 : lcl_parsePathSubViewSize(rPath, aToken);
702 : else
703 15262 : SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken);
704 : }
705 : }
706 : }
707 4862 : }
708 :
709 : }
710 :
711 : namespace oox
712 : {
713 : namespace drawingml
714 : {
715 :
716 26 : void CustomShapeProperties::initializePresetDataMap()
717 : {
718 26 : OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-cs-presets");
719 26 : rtl::Bootstrap::expandMacros(aPath);
720 52 : SvFileStream aStream(aPath, STREAM_READ);
721 26 : if (aStream.GetError() != ERRCODE_NONE)
722 : SAL_WARN("oox", "failed to open oox-drawingml-cs-presets");
723 52 : OString aLine;
724 52 : OUString aName;
725 26 : bool bNotDone = aStream.ReadLine(aLine);
726 52 : PropertyMap aPropertyMap;
727 26 : bool bFirst = true;
728 43810 : while (bNotDone)
729 : {
730 43758 : static const OString aCommentPrefix("/* ");
731 43758 : if (aLine.startsWith(aCommentPrefix))
732 : {
733 4862 : if (bFirst)
734 26 : bFirst = false;
735 : else
736 4836 : maPresetDataMap[StaticTokenMap::get().getTokenFromUnicode(aName)] = aPropertyMap;
737 4862 : aName = OStringToOUString(aLine.copy(aCommentPrefix.getLength(), aLine.getLength() - aCommentPrefix.getLength() - strlen(" */")), RTL_TEXTENCODING_UTF8);
738 : }
739 : else
740 : {
741 38896 : if (aLine == "AdjustmentValues")
742 : {
743 4862 : aStream.ReadLine(aLine);
744 4862 : if (aLine != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}")
745 : {
746 3198 : comphelper::SequenceAsVector<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
747 6396 : OString aExpectedPrefix("([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { ");
748 : assert(aLine.startsWith(aExpectedPrefix));
749 :
750 6396 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
751 3198 : lcl_parseAdjustmentValues(aAdjustmentValues, aValue);
752 6396 : aPropertyMap.setProperty(PROP_AdjustmentValues, aAdjustmentValues.getAsConstList());
753 : }
754 : else
755 1664 : aPropertyMap.setProperty(PROP_AdjustmentValues, uno::Sequence<OUString>(0));
756 : }
757 34034 : else if (aLine == "Equations")
758 : {
759 4862 : aStream.ReadLine(aLine);
760 4862 : if (aLine != "([]string) {}")
761 : {
762 4784 : comphelper::SequenceAsVector<OUString> aEquations;
763 9568 : OString aExpectedPrefix("([]string) { ");
764 : assert(aLine.startsWith(aExpectedPrefix));
765 :
766 9568 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
767 4784 : lcl_parseEquations(aEquations, aValue);
768 9568 : aPropertyMap.setProperty(PROP_Equations, aEquations.getAsConstList());
769 : }
770 : else
771 78 : aPropertyMap.setProperty(PROP_Equations, uno::Sequence<OUString>(0));
772 : }
773 29172 : else if (aLine == "Handles")
774 : {
775 4862 : aStream.ReadLine(aLine);
776 4862 : if (aLine != "([][]com.sun.star.beans.PropertyValue) {}")
777 : {
778 3120 : comphelper::SequenceAsVector< uno::Sequence<beans::PropertyValue> > aHandles;
779 6240 : OString aExpectedPrefix("([][]com.sun.star.beans.PropertyValue) { ");
780 : assert(aLine.startsWith(aExpectedPrefix));
781 :
782 6240 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
783 3120 : lcl_parseHandles(aHandles, aValue);
784 6240 : aPropertyMap.setProperty(PROP_Handles, aHandles.getAsConstList());
785 : }
786 : else
787 1742 : aPropertyMap.setProperty(PROP_Handles, uno::Sequence<OUString>(0));
788 : }
789 24310 : else if (aLine == "MirroredX")
790 : {
791 4862 : aStream.ReadLine(aLine);
792 4862 : if (aLine == "true" || aLine == "false")
793 : {
794 4862 : aPropertyMap.setProperty(PROP_MirroredX, aLine == "true");
795 : }
796 : else
797 : SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected MirroredX parameter");
798 : }
799 19448 : else if (aLine == "MirroredY")
800 : {
801 4862 : aStream.ReadLine(aLine);
802 4862 : if (aLine == "true" || aLine == "false")
803 : {
804 4862 : aPropertyMap.setProperty(PROP_MirroredY, aLine == "true");
805 : }
806 : else
807 : SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected MirroredY parameter");
808 : }
809 14586 : else if (aLine == "Path")
810 : {
811 4862 : aStream.ReadLine(aLine);
812 4862 : OString aExpectedPrefix("([]com.sun.star.beans.PropertyValue) { ");
813 : assert(aLine.startsWith(aExpectedPrefix));
814 :
815 9724 : comphelper::SequenceAsVector<beans::PropertyValue> aPathValue;
816 9724 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
817 4862 : lcl_parsePath(aPathValue, aValue);
818 9724 : aPropertyMap.setProperty(PROP_Path, aPathValue.getAsConstList());
819 : }
820 9724 : else if (aLine == "Type")
821 : {
822 : // Just ignore the line here, we already know the correct type.
823 4862 : aStream.ReadLine(aLine);
824 4862 : aPropertyMap.setProperty(PROP_Type, "ooxml-" + aName);
825 : }
826 4862 : else if (aLine == "ViewBox")
827 : {
828 4862 : aStream.ReadLine(aLine);
829 4862 : OString aExpectedPrefix("(com.sun.star.awt.Rectangle) { ");
830 : assert(aLine.startsWith(aExpectedPrefix));
831 :
832 9724 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
833 9724 : aPropertyMap.setProperty(PROP_ViewBox, lcl_parseRectangle(aValue));
834 : }
835 : else
836 : SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: " << aLine);
837 : }
838 43758 : bNotDone = aStream.ReadLine(aLine);
839 : }
840 52 : maPresetDataMap[StaticTokenMap::get().getTokenFromUnicode(aName)] = aPropertyMap;
841 26 : }
842 :
843 : }
844 408 : }
845 :
846 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|