1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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
;
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
)
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
)
66 for (size_t i
= 0; i
< rValue
.size(); ++i
)
74 else if (rValue
[i
] == '}')
79 lcl_parseAdjustmentValue(
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
);
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
);
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
);
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
);
117 = static_cast<sal_uInt16
>(o3tl::toInt32(o3tl::getToken(rValue
, 0, '}', nIndex
)));
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
);
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
)));
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
));
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
));
177 awt::Size
lcl_parseSize(std::string_view rValue
)
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
));
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
] == '{')
208 else if (rValue
[i
] == '}')
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
);
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
);
243 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken
);
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
] == '{')
263 else if (rValue
[i
] == '}')
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
] == '{')
307 else if (rValue
[i
] == '}')
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
);
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
);
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
] == '{')
380 else if (rValue
[i
] == '}')
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
);
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
] == '{')
430 else if (rValue
[i
] == '}')
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
)
454 else if (rValue
[i
] == '"' && bInString
)
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
] == '{')
477 else if (rValue
[i
] == '}')
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
] == '{')
507 else if (rValue
[i
] == '}')
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
] == '{')
545 else if (rValue
[i
] == '}')
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
] == '{')
573 else if (rValue
[i
] == '}')
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
] == '{')
611 else if (rValue
[i
] == '}')
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
] == '{')
640 else if (rValue
[i
] == '}')
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 ="))
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
] == '{')
677 else if (rValue
[i
] == '}')
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
] == '{')
707 else if (rValue
[i
] == '}')
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
] == '{')
744 else if (rValue
[i
] == '}')
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
] == '{')
774 else if (rValue
[i
] == '}')
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
] == '{')
812 else if (rValue
[i
] == '}')
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
] == '{')
840 else if (rValue
[i
] == '}')
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
] == '{')
875 else if (rValue
[i
] == '}')
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
);
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");
913 bool bNotDone
= aStream
.ReadLine(aLine
);
914 PropertyMap aPropertyMap
;
918 static const char aCommentPrefix
[] = "/* ";
919 if (o3tl::starts_with(aLine
, aCommentPrefix
))
924 maPresetDataMap
[TokenMap::getTokenFromUnicode(aName
)] = aPropertyMap
;
925 aName
= OUString::fromUtf8(std::string_view(aLine
).substr(
926 strlen(aCommentPrefix
),
927 aLine
.getLength() - strlen(aCommentPrefix
) - strlen(" */")));
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
));
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
));
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
));
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");
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");
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
));
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: */