cid#1640468 Dereference after null check
[LibreOffice.git] / oox / source / drawingml / customshapepresetdata.cxx
blobc2872cf1adccea1cc029b4dbb57bda220e63a1b5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <config_folders.h>
11 #include <rtl/bootstrap.hxx>
12 #include <sal/log.hxx>
13 #include <tools/stream.hxx>
14 #include <comphelper/sequence.hxx>
16 #include <drawingml/customshapeproperties.hxx>
17 #include <oox/token/properties.hxx>
18 #include <oox/token/tokenmap.hxx>
19 #include <com/sun/star/awt/Rectangle.hpp>
20 #include <com/sun/star/beans/PropertyValue.hpp>
21 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
22 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
23 #include <o3tl/string_view.hxx>
25 using namespace ::com::sun::star;
27 namespace
29 // Parses a string like: Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj"
30 void lcl_parseAdjustmentValue(
31 std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues,
32 std::string_view rValue)
34 sal_Int32 nIndex = 0;
35 drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue;
38 std::string_view aToken(o3tl::trim(o3tl::getToken(rValue, 0, ',', nIndex)));
39 static const char aNamePrefix[] = "Name = \"";
40 static const char aValuePrefix[] = "Value = (any) { (long) ";
41 if (o3tl::starts_with(aToken, aNamePrefix))
43 std::string_view aName = aToken.substr(
44 strlen(aNamePrefix), aToken.size() - strlen(aNamePrefix) - strlen("\""));
45 aAdjustmentValue.Name = OUString::fromUtf8(aName);
47 else if (o3tl::starts_with(aToken, aValuePrefix))
49 std::string_view aValue = aToken.substr(
50 strlen(aValuePrefix), aToken.size() - strlen(aValuePrefix) - strlen(" }"));
51 aAdjustmentValue.Value <<= o3tl::toInt32(aValue);
53 else if (!o3tl::starts_with(aToken, "State = "))
54 SAL_WARN("oox", "lcl_parseAdjustmentValue: unexpected prefix: " << aToken);
55 } while (nIndex >= 0);
56 rAdjustmentValues.push_back(aAdjustmentValue);
59 // Parses a string like: { Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj" }, { Value = ..., State = ..., Name = ... }
60 void lcl_parseAdjustmentValues(
61 std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues,
62 std::string_view rValue)
64 sal_Int32 nLevel = 0;
65 sal_Int32 nStart = 0;
66 for (size_t i = 0; i < rValue.size(); ++i)
68 if (rValue[i] == '{')
70 if (!nLevel)
71 nStart = i;
72 nLevel++;
74 else if (rValue[i] == '}')
76 nLevel--;
77 if (!nLevel)
79 lcl_parseAdjustmentValue(
80 rAdjustmentValues,
81 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")));
87 drawing::EnhancedCustomShapeParameterPair
88 lcl_parseEnhancedCustomShapeParameterPair(std::string_view rValue)
90 drawing::EnhancedCustomShapeParameterPair aPair;
91 // We expect the following here: First.Value, First.Type, Second.Value, Second.Type
92 static const char aExpectedFVPrefix[]
93 = "First = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
94 assert(o3tl::starts_with(rValue, aExpectedFVPrefix));
95 sal_Int32 nIndex = strlen(aExpectedFVPrefix);
96 aPair.First.Value
97 <<= static_cast<sal_uInt32>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
99 static const char aExpectedFTPrefix[] = ", Type = (short) ";
100 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedFTPrefix));
101 nIndex += strlen(aExpectedFTPrefix);
102 aPair.First.Type
103 = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
105 static const char aExpectedSVPrefix[] = ", Second = "
106 "(com.sun.star.drawing.EnhancedCustomShapeParameter) { "
107 "Value = (any) { (long) ";
108 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedSVPrefix));
109 nIndex += strlen(aExpectedSVPrefix);
110 aPair.Second.Value
111 <<= static_cast<sal_uInt32>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
113 static const char aExpectedSTPrefix[] = ", Type = (short) ";
114 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedSTPrefix));
115 nIndex += strlen(aExpectedSTPrefix);
116 aPair.Second.Type
117 = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
118 return aPair;
121 drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(std::string_view rValue)
123 drawing::EnhancedCustomShapeSegment aSegment;
124 // We expect the following here: Command, Count
125 static const char aExpectedCommandPrefix[] = "Command = (short) ";
126 assert(o3tl::starts_with(rValue, aExpectedCommandPrefix));
127 sal_Int32 nIndex = strlen(aExpectedCommandPrefix);
128 aSegment.Command
129 = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex)));
131 static const char aExpectedCountPrefix[] = " Count = (short) ";
132 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedCountPrefix));
133 nIndex += strlen(aExpectedCountPrefix);
134 aSegment.Count = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
135 return aSegment;
138 awt::Rectangle lcl_parseRectangle(std::string_view rValue)
140 awt::Rectangle aRectangle;
141 // We expect the following here: X, Y, Width, Height
142 static const char aExpectedXPrefix[] = "X = (long) ";
143 assert(o3tl::starts_with(rValue, aExpectedXPrefix));
144 sal_Int32 nIndex = strlen(aExpectedXPrefix);
145 aRectangle.X = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex));
147 static const char aExpectedYPrefix[] = " Y = (long) ";
148 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedYPrefix));
149 nIndex += strlen(aExpectedYPrefix);
150 aRectangle.Y = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex));
152 static const char aExpectedWidthPrefix[] = " Width = (long) ";
153 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedWidthPrefix));
154 nIndex += strlen(aExpectedWidthPrefix);
155 aRectangle.Width = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex));
157 static const char aExpectedHeightPrefix[] = " Height = (long) ";
158 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedHeightPrefix));
159 nIndex += strlen(aExpectedHeightPrefix);
160 aRectangle.Height = o3tl::toInt32(rValue.substr(nIndex));
162 return aRectangle;
165 sal_Int32 lcl_parseDirection(std::string_view rValue)
167 sal_Int32 aDirection;
168 // We expect the following here: Direction
169 static const char aExpectedWidthPrefix[] = "Dir = (long) ";
170 assert(o3tl::starts_with(rValue, aExpectedWidthPrefix));
171 sal_Int32 nIndex = strlen(aExpectedWidthPrefix);
172 aDirection = o3tl::toInt32(rValue.substr(nIndex));
174 return aDirection;
177 awt::Size lcl_parseSize(std::string_view rValue)
179 awt::Size aSize;
180 // We expect the following here: Width, Height
181 static const char aExpectedWidthPrefix[] = "Width = (long) ";
182 assert(o3tl::starts_with(rValue, aExpectedWidthPrefix));
183 sal_Int32 nIndex = strlen(aExpectedWidthPrefix);
184 aSize.Width = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex));
186 static const char aExpectedHeightPrefix[] = " Height = (long) ";
187 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedHeightPrefix));
188 nIndex += strlen(aExpectedHeightPrefix);
189 aSize.Height = o3tl::toInt32(rValue.substr(nIndex));
191 return aSize;
194 drawing::EnhancedCustomShapeTextFrame lcl_parseEnhancedCustomShapeTextFrame(std::string_view rValue)
196 drawing::EnhancedCustomShapeTextFrame aTextFrame;
197 sal_Int32 nLevel = 0;
198 bool bIgnore = false;
199 sal_Int32 nStart = 0;
200 for (size_t i = 0; i < rValue.size(); ++i)
202 if (rValue[i] == '{')
204 if (!nLevel)
205 bIgnore = true;
206 nLevel++;
208 else if (rValue[i] == '}')
210 nLevel--;
211 if (!nLevel)
212 bIgnore = false;
214 else if (rValue[i] == ',' && !bIgnore)
216 std::string_view aToken = rValue.substr(nStart, i - nStart);
217 static const char aExpectedPrefix[]
218 = "TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
219 if (o3tl::starts_with(aToken, aExpectedPrefix))
221 aToken = aToken.substr(strlen(aExpectedPrefix),
222 aToken.size() - strlen(aExpectedPrefix) - strlen(" }"));
223 aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken);
225 else
226 SAL_WARN("oox",
227 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken);
228 nStart = i + strlen(", ");
232 std::string_view aToken = rValue.substr(nStart);
233 static const char aExpectedPrefix[]
234 = "BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
235 if (o3tl::starts_with(aToken, aExpectedPrefix))
237 aToken = aToken.substr(strlen(aExpectedPrefix),
238 aToken.size() - strlen(aExpectedPrefix) - strlen(" }"));
239 aTextFrame.BottomRight = lcl_parseEnhancedCustomShapeParameterPair(aToken);
241 else
242 SAL_WARN("oox",
243 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken);
245 return aTextFrame;
248 // Parses a string like: Name = "Position", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
249 // where "{ ... }" may contain "," as well.
250 void lcl_parseHandlePosition(std::vector<beans::PropertyValue>& rHandle, std::string_view rValue)
252 sal_Int32 nLevel = 0;
253 bool bIgnore = false;
254 sal_Int32 nStart = 0;
255 for (size_t i = 0; i < rValue.size(); ++i)
257 if (rValue[i] == '{')
259 if (!nLevel)
260 bIgnore = true;
261 nLevel++;
263 else if (rValue[i] == '}')
265 nLevel--;
266 if (!nLevel)
267 bIgnore = false;
269 else if (rValue[i] == ',' && !bIgnore)
271 std::string_view aToken = rValue.substr(nStart, i - nStart);
272 static const char aExpectedPrefix[]
273 = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
274 if (o3tl::starts_with(aToken, aExpectedPrefix))
276 aToken = aToken.substr(strlen(aExpectedPrefix),
277 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
279 beans::PropertyValue aPropertyValue;
280 aPropertyValue.Name = "Position";
281 aPropertyValue.Value <<= lcl_parseEnhancedCustomShapeParameterPair(aToken);
282 rHandle.push_back(aPropertyValue);
284 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
285 SAL_WARN("oox", "lcl_parseHandlePosition: unexpected token: " << aToken);
286 nStart = i + strlen(", ");
291 // Parses a string like: Name = "RangeYMaximum", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
292 // where "{ ... }" may contain "," as well.
293 void lcl_parseHandleRange(std::vector<beans::PropertyValue>& rHandle, std::string_view rValue,
294 const OUString& rName)
296 sal_Int32 nLevel = 0;
297 bool bIgnore = false;
298 sal_Int32 nStart = 0;
299 for (size_t i = 0; i < rValue.size(); ++i)
301 if (rValue[i] == '{')
303 if (!nLevel)
304 bIgnore = true;
305 nLevel++;
307 else if (rValue[i] == '}')
309 nLevel--;
310 if (!nLevel)
311 bIgnore = false;
313 else if (rValue[i] == ',' && !bIgnore)
315 static const char aExpectedPrefix[]
316 = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { ";
317 if (o3tl::starts_with(rValue.substr(nStart), aExpectedPrefix))
319 drawing::EnhancedCustomShapeParameter aParameter;
320 sal_Int32 nIndex{ nStart + static_cast<sal_Int32>(strlen(aExpectedPrefix)) };
321 // We expect the following here: Value and Type
322 static const char aExpectedVPrefix[] = "Value = (any) { (long) ";
323 assert(o3tl::starts_with(rValue.substr(nIndex), aExpectedVPrefix));
324 nIndex += strlen(aExpectedVPrefix);
325 aParameter.Value <<= o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex));
327 static const char aExpectedTPrefix[] = ", Type = (short) ";
328 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedTPrefix));
329 nIndex += strlen(aExpectedTPrefix);
330 aParameter.Type
331 = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
333 beans::PropertyValue aPropertyValue;
334 aPropertyValue.Name = rName;
335 aPropertyValue.Value <<= aParameter;
336 rHandle.push_back(aPropertyValue);
338 else if (!o3tl::starts_with(rValue.substr(nStart), "Name =")
339 && !o3tl::starts_with(rValue.substr(nStart), "Handle ="))
340 SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: "
341 << rValue.substr(nStart, i - nStart));
342 nStart = i + strlen(", ");
347 // Parses a string like: Name = "RefY", Handle = (long) 0, Value = (any) { (long) 0 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
348 void lcl_parseHandleRef(std::vector<beans::PropertyValue>& rHandle, std::string_view rValue,
349 const OUString& rName)
351 static constexpr std::string_view aPrefix = "\", Handle = (long) 0, Value = (any) { (long) ";
352 const sal_Int32 nStart = SAL_N_ELEMENTS("Name = \"") - 1 + rName.getLength();
354 if (rValue.substr(nStart, aPrefix.size()) == aPrefix)
356 sal_Int32 nIndex = nStart + aPrefix.size();
357 beans::PropertyValue aPropertyValue;
358 aPropertyValue.Name = rName;
359 // We only expect a Value here
360 aPropertyValue.Value <<= o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex));
361 rHandle.push_back(aPropertyValue);
363 else
364 SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue);
367 uno::Sequence<beans::PropertyValue> lcl_parseHandle(std::string_view rValue)
369 std::vector<beans::PropertyValue> aRet;
370 sal_Int32 nLevel = 0;
371 sal_Int32 nStart = 0;
372 for (size_t i = 0; i < rValue.size(); ++i)
374 if (rValue[i] == '{')
376 if (!nLevel)
377 nStart = i;
378 nLevel++;
380 else if (rValue[i] == '}')
382 nLevel--;
383 if (!nLevel)
385 std::string_view aToken
386 = rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"));
387 if (o3tl::starts_with(aToken, "Name = \"Position\""))
388 lcl_parseHandlePosition(aRet, aToken);
389 else if (o3tl::starts_with(aToken, "Name = \"RangeXMaximum\""))
390 lcl_parseHandleRange(aRet, aToken, u"RangeXMaximum"_ustr);
391 else if (o3tl::starts_with(aToken, "Name = \"RangeXMinimum\""))
392 lcl_parseHandleRange(aRet, aToken, u"RangeXMinimum"_ustr);
393 else if (o3tl::starts_with(aToken, "Name = \"RangeYMaximum\""))
394 lcl_parseHandleRange(aRet, aToken, u"RangeYMaximum"_ustr);
395 else if (o3tl::starts_with(aToken, "Name = \"RangeYMinimum\""))
396 lcl_parseHandleRange(aRet, aToken, u"RangeYMinimum"_ustr);
397 else if (o3tl::starts_with(aToken, "Name = \"RadiusRangeMaximum\""))
398 lcl_parseHandleRange(aRet, aToken, u"RadiusRangeMaximum"_ustr);
399 else if (o3tl::starts_with(aToken, "Name = \"RadiusRangeMinimum\""))
400 lcl_parseHandleRange(aRet, aToken, u"RadiusRangeMinimum"_ustr);
401 else if (o3tl::starts_with(aToken, "Name = \"RefX\""))
402 lcl_parseHandleRef(aRet, aToken, u"RefX"_ustr);
403 else if (o3tl::starts_with(aToken, "Name = \"RefY\""))
404 lcl_parseHandleRef(aRet, aToken, u"RefY"_ustr);
405 else if (o3tl::starts_with(aToken, "Name = \"RefR\""))
406 lcl_parseHandleRef(aRet, aToken, u"RefR"_ustr);
407 else if (o3tl::starts_with(aToken, "Name = \"RefAngle\""))
408 lcl_parseHandleRef(aRet, aToken, u"RefAngle"_ustr);
409 else
410 SAL_WARN("oox", "lcl_parseHandle: unexpected token: " << aToken);
414 return comphelper::containerToSequence(aRet);
417 void lcl_parseHandles(std::vector<uno::Sequence<beans::PropertyValue>>& rHandles,
418 std::string_view rValue)
420 sal_Int32 nLevel = 0;
421 sal_Int32 nStart = 0;
422 for (size_t i = 0; i < rValue.size(); ++i)
424 if (rValue[i] == '{')
426 if (!nLevel)
427 nStart = i;
428 nLevel++;
430 else if (rValue[i] == '}')
432 nLevel--;
433 if (!nLevel)
435 uno::Sequence<beans::PropertyValue> aHandle = lcl_parseHandle(
436 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")));
437 rHandles.push_back(aHandle);
443 void lcl_parseEquations(std::vector<OUString>& rEquations, std::string_view rValue)
445 bool bInString = false;
446 sal_Int32 nStart = 0;
447 for (size_t i = 0; i < rValue.size(); ++i)
449 if (rValue[i] == '"' && !bInString)
451 nStart = i;
452 bInString = true;
454 else if (rValue[i] == '"' && bInString)
456 bInString = false;
457 rEquations.push_back(OUString::fromUtf8(
458 rValue.substr(nStart + strlen("\""), i - nStart - strlen("\""))));
463 void lcl_parsePathCoordinateValues(std::vector<beans::PropertyValue>& rPath,
464 std::string_view rValue)
466 std::vector<drawing::EnhancedCustomShapeParameterPair> aPairs;
467 sal_Int32 nLevel = 0;
468 sal_Int32 nStart = 0;
469 for (size_t i = 0; i < rValue.size(); ++i)
471 if (rValue[i] == '{')
473 if (!nLevel)
474 nStart = i;
475 nLevel++;
477 else if (rValue[i] == '}')
479 nLevel--;
480 if (!nLevel)
481 aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair(
482 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
486 beans::PropertyValue aPropertyValue;
487 aPropertyValue.Name = "Coordinates";
488 aPropertyValue.Value <<= comphelper::containerToSequence(aPairs);
489 rPath.push_back(aPropertyValue);
492 // Parses a string like: Name = "Coordinates", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
493 // where "{ ... }" may contain "," as well.
494 void lcl_parsePathCoordinates(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
496 sal_Int32 nLevel = 0;
497 bool bIgnore = false;
498 sal_Int32 nStart = 0;
499 for (size_t i = 0; i < rValue.size(); ++i)
501 if (rValue[i] == '{')
503 if (!nLevel)
504 bIgnore = true;
505 nLevel++;
507 else if (rValue[i] == '}')
509 nLevel--;
510 if (!nLevel)
511 bIgnore = false;
513 else if (rValue[i] == ',' && !bIgnore)
515 std::string_view aToken = rValue.substr(nStart, i - nStart);
516 static const char aExpectedPrefix[]
517 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
518 if (o3tl::starts_with(aToken, aExpectedPrefix))
520 aToken = aToken.substr(strlen(aExpectedPrefix),
521 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
522 lcl_parsePathCoordinateValues(rPath, aToken);
524 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
525 SAL_WARN("oox", "lcl_parsePathCoordinates: unexpected token: " << aToken);
526 nStart = i + strlen(", ");
531 void lcl_parsePathGluePointsValues(std::vector<beans::PropertyValue>& rPath,
532 std::string_view rValue)
534 std::vector<drawing::EnhancedCustomShapeParameterPair> aPairs;
535 sal_Int32 nLevel = 0;
536 sal_Int32 nStart = 0;
537 for (size_t i = 0; i < rValue.size(); ++i)
539 if (rValue[i] == '{')
541 if (!nLevel)
542 nStart = i;
543 nLevel++;
545 else if (rValue[i] == '}')
547 nLevel--;
548 if (!nLevel)
549 aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair(
550 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
554 beans::PropertyValue aPropertyValue;
555 aPropertyValue.Name = "GluePoints";
556 aPropertyValue.Value <<= comphelper::containerToSequence(aPairs);
557 rPath.push_back(aPropertyValue);
560 void lcl_parsePathGluePoints(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
562 sal_Int32 nLevel = 0;
563 bool bIgnore = false;
564 sal_Int32 nStart = 0;
565 for (size_t i = 0; i < rValue.size(); ++i)
567 if (rValue[i] == '{')
569 if (!nLevel)
570 bIgnore = true;
571 nLevel++;
573 else if (rValue[i] == '}')
575 nLevel--;
576 if (!nLevel)
577 bIgnore = false;
579 else if (rValue[i] == ',' && !bIgnore)
581 std::string_view aToken = rValue.substr(nStart, i - nStart);
582 static const char aExpectedPrefix[]
583 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
584 if (o3tl::starts_with(aToken, aExpectedPrefix))
586 aToken = aToken.substr(strlen(aExpectedPrefix),
587 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
588 lcl_parsePathGluePointsValues(rPath, aToken);
590 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
591 SAL_WARN("oox", "lcl_parsePathGluePoints: unexpected token: " << aToken);
592 nStart = i + strlen(", ");
597 void lcl_parsePathGluePointLeavingDirectionsValues(std::vector<beans::PropertyValue>& rPath,
598 std::string_view rValue)
600 std::vector<double> aDirection;
601 sal_Int32 nLevel = 0;
602 sal_Int32 nStart = 0;
603 for (size_t i = 0; i < rValue.size(); ++i)
605 if (rValue[i] == '{')
607 if (!nLevel)
608 nStart = i;
609 nLevel++;
611 else if (rValue[i] == '}')
613 nLevel--;
614 if (!nLevel)
615 aDirection.push_back(lcl_parseDirection(
616 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
620 beans::PropertyValue aPropertyValue;
621 aPropertyValue.Name = "GluePointLeavingDirections";
622 aPropertyValue.Value <<= comphelper::containerToSequence(aDirection);
623 rPath.push_back(aPropertyValue);
626 void lcl_parsePathGluePointLeavingDirections(std::vector<beans::PropertyValue>& rPath,
627 std::string_view rValue)
629 sal_Int32 nLevel = 0;
630 bool bIgnore = false;
631 sal_Int32 nStart = 0;
632 for (size_t i = 0; i < rValue.size(); ++i)
634 if (rValue[i] == '{')
636 if (!nLevel)
637 bIgnore = true;
638 nLevel++;
640 else if (rValue[i] == '}')
642 nLevel--;
643 if (!nLevel)
644 bIgnore = false;
646 else if (rValue[i] == ',' && !bIgnore)
648 std::string_view aToken = rValue.substr(nStart, i - nStart);
649 static const char aExpectedPrefix[] = "Value = (any) { ([]long) { ";
650 if (o3tl::starts_with(aToken, aExpectedPrefix))
652 aToken = aToken.substr(strlen(aExpectedPrefix),
653 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
654 lcl_parsePathGluePointLeavingDirectionsValues(rPath, aToken);
656 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
657 SAL_WARN("oox",
658 "lcl_parsePathGluePointLeavingDirections: unexpected token: " << aToken);
659 nStart = i + strlen(", ");
664 void lcl_parsePathSegmentValues(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
666 std::vector<drawing::EnhancedCustomShapeSegment> aSegments;
667 sal_Int32 nLevel = 0;
668 sal_Int32 nStart = 0;
669 for (size_t i = 0; i < rValue.size(); ++i)
671 if (rValue[i] == '{')
673 if (!nLevel)
674 nStart = i;
675 nLevel++;
677 else if (rValue[i] == '}')
679 nLevel--;
680 if (!nLevel)
681 aSegments.push_back(lcl_parseEnhancedCustomShapeSegment(
682 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
686 beans::PropertyValue aPropertyValue;
687 aPropertyValue.Name = "Segments";
688 aPropertyValue.Value <<= comphelper::containerToSequence(aSegments);
689 rPath.push_back(aPropertyValue);
692 // Parses a string like: Name = "Segments", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
693 // where "{ ... }" may contain "," as well.
694 void lcl_parsePathSegments(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
696 sal_Int32 nLevel = 0;
697 bool bIgnore = false;
698 sal_Int32 nStart = 0;
699 for (size_t i = 0; i < rValue.size(); ++i)
701 if (rValue[i] == '{')
703 if (!nLevel)
704 bIgnore = true;
705 nLevel++;
707 else if (rValue[i] == '}')
709 nLevel--;
710 if (!nLevel)
711 bIgnore = false;
713 else if (rValue[i] == ',' && !bIgnore)
715 std::string_view aToken = rValue.substr(nStart, i - nStart);
716 static const char aExpectedPrefix[]
717 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { ";
718 if (o3tl::starts_with(aToken, aExpectedPrefix))
720 aToken = aToken.substr(strlen(aExpectedPrefix),
721 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
722 lcl_parsePathSegmentValues(rPath, aToken);
724 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
725 SAL_WARN("oox", "lcl_parsePathSegments: unexpected token: " << aToken);
726 nStart = i + strlen(", ");
731 void lcl_parsePathTextFrameValues(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
733 std::vector<drawing::EnhancedCustomShapeTextFrame> aTextFrames;
734 sal_Int32 nLevel = 0;
735 sal_Int32 nStart = 0;
736 for (size_t i = 0; i < rValue.size(); ++i)
738 if (rValue[i] == '{')
740 if (!nLevel)
741 nStart = i;
742 nLevel++;
744 else if (rValue[i] == '}')
746 nLevel--;
747 if (!nLevel)
748 aTextFrames.push_back(lcl_parseEnhancedCustomShapeTextFrame(
749 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
753 beans::PropertyValue aPropertyValue;
754 aPropertyValue.Name = "TextFrames";
755 aPropertyValue.Value <<= comphelper::containerToSequence(aTextFrames);
756 rPath.push_back(aPropertyValue);
759 // Parses a string like: Name = "TextFrames", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
760 // where "{ ... }" may contain "," as well.
761 void lcl_parsePathTextFrames(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
763 sal_Int32 nLevel = 0;
764 bool bIgnore = false;
765 sal_Int32 nStart = 0;
766 for (size_t i = 0; i < rValue.size(); ++i)
768 if (rValue[i] == '{')
770 if (!nLevel)
771 bIgnore = true;
772 nLevel++;
774 else if (rValue[i] == '}')
776 nLevel--;
777 if (!nLevel)
778 bIgnore = false;
780 else if (rValue[i] == ',' && !bIgnore)
782 std::string_view aToken = rValue.substr(nStart, i - nStart);
783 static const char aExpectedPrefix[]
784 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { ";
785 if (o3tl::starts_with(aToken, aExpectedPrefix))
787 aToken = aToken.substr(strlen(aExpectedPrefix),
788 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
789 lcl_parsePathTextFrameValues(rPath, aToken);
791 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
792 SAL_WARN("oox", "lcl_parsePathTextFrames: unexpected token: " << aToken);
793 nStart = i + strlen(", ");
798 void lcl_parsePathSubViewSizeValues(std::vector<beans::PropertyValue>& rPath,
799 std::string_view rValue)
801 std::vector<awt::Size> aSizes;
802 sal_Int32 nLevel = 0;
803 sal_Int32 nStart = 0;
804 for (size_t i = 0; i < rValue.size(); ++i)
806 if (rValue[i] == '{')
808 if (!nLevel)
809 nStart = i;
810 nLevel++;
812 else if (rValue[i] == '}')
814 nLevel--;
815 if (!nLevel)
816 aSizes.push_back(lcl_parseSize(
817 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
821 beans::PropertyValue aPropertyValue;
822 aPropertyValue.Name = "SubViewSize";
823 aPropertyValue.Value <<= comphelper::containerToSequence(aSizes);
824 rPath.push_back(aPropertyValue);
827 void lcl_parsePathSubViewSize(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
829 sal_Int32 nLevel = 0;
830 bool bIgnore = false;
831 sal_Int32 nStart = 0;
832 for (size_t i = 0; i < rValue.size(); ++i)
834 if (rValue[i] == '{')
836 if (!nLevel)
837 bIgnore = true;
838 nLevel++;
840 else if (rValue[i] == '}')
842 nLevel--;
843 if (!nLevel)
844 bIgnore = false;
846 else if (rValue[i] == ',' && !bIgnore)
848 std::string_view aToken = rValue.substr(nStart, i - nStart);
849 static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.awt.Size) { ";
850 if (o3tl::starts_with(aToken, aExpectedPrefix))
852 aToken = aToken.substr(strlen(aExpectedPrefix),
853 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
854 lcl_parsePathSubViewSizeValues(rPath, aToken);
856 else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle ="))
857 SAL_WARN("oox", "lcl_parsePathSubViewSize: unexpected token: " << aToken);
858 nStart = i + strlen(", ");
863 void lcl_parsePath(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
865 sal_Int32 nLevel = 0;
866 sal_Int32 nStart = 0;
867 for (size_t i = 0; i < rValue.size(); ++i)
869 if (rValue[i] == '{')
871 if (!nLevel)
872 nStart = i;
873 nLevel++;
875 else if (rValue[i] == '}')
877 nLevel--;
878 if (!nLevel)
880 std::string_view aToken
881 = rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"));
882 if (o3tl::starts_with(aToken, "Name = \"Coordinates\""))
883 lcl_parsePathCoordinates(rPath, aToken);
884 else if (o3tl::starts_with(aToken, "Name = \"GluePoints\""))
885 lcl_parsePathGluePoints(rPath, aToken);
886 else if (o3tl::starts_with(aToken, "Name = \"GluePointLeavingDirections\""))
887 lcl_parsePathGluePointLeavingDirections(rPath, aToken);
888 else if (o3tl::starts_with(aToken, "Name = \"Segments\""))
889 lcl_parsePathSegments(rPath, aToken);
890 else if (o3tl::starts_with(aToken, "Name = \"TextFrames\""))
891 lcl_parsePathTextFrames(rPath, aToken);
892 else if (o3tl::starts_with(aToken, "Name = \"SubViewSize\""))
893 lcl_parsePathSubViewSize(rPath, aToken);
894 else
895 SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken);
902 namespace oox::drawingml
904 void CustomShapeProperties::initializePresetDataMap()
906 OUString aPath(u"$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-cs-presets"_ustr);
907 rtl::Bootstrap::expandMacros(aPath);
908 SvFileStream aStream(aPath, StreamMode::READ);
909 if (aStream.GetError() != ERRCODE_NONE)
910 SAL_WARN("oox", "failed to open oox-drawingml-cs-presets");
911 OStringBuffer aLine;
912 OUString aName;
913 bool bNotDone = aStream.ReadLine(aLine);
914 PropertyMap aPropertyMap;
915 bool bFirst = true;
916 while (bNotDone)
918 static const char aCommentPrefix[] = "/* ";
919 if (o3tl::starts_with(aLine, aCommentPrefix))
921 if (bFirst)
922 bFirst = false;
923 else
924 maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap;
925 aName = OUString::fromUtf8(std::string_view(aLine).substr(
926 strlen(aCommentPrefix),
927 aLine.getLength() - strlen(aCommentPrefix) - strlen(" */")));
929 else
931 if (std::string_view(aLine) == "AdjustmentValues")
933 aStream.ReadLine(aLine);
934 if (std::string_view(aLine)
935 != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}")
937 std::vector<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
938 static constexpr std::string_view aExpectedPrefix(
939 "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { ");
940 assert(o3tl::starts_with(aLine, aExpectedPrefix));
942 std::string_view aValue = std::string_view(aLine).substr(
943 aExpectedPrefix.size(),
944 aLine.getLength() - aExpectedPrefix.size() - strlen(" }"));
945 lcl_parseAdjustmentValues(aAdjustmentValues, aValue);
946 aPropertyMap.setProperty(PROP_AdjustmentValues,
947 comphelper::containerToSequence(aAdjustmentValues));
949 else
950 aPropertyMap.setProperty(PROP_AdjustmentValues, uno::Sequence<OUString>(0));
952 else if (std::string_view(aLine) == "Equations")
954 aStream.ReadLine(aLine);
955 if (std::string_view(aLine) != "([]string) {}")
957 std::vector<OUString> aEquations;
958 static constexpr std::string_view aExpectedPrefix("([]string) { ");
959 assert(o3tl::starts_with(aLine, aExpectedPrefix));
961 std::string_view aValue = std::string_view(aLine).substr(
962 aExpectedPrefix.size(),
963 aLine.getLength() - aExpectedPrefix.size() - strlen(" }"));
964 lcl_parseEquations(aEquations, aValue);
965 aPropertyMap.setProperty(PROP_Equations,
966 comphelper::containerToSequence(aEquations));
968 else
969 aPropertyMap.setProperty(PROP_Equations, uno::Sequence<OUString>(0));
971 else if (std::string_view(aLine) == "Handles")
973 aStream.ReadLine(aLine);
974 if (std::string_view(aLine) != "([][]com.sun.star.beans.PropertyValue) {}")
976 std::vector<uno::Sequence<beans::PropertyValue>> aHandles;
977 static constexpr std::string_view aExpectedPrefix(
978 "([][]com.sun.star.beans.PropertyValue) { ");
979 assert(o3tl::starts_with(aLine, aExpectedPrefix));
981 std::string_view aValue = std::string_view(aLine).substr(
982 aExpectedPrefix.size(),
983 aLine.getLength() - aExpectedPrefix.size() - strlen(" }"));
984 lcl_parseHandles(aHandles, aValue);
985 aPropertyMap.setProperty(PROP_Handles,
986 comphelper::containerToSequence(aHandles));
988 else
989 aPropertyMap.setProperty(PROP_Handles, uno::Sequence<OUString>(0));
991 else if (std::string_view(aLine) == "MirroredX")
993 aStream.ReadLine(aLine);
994 if (std::string_view(aLine) == "true" || std::string_view(aLine) == "false")
996 aPropertyMap.setProperty(PROP_MirroredX, std::string_view(aLine) == "true");
998 else
999 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected "
1000 "MirroredX parameter");
1002 else if (std::string_view(aLine) == "MirroredY")
1004 aStream.ReadLine(aLine);
1005 if (std::string_view(aLine) == "true" || std::string_view(aLine) == "false")
1007 aPropertyMap.setProperty(PROP_MirroredY, std::string_view(aLine) == "true");
1009 else
1010 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected "
1011 "MirroredY parameter");
1013 else if (std::string_view(aLine) == "Path")
1015 aStream.ReadLine(aLine);
1016 static constexpr std::string_view aExpectedPrefix(
1017 "([]com.sun.star.beans.PropertyValue) { ");
1018 assert(o3tl::starts_with(aLine, aExpectedPrefix));
1020 std::vector<beans::PropertyValue> aPathValue;
1021 std::string_view aValue = std::string_view(aLine).substr(
1022 aExpectedPrefix.size(),
1023 aLine.getLength() - aExpectedPrefix.size() - strlen(" }"));
1024 lcl_parsePath(aPathValue, aValue);
1025 aPropertyMap.setProperty(PROP_Path, comphelper::containerToSequence(aPathValue));
1027 else if (std::string_view(aLine) == "Type")
1029 // Just ignore the line here, we already know the correct type.
1030 aStream.ReadLine(aLine);
1031 aPropertyMap.setProperty(PROP_Type, "ooxml-" + aName);
1033 else if (std::string_view(aLine) == "ViewBox")
1035 aStream.ReadLine(aLine);
1036 static constexpr std::string_view aExpectedPrefix(
1037 "(com.sun.star.awt.Rectangle) { ");
1038 assert(o3tl::starts_with(aLine, aExpectedPrefix));
1040 std::string_view aValue = std::string_view(aLine).substr(
1041 aExpectedPrefix.size(),
1042 aLine.getLength() - aExpectedPrefix.size() - strlen(" }"));
1043 aPropertyMap.setProperty(PROP_ViewBox, lcl_parseRectangle(aValue));
1045 else
1046 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: "
1047 << std::string_view(aLine));
1049 bNotDone = aStream.ReadLine(aLine);
1051 maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = std::move(aPropertyMap);
1055 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */