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/sequence.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 5100 : void lcl_parseAdjustmentValue(std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, const OString& rValue)
26 : {
27 5100 : sal_Int32 nIndex = 0;
28 5100 : drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue;
29 15300 : do
30 : {
31 15300 : OString aToken = rValue.getToken(0, ',', nIndex).trim();
32 : static const char aNamePrefix[] = "Name = \"";
33 : static const char aValuePrefix[] = "Value = (any) { (long) ";
34 15300 : if (aToken.startsWith(aNamePrefix))
35 : {
36 5100 : OString aName = aToken.copy(strlen(aNamePrefix), aToken.getLength() - strlen(aNamePrefix) - strlen("\""));
37 5100 : aAdjustmentValue.Name = OUString::fromUtf8(aName);
38 : }
39 10200 : else if (aToken.startsWith(aValuePrefix))
40 : {
41 5100 : OString aValue = aToken.copy(strlen(aValuePrefix), aToken.getLength() - strlen(aValuePrefix) - strlen(" }"));
42 5100 : aAdjustmentValue.Value = uno::makeAny(aValue.toInt32());
43 : }
44 5100 : else if (!aToken.startsWith("State = "))
45 15300 : SAL_WARN("oox", "lcl_parseAdjustmentValue: unexpected prefix: " << aToken);
46 : }
47 15300 : while (nIndex >= 0);
48 5100 : rAdjustmentValues.push_back(aAdjustmentValue);
49 5100 : }
50 :
51 : // Parses a string like: { Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj" }, { Value = ..., State = ..., Name = ... }
52 2091 : void lcl_parseAdjustmentValues(std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, const OString& rValue)
53 : {
54 2091 : sal_Int32 nLevel = 0;
55 2091 : sal_Int32 nStart = 0;
56 548437 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
57 : {
58 546346 : if (rValue[i] == '{')
59 : {
60 10200 : if (!nLevel)
61 5100 : nStart = i;
62 10200 : nLevel++;
63 : }
64 536146 : else if (rValue[i] == '}')
65 : {
66 10200 : nLevel--;
67 10200 : if (!nLevel)
68 : {
69 5100 : lcl_parseAdjustmentValue(rAdjustmentValues, rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")));
70 : }
71 : }
72 : }
73 2091 : }
74 :
75 62628 : drawing::EnhancedCustomShapeParameterPair lcl_parseEnhancedCustomShapeParameterPair(const OString& rValue)
76 : {
77 62628 : drawing::EnhancedCustomShapeParameterPair aPair;
78 125256 : OString aToken = rValue;
79 : // We expect the followings here: First.Value, First.Type, Second.Value, Second.Type
80 : static const char aExpectedFVPrefix[] = "First = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
81 : assert(aToken.startsWith(aExpectedFVPrefix));
82 62628 : sal_Int32 nIndex = strlen(aExpectedFVPrefix);
83 62628 : aPair.First.Value = uno::makeAny(static_cast<sal_uInt32>(aToken.getToken(0, '}', nIndex).toInt32()));
84 :
85 : static const char aExpectedFTPrefix[] = ", Type = (short) ";
86 62628 : aToken = aToken.copy(nIndex);
87 : assert(aToken.startsWith(aExpectedFTPrefix));
88 62628 : nIndex = strlen(aExpectedFTPrefix);
89 62628 : aPair.First.Type = static_cast<sal_uInt16>(aToken.getToken(0, '}', nIndex).toInt32());
90 :
91 : static const char aExpectedSVPrefix[] = ", Second = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
92 62628 : aToken = aToken.copy(nIndex);
93 : assert(aToken.startsWith(aExpectedSVPrefix));
94 62628 : nIndex = strlen(aExpectedSVPrefix);
95 62628 : aPair.Second.Value = uno::makeAny(static_cast<sal_uInt32>(aToken.getToken(0, '}', nIndex).toInt32()));
96 :
97 : static const char aExpectedSTPrefix[] = ", Type = (short) ";
98 62628 : aToken = aToken.copy(nIndex);
99 : assert(aToken.startsWith(aExpectedSTPrefix));
100 62628 : nIndex = strlen(aExpectedSTPrefix);
101 62628 : aPair.Second.Type = static_cast<sal_uInt16>(aToken.getToken(0, '}', nIndex).toInt32());
102 125256 : return aPair;
103 : }
104 :
105 36890 : drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(const OString& rValue)
106 : {
107 36890 : drawing::EnhancedCustomShapeSegment aSegment;
108 36890 : OString aToken = rValue;
109 : // We expect the followings here: Command, Count
110 : static const char aExpectedCommandPrefix[] = "Command = (short) ";
111 : assert(aToken.startsWith(aExpectedCommandPrefix));
112 36890 : sal_Int32 nIndex = strlen(aExpectedCommandPrefix);
113 36890 : aSegment.Command = static_cast<sal_Int16>(aToken.getToken(0, ',', nIndex).toInt32());
114 :
115 : static const char aExpectedCountPrefix[] = " Count = (short) ";
116 36890 : aToken = aToken.copy(nIndex);
117 : assert(aToken.startsWith(aExpectedCountPrefix));
118 36890 : nIndex = strlen(aExpectedCountPrefix);
119 36890 : aSegment.Count = static_cast<sal_Int16>(aToken.getToken(0, '}', nIndex).toInt32());
120 36890 : return aSegment;
121 : }
122 :
123 3179 : awt::Rectangle lcl_parseRectangle(const OString& rValue)
124 : {
125 3179 : awt::Rectangle aRectangle;
126 3179 : OString aToken = rValue;
127 : // We expect the followings here: X, Y, Width, Height
128 : static const char aExpectedXPrefix[] = "X = (long) ";
129 : assert(aToken.startsWith(aExpectedXPrefix));
130 3179 : sal_Int32 nIndex = strlen(aExpectedXPrefix);
131 3179 : aRectangle.X = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
132 :
133 : static const char aExpectedYPrefix[] = " Y = (long) ";
134 3179 : aToken = aToken.copy(nIndex);
135 : assert(aToken.startsWith(aExpectedYPrefix));
136 3179 : nIndex = strlen(aExpectedYPrefix);
137 3179 : aRectangle.Y = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
138 :
139 : static const char aExpectedWidthPrefix[] = " Width = (long) ";
140 3179 : aToken = aToken.copy(nIndex);
141 : assert(aToken.startsWith(aExpectedWidthPrefix));
142 3179 : nIndex = strlen(aExpectedWidthPrefix);
143 3179 : aRectangle.Width = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
144 :
145 : static const char aExpectedHeightPrefix[] = " Height = (long) ";
146 3179 : aToken = aToken.copy(nIndex);
147 : assert(aToken.startsWith(aExpectedHeightPrefix));
148 3179 : nIndex = strlen(aExpectedHeightPrefix);
149 3179 : aRectangle.Height = static_cast<sal_Int32>(aToken.copy(nIndex).toInt32());
150 :
151 3179 : return aRectangle;
152 : }
153 :
154 901 : awt::Size lcl_parseSize(const OString& rValue)
155 : {
156 901 : awt::Size aSize;
157 901 : OString aToken = rValue;
158 : // We expect the followings here: Width, Height
159 : static const char aExpectedWidthPrefix[] = "Width = (long) ";
160 : assert(aToken.startsWith(aExpectedWidthPrefix));
161 901 : sal_Int32 nIndex = strlen(aExpectedWidthPrefix);
162 901 : aSize.Width = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
163 :
164 : static const char aExpectedHeightPrefix[] = " Height = (long) ";
165 901 : aToken = aToken.copy(nIndex);
166 : assert(aToken.startsWith(aExpectedHeightPrefix));
167 901 : nIndex = strlen(aExpectedHeightPrefix);
168 901 : aSize.Height = static_cast<sal_Int32>(aToken.copy(nIndex).toInt32());
169 :
170 901 : return aSize;
171 : }
172 :
173 3094 : drawing::EnhancedCustomShapeTextFrame lcl_parseEnhancedCustomShapeTextFrame(const OString& rValue)
174 : {
175 3094 : drawing::EnhancedCustomShapeTextFrame aTextFrame;
176 3094 : sal_Int32 nLevel = 0;
177 3094 : bool bIgnore = false;
178 3094 : sal_Int32 nStart = 0;
179 1815481 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
180 : {
181 1812387 : if (rValue[i] == '{')
182 : {
183 30940 : if (!nLevel)
184 6188 : bIgnore = true;
185 30940 : nLevel++;
186 : }
187 1781447 : else if (rValue[i] == '}')
188 : {
189 30940 : nLevel--;
190 30940 : if (!nLevel)
191 6188 : bIgnore = false;
192 : }
193 1750507 : else if (rValue[i] == ',' && !bIgnore)
194 : {
195 3094 : OString aToken = rValue.copy(nStart, i - nStart);
196 : static const char aExpectedPrefix[] = "TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
197 3094 : if (aToken.startsWith(aExpectedPrefix))
198 : {
199 3094 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" }"));
200 3094 : aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken);
201 : }
202 : else
203 : SAL_WARN("oox", "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken);
204 3094 : nStart = i + strlen(", ");
205 : }
206 : }
207 :
208 6188 : OString aToken = rValue.copy(nStart, rValue.getLength() - nStart);
209 : static const char aExpectedPrefix[] = "BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
210 3094 : if (aToken.startsWith(aExpectedPrefix))
211 : {
212 3094 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" }"));
213 3094 : aTextFrame.BottomRight = lcl_parseEnhancedCustomShapeParameterPair(aToken);
214 : }
215 : else
216 : SAL_WARN("oox", "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken);
217 :
218 6188 : 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 4131 : void lcl_parseHandlePosition(std::vector<beans::PropertyValue>& rHandle, const OString& rValue)
224 : {
225 4131 : sal_Int32 nLevel = 0;
226 4131 : bool bIgnore = false;
227 4131 : sal_Int32 nStart = 0;
228 1627104 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
229 : {
230 1622973 : if (rValue[i] == '{')
231 : {
232 24786 : if (!nLevel)
233 4131 : bIgnore = true;
234 24786 : nLevel++;
235 : }
236 1598187 : else if (rValue[i] == '}')
237 : {
238 24786 : nLevel--;
239 24786 : if (!nLevel)
240 4131 : bIgnore = false;
241 : }
242 1573401 : else if (rValue[i] == ',' && !bIgnore)
243 : {
244 12393 : OString aToken = rValue.copy(nStart, i - nStart);
245 : static const char aExpectedPrefix[] = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
246 12393 : if (aToken.startsWith(aExpectedPrefix))
247 : {
248 4131 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }"));
249 :
250 4131 : beans::PropertyValue aPropertyValue;
251 4131 : aPropertyValue.Name = "Position";
252 4131 : aPropertyValue.Value = uno::makeAny(lcl_parseEnhancedCustomShapeParameterPair(aToken));
253 4131 : rHandle.push_back(aPropertyValue);
254 : }
255 8262 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
256 : SAL_WARN("oox", "lcl_parseHandlePosition: unexpected token: " << aToken);
257 12393 : nStart = i + strlen(", ");
258 : }
259 : }
260 4131 : }
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 9146 : void lcl_parseHandleRange(std::vector<beans::PropertyValue>& rHandle, const OString& rValue, const OUString& rName)
265 : {
266 9146 : sal_Int32 nLevel = 0;
267 9146 : bool bIgnore = false;
268 9146 : sal_Int32 nStart = 0;
269 2041377 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
270 : {
271 2032231 : if (rValue[i] == '{')
272 : {
273 27438 : if (!nLevel)
274 9146 : bIgnore = true;
275 27438 : nLevel++;
276 : }
277 2004793 : else if (rValue[i] == '}')
278 : {
279 27438 : nLevel--;
280 27438 : if (!nLevel)
281 9146 : bIgnore = false;
282 : }
283 1977355 : else if (rValue[i] == ',' && !bIgnore)
284 : {
285 27438 : OString aToken = rValue.copy(nStart, i - nStart);
286 : static const char aExpectedPrefix[] = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { ";
287 27438 : if (aToken.startsWith(aExpectedPrefix))
288 : {
289 9146 : drawing::EnhancedCustomShapeParameter aParameter;
290 9146 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }"));
291 : // We expect the followings here: Value and Type
292 : static const char aExpectedVPrefix[] = "Value = (any) { (long) ";
293 : assert(aToken.startsWith(aExpectedVPrefix));
294 9146 : sal_Int32 nIndex = strlen(aExpectedVPrefix);
295 9146 : aParameter.Value = uno::makeAny(aToken.getToken(0, '}', nIndex).toInt32());
296 :
297 : static const char aExpectedTPrefix[] = ", Type = (short) ";
298 9146 : aToken = aToken.copy(nIndex);
299 : assert(aToken.startsWith(aExpectedTPrefix));
300 9146 : nIndex = strlen(aExpectedTPrefix);
301 9146 : aParameter.Type = static_cast<sal_Int16>(aToken.getToken(0, '}', nIndex).toInt32());
302 :
303 18292 : beans::PropertyValue aPropertyValue;
304 9146 : aPropertyValue.Name = rName;
305 9146 : aPropertyValue.Value = uno::makeAny(aParameter);
306 18292 : rHandle.push_back(aPropertyValue);
307 :
308 : }
309 18292 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
310 : SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: " << aToken);
311 27438 : nStart = i + strlen(", ");
312 : }
313 : }
314 9146 : }
315 :
316 : // Parses a string like: Name = "RefY", Handle = (long) 0, Value = (any) { (long) 0 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
317 4420 : void lcl_parseHandleRef(std::vector<beans::PropertyValue>& rHandle, const OString& rValue, const OUString& rName)
318 : {
319 : static const char aExpectedXPrefix[] = "Name = \"RefX\", Handle = (long) 0, Value = (any) { (long) ";
320 : static const char aExpectedYPrefix[] = "Name = \"RefY\", Handle = (long) 0, Value = (any) { (long) ";
321 4420 : if (rValue.startsWith(aExpectedXPrefix) || rValue.startsWith(aExpectedYPrefix))
322 : {
323 4420 : sal_Int32 nIndex = strlen(aExpectedXPrefix);
324 4420 : beans::PropertyValue aPropertyValue;
325 4420 : aPropertyValue.Name = rName;
326 : // We only expect a Value here
327 4420 : aPropertyValue.Value = uno::makeAny(rValue.getToken(0, '}', nIndex).toInt32());
328 4420 : rHandle.push_back(aPropertyValue);
329 : }
330 : else
331 : SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue);
332 4420 : }
333 :
334 4131 : uno::Sequence<beans::PropertyValue> lcl_parseHandle(const OString& rValue)
335 : {
336 4131 : std::vector<beans::PropertyValue> aRet;
337 4131 : sal_Int32 nLevel = 0;
338 4131 : sal_Int32 nStart = 0;
339 4274395 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
340 : {
341 4270264 : if (rValue[i] == '{')
342 : {
343 74341 : if (!nLevel)
344 17697 : nStart = i;
345 74341 : nLevel++;
346 : }
347 4195923 : else if (rValue[i] == '}')
348 : {
349 74341 : nLevel--;
350 74341 : if (!nLevel)
351 : {
352 17697 : OString aToken = rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"));
353 17697 : if (aToken.startsWith("Name = \"Position\""))
354 4131 : lcl_parseHandlePosition(aRet, aToken);
355 13566 : else if (aToken.startsWith("Name = \"RangeXMaximum\""))
356 2244 : lcl_parseHandleRange(aRet, aToken, "RangeXMaximum");
357 11322 : else if (aToken.startsWith("Name = \"RangeXMinimum\""))
358 2244 : lcl_parseHandleRange(aRet, aToken, "RangeXMinimum");
359 9078 : else if (aToken.startsWith("Name = \"RangeYMaximum\""))
360 2176 : lcl_parseHandleRange(aRet, aToken, "RangeYMaximum");
361 6902 : else if (aToken.startsWith("Name = \"RangeYMinimum\""))
362 2176 : lcl_parseHandleRange(aRet, aToken, "RangeYMinimum");
363 4726 : else if (aToken.startsWith("Name = \"RadiusRangeMaximum\""))
364 153 : lcl_parseHandleRange(aRet, aToken, "RadiusRangeMaximum");
365 4573 : else if (aToken.startsWith("Name = \"RadiusRangeMinimum\""))
366 153 : lcl_parseHandleRange(aRet, aToken, "RadiusRangeMinimum");
367 4420 : else if (aToken.startsWith("Name = \"RefX\""))
368 2244 : lcl_parseHandleRef(aRet, aToken, "RefX");
369 2176 : else if (aToken.startsWith("Name = \"RefY\""))
370 2176 : lcl_parseHandleRef(aRet, aToken, "RefY");
371 : else
372 17697 : SAL_WARN("oox", "lcl_parseHandle: unexpected token: " << aToken);
373 : }
374 : }
375 : }
376 4131 : return comphelper::containerToSequence(aRet);
377 : }
378 :
379 2040 : void lcl_parseHandles(std::vector< uno::Sequence<beans::PropertyValue> >& rHandles, const OString& rValue)
380 : {
381 2040 : sal_Int32 nLevel = 0;
382 2040 : sal_Int32 nStart = 0;
383 4293010 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
384 : {
385 4290970 : if (rValue[i] == '{')
386 : {
387 78472 : if (!nLevel)
388 4131 : nStart = i;
389 78472 : nLevel++;
390 : }
391 4212498 : else if (rValue[i] == '}')
392 : {
393 78472 : nLevel--;
394 78472 : if (!nLevel)
395 : {
396 4131 : uno::Sequence<beans::PropertyValue> aHandle = lcl_parseHandle(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")));
397 4131 : rHandles.push_back(aHandle);
398 : }
399 : }
400 : }
401 2040 : }
402 :
403 3128 : void lcl_parseEquations(std::vector<OUString>& rEquations, const OString& rValue)
404 : {
405 3128 : bool bInString = false;
406 3128 : sal_Int32 nStart = 0;
407 1728288 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
408 : {
409 1725160 : if (rValue[i] == '"' && !bInString)
410 : {
411 89250 : nStart = i;
412 89250 : bInString = true;
413 : }
414 1635910 : else if (rValue[i] == '"' && bInString)
415 : {
416 89250 : bInString = false;
417 89250 : rEquations.push_back(OUString::fromUtf8(rValue.copy(nStart + strlen("\""), i - nStart - strlen("\""))));
418 : }
419 : }
420 3128 : }
421 :
422 3179 : void lcl_parsePathCoordinateValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
423 : {
424 3179 : std::vector<drawing::EnhancedCustomShapeParameterPair> aPairs;
425 3179 : sal_Int32 nLevel = 0;
426 3179 : sal_Int32 nStart = 0;
427 11845974 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
428 : {
429 11842795 : if (rValue[i] == '{')
430 : {
431 261545 : if (!nLevel)
432 52309 : nStart = i;
433 261545 : nLevel++;
434 : }
435 11581250 : else if (rValue[i] == '}')
436 : {
437 261545 : nLevel--;
438 261545 : if (!nLevel)
439 52309 : aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
440 : }
441 : }
442 :
443 6358 : beans::PropertyValue aPropertyValue;
444 3179 : aPropertyValue.Name = "Coordinates";
445 3179 : aPropertyValue.Value = uno::makeAny(comphelper::containerToSequence(aPairs));
446 6358 : rPath.push_back(aPropertyValue);
447 3179 : }
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 3179 : void lcl_parsePathCoordinates(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
452 : {
453 3179 : sal_Int32 nLevel = 0;
454 3179 : bool bIgnore = false;
455 3179 : sal_Int32 nStart = 0;
456 12411836 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
457 : {
458 12408657 : if (rValue[i] == '{')
459 : {
460 267903 : if (!nLevel)
461 3179 : bIgnore = true;
462 267903 : nLevel++;
463 : }
464 12140754 : else if (rValue[i] == '}')
465 : {
466 267903 : nLevel--;
467 267903 : if (!nLevel)
468 3179 : bIgnore = false;
469 : }
470 11872851 : else if (rValue[i] == ',' && !bIgnore)
471 : {
472 9537 : OString aToken = rValue.copy(nStart, i - nStart);
473 : static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
474 9537 : if (aToken.startsWith(aExpectedPrefix))
475 : {
476 3179 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }"));
477 3179 : lcl_parsePathCoordinateValues(rPath, aToken);
478 : }
479 6358 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
480 : SAL_WARN("oox", "lcl_parsePathCoordinates: unexpected token: " << aToken);
481 9537 : nStart = i + strlen(", ");
482 : }
483 : }
484 3179 : }
485 :
486 3179 : void lcl_parsePathSegmentValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
487 : {
488 3179 : std::vector<drawing::EnhancedCustomShapeSegment> aSegments;
489 3179 : sal_Int32 nLevel = 0;
490 3179 : sal_Int32 nStart = 0;
491 1626832 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
492 : {
493 1623653 : if (rValue[i] == '{')
494 : {
495 36890 : if (!nLevel)
496 36890 : nStart = i;
497 36890 : nLevel++;
498 : }
499 1586763 : else if (rValue[i] == '}')
500 : {
501 36890 : nLevel--;
502 36890 : if (!nLevel)
503 36890 : aSegments.push_back(lcl_parseEnhancedCustomShapeSegment(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
504 : }
505 : }
506 :
507 6358 : beans::PropertyValue aPropertyValue;
508 3179 : aPropertyValue.Name = "Segments";
509 3179 : aPropertyValue.Value = uno::makeAny(comphelper::containerToSequence(aSegments));
510 6358 : rPath.push_back(aPropertyValue);
511 3179 : }
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 3179 : void lcl_parsePathSegments(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
516 : {
517 3179 : sal_Int32 nLevel = 0;
518 3179 : bool bIgnore = false;
519 3179 : sal_Int32 nStart = 0;
520 2164083 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
521 : {
522 2160904 : if (rValue[i] == '{')
523 : {
524 43248 : if (!nLevel)
525 3179 : bIgnore = true;
526 43248 : nLevel++;
527 : }
528 2117656 : else if (rValue[i] == '}')
529 : {
530 43248 : nLevel--;
531 43248 : if (!nLevel)
532 3179 : bIgnore = false;
533 : }
534 2074408 : else if (rValue[i] == ',' && !bIgnore)
535 : {
536 9537 : OString aToken = rValue.copy(nStart, i - nStart);
537 : static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { ";
538 9537 : if (aToken.startsWith(aExpectedPrefix))
539 : {
540 3179 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }"));
541 3179 : lcl_parsePathSegmentValues(rPath, aToken);
542 : }
543 6358 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
544 : SAL_WARN("oox", "lcl_parsePathSegments: unexpected token: " << aToken);
545 9537 : nStart = i + strlen(", ");
546 : }
547 : }
548 3179 : }
549 :
550 3094 : void lcl_parsePathTextFrameValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
551 : {
552 3094 : std::vector<drawing::EnhancedCustomShapeTextFrame> aTextFrames;
553 3094 : sal_Int32 nLevel = 0;
554 3094 : sal_Int32 nStart = 0;
555 1827857 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
556 : {
557 1824763 : if (rValue[i] == '{')
558 : {
559 34034 : if (!nLevel)
560 3094 : nStart = i;
561 34034 : nLevel++;
562 : }
563 1790729 : else if (rValue[i] == '}')
564 : {
565 34034 : nLevel--;
566 34034 : if (!nLevel)
567 3094 : aTextFrames.push_back(lcl_parseEnhancedCustomShapeTextFrame(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
568 : }
569 : }
570 :
571 6188 : beans::PropertyValue aPropertyValue;
572 3094 : aPropertyValue.Name = "TextFrames";
573 3094 : aPropertyValue.Value = uno::makeAny(comphelper::containerToSequence(aTextFrames));
574 6188 : rPath.push_back(aPropertyValue);
575 3094 : }
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 3094 : void lcl_parsePathTextFrames(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
580 : {
581 3094 : sal_Int32 nLevel = 0;
582 3094 : bool bIgnore = false;
583 3094 : sal_Int32 nStart = 0;
584 2363119 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
585 : {
586 2360025 : if (rValue[i] == '{')
587 : {
588 40222 : if (!nLevel)
589 3094 : bIgnore = true;
590 40222 : nLevel++;
591 : }
592 2319803 : else if (rValue[i] == '}')
593 : {
594 40222 : nLevel--;
595 40222 : if (!nLevel)
596 3094 : bIgnore = false;
597 : }
598 2279581 : else if (rValue[i] == ',' && !bIgnore)
599 : {
600 9282 : OString aToken = rValue.copy(nStart, i - nStart);
601 : static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { ";
602 9282 : if (aToken.startsWith(aExpectedPrefix))
603 : {
604 3094 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }"));
605 3094 : lcl_parsePathTextFrameValues(rPath, aToken);
606 : }
607 6188 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
608 : SAL_WARN("oox", "lcl_parsePathTextFrames: unexpected token: " << aToken);
609 9282 : nStart = i + strlen(", ");
610 : }
611 : }
612 3094 : }
613 :
614 527 : void lcl_parsePathSubViewSizeValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
615 : {
616 527 : std::vector<awt::Size> aSizes;
617 527 : sal_Int32 nLevel = 0;
618 527 : sal_Int32 nStart = 0;
619 38352 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
620 : {
621 37825 : if (rValue[i] == '{')
622 : {
623 901 : if (!nLevel)
624 901 : nStart = i;
625 901 : nLevel++;
626 : }
627 36924 : else if (rValue[i] == '}')
628 : {
629 901 : nLevel--;
630 901 : if (!nLevel)
631 901 : aSizes.push_back(lcl_parseSize(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))));
632 : }
633 : }
634 :
635 1054 : beans::PropertyValue aPropertyValue;
636 527 : aPropertyValue.Name = "SubViewSize";
637 527 : aPropertyValue.Value = uno::makeAny(comphelper::containerToSequence(aSizes));
638 1054 : rPath.push_back(aPropertyValue);
639 527 : }
640 :
641 527 : void lcl_parsePathSubViewSize(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
642 : {
643 527 : sal_Int32 nLevel = 0;
644 527 : bool bIgnore = false;
645 527 : sal_Int32 nStart = 0;
646 115294 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
647 : {
648 114767 : if (rValue[i] == '{')
649 : {
650 1955 : if (!nLevel)
651 527 : bIgnore = true;
652 1955 : nLevel++;
653 : }
654 112812 : else if (rValue[i] == '}')
655 : {
656 1955 : nLevel--;
657 1955 : if (!nLevel)
658 527 : bIgnore = false;
659 : }
660 110857 : else if (rValue[i] == ',' && !bIgnore)
661 : {
662 1581 : OString aToken = rValue.copy(nStart, i - nStart);
663 : static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.awt.Size) { ";
664 1581 : if (aToken.startsWith(aExpectedPrefix))
665 : {
666 527 : aToken = aToken.copy(strlen(aExpectedPrefix), aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }"));
667 527 : lcl_parsePathSubViewSizeValues(rPath, aToken);
668 : }
669 1054 : else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
670 : SAL_WARN("oox", "lcl_parsePathSubViewSize: unexpected token: " << aToken);
671 1581 : nStart = i + strlen(", ");
672 : }
673 : }
674 527 : }
675 :
676 3179 : void lcl_parsePath(std::vector<beans::PropertyValue>& rPath, const OString& rValue)
677 : {
678 3179 : sal_Int32 nLevel = 0;
679 3179 : sal_Int32 nStart = 0;
680 17101048 : for (sal_Int32 i = 0; i < rValue.getLength(); ++i)
681 : {
682 17097869 : if (rValue[i] == '{')
683 : {
684 363307 : if (!nLevel)
685 9979 : nStart = i;
686 363307 : nLevel++;
687 : }
688 16734562 : else if (rValue[i] == '}')
689 : {
690 363307 : nLevel--;
691 363307 : if (!nLevel)
692 : {
693 9979 : OString aToken = rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"));
694 9979 : if (aToken.startsWith("Name = \"Coordinates\""))
695 3179 : lcl_parsePathCoordinates(rPath, aToken);
696 6800 : else if (aToken.startsWith("Name = \"Segments\""))
697 3179 : lcl_parsePathSegments(rPath, aToken);
698 3621 : else if (aToken.startsWith("Name = \"TextFrames\""))
699 3094 : lcl_parsePathTextFrames(rPath, aToken);
700 527 : else if (aToken.startsWith("Name = \"SubViewSize\""))
701 527 : lcl_parsePathSubViewSize(rPath, aToken);
702 : else
703 9979 : SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken);
704 : }
705 : }
706 : }
707 3179 : }
708 :
709 : }
710 :
711 : namespace oox
712 : {
713 : namespace drawingml
714 : {
715 :
716 17 : void CustomShapeProperties::initializePresetDataMap()
717 : {
718 17 : OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-cs-presets");
719 17 : rtl::Bootstrap::expandMacros(aPath);
720 34 : SvFileStream aStream(aPath, StreamMode::READ);
721 17 : if (aStream.GetError() != ERRCODE_NONE)
722 : SAL_WARN("oox", "failed to open oox-drawingml-cs-presets");
723 34 : OString aLine;
724 34 : OUString aName;
725 17 : bool bNotDone = aStream.ReadLine(aLine);
726 34 : PropertyMap aPropertyMap;
727 17 : bool bFirst = true;
728 28645 : while (bNotDone)
729 : {
730 : static const char aCommentPrefix[] = "/* ";
731 28611 : if (aLine.startsWith(aCommentPrefix))
732 : {
733 3179 : if (bFirst)
734 17 : bFirst = false;
735 : else
736 3162 : maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap;
737 3179 : aName = OUString::fromUtf8(aLine.copy(strlen(aCommentPrefix), aLine.getLength() - strlen(aCommentPrefix) - strlen(" */")));
738 : }
739 : else
740 : {
741 25432 : if (aLine == "AdjustmentValues")
742 : {
743 3179 : aStream.ReadLine(aLine);
744 3179 : if (aLine != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}")
745 : {
746 2091 : std::vector<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
747 4182 : OString aExpectedPrefix("([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { ");
748 : assert(aLine.startsWith(aExpectedPrefix));
749 :
750 4182 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
751 2091 : lcl_parseAdjustmentValues(aAdjustmentValues, aValue);
752 4182 : aPropertyMap.setProperty(PROP_AdjustmentValues, comphelper::containerToSequence(aAdjustmentValues));
753 : }
754 : else
755 1088 : aPropertyMap.setProperty(PROP_AdjustmentValues, uno::Sequence<OUString>(0));
756 : }
757 22253 : else if (aLine == "Equations")
758 : {
759 3179 : aStream.ReadLine(aLine);
760 3179 : if (aLine != "([]string) {}")
761 : {
762 3128 : std::vector<OUString> aEquations;
763 6256 : OString aExpectedPrefix("([]string) { ");
764 : assert(aLine.startsWith(aExpectedPrefix));
765 :
766 6256 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
767 3128 : lcl_parseEquations(aEquations, aValue);
768 6256 : aPropertyMap.setProperty(PROP_Equations, comphelper::containerToSequence(aEquations));
769 : }
770 : else
771 51 : aPropertyMap.setProperty(PROP_Equations, uno::Sequence<OUString>(0));
772 : }
773 19074 : else if (aLine == "Handles")
774 : {
775 3179 : aStream.ReadLine(aLine);
776 3179 : if (aLine != "([][]com.sun.star.beans.PropertyValue) {}")
777 : {
778 2040 : std::vector< uno::Sequence<beans::PropertyValue> > aHandles;
779 4080 : OString aExpectedPrefix("([][]com.sun.star.beans.PropertyValue) { ");
780 : assert(aLine.startsWith(aExpectedPrefix));
781 :
782 4080 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
783 2040 : lcl_parseHandles(aHandles, aValue);
784 4080 : aPropertyMap.setProperty(PROP_Handles, comphelper::containerToSequence(aHandles));
785 : }
786 : else
787 1139 : aPropertyMap.setProperty(PROP_Handles, uno::Sequence<OUString>(0));
788 : }
789 15895 : else if (aLine == "MirroredX")
790 : {
791 3179 : aStream.ReadLine(aLine);
792 3179 : if (aLine == "true" || aLine == "false")
793 : {
794 3179 : aPropertyMap.setProperty(PROP_MirroredX, aLine == "true");
795 : }
796 : else
797 : SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected MirroredX parameter");
798 : }
799 12716 : else if (aLine == "MirroredY")
800 : {
801 3179 : aStream.ReadLine(aLine);
802 3179 : if (aLine == "true" || aLine == "false")
803 : {
804 3179 : aPropertyMap.setProperty(PROP_MirroredY, aLine == "true");
805 : }
806 : else
807 : SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected MirroredY parameter");
808 : }
809 9537 : else if (aLine == "Path")
810 : {
811 3179 : aStream.ReadLine(aLine);
812 3179 : OString aExpectedPrefix("([]com.sun.star.beans.PropertyValue) { ");
813 : assert(aLine.startsWith(aExpectedPrefix));
814 :
815 6358 : std::vector<beans::PropertyValue> aPathValue;
816 6358 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
817 3179 : lcl_parsePath(aPathValue, aValue);
818 6358 : aPropertyMap.setProperty(PROP_Path, comphelper::containerToSequence(aPathValue));
819 : }
820 6358 : else if (aLine == "Type")
821 : {
822 : // Just ignore the line here, we already know the correct type.
823 3179 : aStream.ReadLine(aLine);
824 3179 : aPropertyMap.setProperty(PROP_Type, "ooxml-" + aName);
825 : }
826 3179 : else if (aLine == "ViewBox")
827 : {
828 3179 : aStream.ReadLine(aLine);
829 3179 : OString aExpectedPrefix("(com.sun.star.awt.Rectangle) { ");
830 : assert(aLine.startsWith(aExpectedPrefix));
831 :
832 6358 : OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
833 6358 : aPropertyMap.setProperty(PROP_ViewBox, lcl_parseRectangle(aValue));
834 : }
835 : else
836 : SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: " << aLine);
837 : }
838 28611 : bNotDone = aStream.ReadLine(aLine);
839 : }
840 34 : maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap;
841 17 : }
842 :
843 : }
844 246 : }
845 :
846 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|