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 OString
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 OString aName
= aToken
.copy(strlen(aNamePrefix
),
44 aToken
.getLength() - strlen(aNamePrefix
) - strlen("\""));
45 aAdjustmentValue
.Name
= OUString::fromUtf8(aName
);
47 else if (o3tl::starts_with(aToken
, aValuePrefix
))
49 OString aValue
= aToken
.copy(strlen(aValuePrefix
),
50 aToken
.getLength() - strlen(aValuePrefix
) - strlen(" }"));
51 aAdjustmentValue
.Value
<<= aValue
.toInt32();
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 awt::Size
lcl_parseSize(std::string_view rValue
)
168 // We expect the following here: Width, Height
169 static const char aExpectedWidthPrefix
[] = "Width = (long) ";
170 assert(o3tl::starts_with(rValue
, aExpectedWidthPrefix
));
171 sal_Int32 nIndex
= strlen(aExpectedWidthPrefix
);
172 aSize
.Width
= o3tl::toInt32(o3tl::getToken(rValue
, 0, ',', nIndex
));
174 static const char aExpectedHeightPrefix
[] = " Height = (long) ";
175 assert(nIndex
>= 0 && o3tl::starts_with(rValue
.substr(nIndex
), aExpectedHeightPrefix
));
176 nIndex
+= strlen(aExpectedHeightPrefix
);
177 aSize
.Height
= o3tl::toInt32(rValue
.substr(nIndex
));
182 drawing::EnhancedCustomShapeTextFrame
lcl_parseEnhancedCustomShapeTextFrame(std::string_view rValue
)
184 drawing::EnhancedCustomShapeTextFrame aTextFrame
;
185 sal_Int32 nLevel
= 0;
186 bool bIgnore
= false;
187 sal_Int32 nStart
= 0;
188 for (size_t i
= 0; i
< rValue
.size(); ++i
)
190 if (rValue
[i
] == '{')
196 else if (rValue
[i
] == '}')
202 else if (rValue
[i
] == ',' && !bIgnore
)
204 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
205 static const char aExpectedPrefix
[]
206 = "TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
207 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
209 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
210 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" }"));
211 aTextFrame
.TopLeft
= lcl_parseEnhancedCustomShapeParameterPair(aToken
);
215 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken
);
216 nStart
= i
+ strlen(", ");
220 std::string_view aToken
= rValue
.substr(nStart
);
221 static const char aExpectedPrefix
[]
222 = "BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
223 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
225 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
226 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" }"));
227 aTextFrame
.BottomRight
= lcl_parseEnhancedCustomShapeParameterPair(aToken
);
231 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken
);
236 // Parses a string like: Name = "Position", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
237 // where "{ ... }" may contain "," as well.
238 void lcl_parseHandlePosition(std::vector
<beans::PropertyValue
>& rHandle
, std::string_view rValue
)
240 sal_Int32 nLevel
= 0;
241 bool bIgnore
= false;
242 sal_Int32 nStart
= 0;
243 for (size_t i
= 0; i
< rValue
.size(); ++i
)
245 if (rValue
[i
] == '{')
251 else if (rValue
[i
] == '}')
257 else if (rValue
[i
] == ',' && !bIgnore
)
259 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
260 static const char aExpectedPrefix
[]
261 = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
262 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
264 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
265 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" } }"));
267 beans::PropertyValue aPropertyValue
;
268 aPropertyValue
.Name
= "Position";
269 aPropertyValue
.Value
<<= lcl_parseEnhancedCustomShapeParameterPair(aToken
);
270 rHandle
.push_back(aPropertyValue
);
272 else if (!o3tl::starts_with(aToken
, "Name =") && !o3tl::starts_with(aToken
, "Handle ="))
273 SAL_WARN("oox", "lcl_parseHandlePosition: unexpected token: " << aToken
);
274 nStart
= i
+ strlen(", ");
279 // Parses a string like: Name = "RangeYMaximum", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
280 // where "{ ... }" may contain "," as well.
281 void lcl_parseHandleRange(std::vector
<beans::PropertyValue
>& rHandle
, std::string_view rValue
,
282 const OUString
& rName
)
284 sal_Int32 nLevel
= 0;
285 bool bIgnore
= false;
286 sal_Int32 nStart
= 0;
287 for (size_t i
= 0; i
< rValue
.size(); ++i
)
289 if (rValue
[i
] == '{')
295 else if (rValue
[i
] == '}')
301 else if (rValue
[i
] == ',' && !bIgnore
)
303 static const char aExpectedPrefix
[]
304 = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { ";
305 if (o3tl::starts_with(rValue
.substr(nStart
), aExpectedPrefix
))
307 drawing::EnhancedCustomShapeParameter aParameter
;
308 sal_Int32 nIndex
{ nStart
+ static_cast<sal_Int32
>(strlen(aExpectedPrefix
)) };
309 // We expect the following here: Value and Type
310 static const char aExpectedVPrefix
[] = "Value = (any) { (long) ";
311 assert(o3tl::starts_with(rValue
.substr(nIndex
), aExpectedVPrefix
));
312 nIndex
+= strlen(aExpectedVPrefix
);
313 aParameter
.Value
<<= o3tl::toInt32(o3tl::getToken(rValue
, 0, '}', nIndex
));
315 static const char aExpectedTPrefix
[] = ", Type = (short) ";
316 assert(nIndex
>= 0 && o3tl::starts_with(rValue
.substr(nIndex
), aExpectedTPrefix
));
317 nIndex
+= strlen(aExpectedTPrefix
);
319 = static_cast<sal_Int16
>(o3tl::toInt32(o3tl::getToken(rValue
, 0, '}', nIndex
)));
321 beans::PropertyValue aPropertyValue
;
322 aPropertyValue
.Name
= rName
;
323 aPropertyValue
.Value
<<= aParameter
;
324 rHandle
.push_back(aPropertyValue
);
326 else if (!o3tl::starts_with(rValue
.substr(nStart
), "Name =")
327 && !o3tl::starts_with(rValue
.substr(nStart
), "Handle ="))
328 SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: "
329 << rValue
.substr(nStart
, i
- nStart
));
330 nStart
= i
+ strlen(", ");
335 // Parses a string like: Name = "RefY", Handle = (long) 0, Value = (any) { (long) 0 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
336 void lcl_parseHandleRef(std::vector
<beans::PropertyValue
>& rHandle
, std::string_view rValue
,
337 const OUString
& rName
)
339 static constexpr std::string_view aPrefix
= "\", Handle = (long) 0, Value = (any) { (long) ";
340 const sal_Int32 nStart
= SAL_N_ELEMENTS("Name = \"") - 1 + rName
.getLength();
342 if (rValue
.substr(nStart
, aPrefix
.size()) == aPrefix
)
344 sal_Int32 nIndex
= nStart
+ aPrefix
.size();
345 beans::PropertyValue aPropertyValue
;
346 aPropertyValue
.Name
= rName
;
347 // We only expect a Value here
348 aPropertyValue
.Value
<<= o3tl::toInt32(o3tl::getToken(rValue
, 0, '}', nIndex
));
349 rHandle
.push_back(aPropertyValue
);
352 SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue
);
355 uno::Sequence
<beans::PropertyValue
> lcl_parseHandle(std::string_view rValue
)
357 std::vector
<beans::PropertyValue
> aRet
;
358 sal_Int32 nLevel
= 0;
359 sal_Int32 nStart
= 0;
360 for (size_t i
= 0; i
< rValue
.size(); ++i
)
362 if (rValue
[i
] == '{')
368 else if (rValue
[i
] == '}')
373 std::string_view aToken
374 = rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"));
375 if (o3tl::starts_with(aToken
, "Name = \"Position\""))
376 lcl_parseHandlePosition(aRet
, aToken
);
377 else if (o3tl::starts_with(aToken
, "Name = \"RangeXMaximum\""))
378 lcl_parseHandleRange(aRet
, aToken
, "RangeXMaximum");
379 else if (o3tl::starts_with(aToken
, "Name = \"RangeXMinimum\""))
380 lcl_parseHandleRange(aRet
, aToken
, "RangeXMinimum");
381 else if (o3tl::starts_with(aToken
, "Name = \"RangeYMaximum\""))
382 lcl_parseHandleRange(aRet
, aToken
, "RangeYMaximum");
383 else if (o3tl::starts_with(aToken
, "Name = \"RangeYMinimum\""))
384 lcl_parseHandleRange(aRet
, aToken
, "RangeYMinimum");
385 else if (o3tl::starts_with(aToken
, "Name = \"RadiusRangeMaximum\""))
386 lcl_parseHandleRange(aRet
, aToken
, "RadiusRangeMaximum");
387 else if (o3tl::starts_with(aToken
, "Name = \"RadiusRangeMinimum\""))
388 lcl_parseHandleRange(aRet
, aToken
, "RadiusRangeMinimum");
389 else if (o3tl::starts_with(aToken
, "Name = \"RefX\""))
390 lcl_parseHandleRef(aRet
, aToken
, "RefX");
391 else if (o3tl::starts_with(aToken
, "Name = \"RefY\""))
392 lcl_parseHandleRef(aRet
, aToken
, "RefY");
393 else if (o3tl::starts_with(aToken
, "Name = \"RefR\""))
394 lcl_parseHandleRef(aRet
, aToken
, "RefR");
395 else if (o3tl::starts_with(aToken
, "Name = \"RefAngle\""))
396 lcl_parseHandleRef(aRet
, aToken
, "RefAngle");
398 SAL_WARN("oox", "lcl_parseHandle: unexpected token: " << aToken
);
402 return comphelper::containerToSequence(aRet
);
405 void lcl_parseHandles(std::vector
<uno::Sequence
<beans::PropertyValue
>>& rHandles
,
406 std::string_view rValue
)
408 sal_Int32 nLevel
= 0;
409 sal_Int32 nStart
= 0;
410 for (size_t i
= 0; i
< rValue
.size(); ++i
)
412 if (rValue
[i
] == '{')
418 else if (rValue
[i
] == '}')
423 uno::Sequence
<beans::PropertyValue
> aHandle
= lcl_parseHandle(
424 rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },")));
425 rHandles
.push_back(aHandle
);
431 void lcl_parseEquations(std::vector
<OUString
>& rEquations
, std::string_view rValue
)
433 bool bInString
= false;
434 sal_Int32 nStart
= 0;
435 for (size_t i
= 0; i
< rValue
.size(); ++i
)
437 if (rValue
[i
] == '"' && !bInString
)
442 else if (rValue
[i
] == '"' && bInString
)
445 rEquations
.push_back(OUString::fromUtf8(
446 rValue
.substr(nStart
+ strlen("\""), i
- nStart
- strlen("\""))));
451 void lcl_parsePathCoordinateValues(std::vector
<beans::PropertyValue
>& rPath
,
452 std::string_view rValue
)
454 std::vector
<drawing::EnhancedCustomShapeParameterPair
> aPairs
;
455 sal_Int32 nLevel
= 0;
456 sal_Int32 nStart
= 0;
457 for (size_t i
= 0; i
< rValue
.size(); ++i
)
459 if (rValue
[i
] == '{')
465 else if (rValue
[i
] == '}')
469 aPairs
.push_back(lcl_parseEnhancedCustomShapeParameterPair(
470 rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"))));
474 beans::PropertyValue aPropertyValue
;
475 aPropertyValue
.Name
= "Coordinates";
476 aPropertyValue
.Value
<<= comphelper::containerToSequence(aPairs
);
477 rPath
.push_back(aPropertyValue
);
480 // Parses a string like: Name = "Coordinates", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
481 // where "{ ... }" may contain "," as well.
482 void lcl_parsePathCoordinates(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
484 sal_Int32 nLevel
= 0;
485 bool bIgnore
= false;
486 sal_Int32 nStart
= 0;
487 for (size_t i
= 0; i
< rValue
.size(); ++i
)
489 if (rValue
[i
] == '{')
495 else if (rValue
[i
] == '}')
501 else if (rValue
[i
] == ',' && !bIgnore
)
503 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
504 static const char aExpectedPrefix
[]
505 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
506 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
508 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
509 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" } }"));
510 lcl_parsePathCoordinateValues(rPath
, aToken
);
512 else if (!o3tl::starts_with(aToken
, "Name =") && !o3tl::starts_with(aToken
, "Handle ="))
513 SAL_WARN("oox", "lcl_parsePathCoordinates: unexpected token: " << aToken
);
514 nStart
= i
+ strlen(", ");
519 void lcl_parsePathGluePointsValues(std::vector
<beans::PropertyValue
>& rPath
,
520 std::string_view rValue
)
522 std::vector
<drawing::EnhancedCustomShapeParameterPair
> aPairs
;
523 sal_Int32 nLevel
= 0;
524 sal_Int32 nStart
= 0;
525 for (size_t i
= 0; i
< rValue
.size(); ++i
)
527 if (rValue
[i
] == '{')
533 else if (rValue
[i
] == '}')
537 aPairs
.push_back(lcl_parseEnhancedCustomShapeParameterPair(
538 rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"))));
542 beans::PropertyValue aPropertyValue
;
543 aPropertyValue
.Name
= "GluePoints";
544 aPropertyValue
.Value
<<= comphelper::containerToSequence(aPairs
);
545 rPath
.push_back(aPropertyValue
);
548 void lcl_parsePathGluePoints(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
550 sal_Int32 nLevel
= 0;
551 bool bIgnore
= false;
552 sal_Int32 nStart
= 0;
553 for (size_t i
= 0; i
< rValue
.size(); ++i
)
555 if (rValue
[i
] == '{')
561 else if (rValue
[i
] == '}')
567 else if (rValue
[i
] == ',' && !bIgnore
)
569 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
570 static const char aExpectedPrefix
[]
571 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ";
572 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
574 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
575 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" } }"));
576 lcl_parsePathGluePointsValues(rPath
, aToken
);
578 else if (!o3tl::starts_with(aToken
, "Name =") && !o3tl::starts_with(aToken
, "Handle ="))
579 SAL_WARN("oox", "lcl_parsePathGluePoints: unexpected token: " << aToken
);
580 nStart
= i
+ strlen(", ");
585 void lcl_parsePathSegmentValues(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
587 std::vector
<drawing::EnhancedCustomShapeSegment
> aSegments
;
588 sal_Int32 nLevel
= 0;
589 sal_Int32 nStart
= 0;
590 for (size_t i
= 0; i
< rValue
.size(); ++i
)
592 if (rValue
[i
] == '{')
598 else if (rValue
[i
] == '}')
602 aSegments
.push_back(lcl_parseEnhancedCustomShapeSegment(
603 rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"))));
607 beans::PropertyValue aPropertyValue
;
608 aPropertyValue
.Name
= "Segments";
609 aPropertyValue
.Value
<<= comphelper::containerToSequence(aSegments
);
610 rPath
.push_back(aPropertyValue
);
613 // Parses a string like: Name = "Segments", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
614 // where "{ ... }" may contain "," as well.
615 void lcl_parsePathSegments(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
617 sal_Int32 nLevel
= 0;
618 bool bIgnore
= false;
619 sal_Int32 nStart
= 0;
620 for (size_t i
= 0; i
< rValue
.size(); ++i
)
622 if (rValue
[i
] == '{')
628 else if (rValue
[i
] == '}')
634 else if (rValue
[i
] == ',' && !bIgnore
)
636 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
637 static const char aExpectedPrefix
[]
638 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { ";
639 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
641 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
642 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" } }"));
643 lcl_parsePathSegmentValues(rPath
, aToken
);
645 else if (!o3tl::starts_with(aToken
, "Name =") && !o3tl::starts_with(aToken
, "Handle ="))
646 SAL_WARN("oox", "lcl_parsePathSegments: unexpected token: " << aToken
);
647 nStart
= i
+ strlen(", ");
652 void lcl_parsePathTextFrameValues(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
654 std::vector
<drawing::EnhancedCustomShapeTextFrame
> aTextFrames
;
655 sal_Int32 nLevel
= 0;
656 sal_Int32 nStart
= 0;
657 for (size_t i
= 0; i
< rValue
.size(); ++i
)
659 if (rValue
[i
] == '{')
665 else if (rValue
[i
] == '}')
669 aTextFrames
.push_back(lcl_parseEnhancedCustomShapeTextFrame(
670 rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"))));
674 beans::PropertyValue aPropertyValue
;
675 aPropertyValue
.Name
= "TextFrames";
676 aPropertyValue
.Value
<<= comphelper::containerToSequence(aTextFrames
);
677 rPath
.push_back(aPropertyValue
);
680 // Parses a string like: Name = "TextFrames", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
681 // where "{ ... }" may contain "," as well.
682 void lcl_parsePathTextFrames(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
684 sal_Int32 nLevel
= 0;
685 bool bIgnore
= false;
686 sal_Int32 nStart
= 0;
687 for (size_t i
= 0; i
< rValue
.size(); ++i
)
689 if (rValue
[i
] == '{')
695 else if (rValue
[i
] == '}')
701 else if (rValue
[i
] == ',' && !bIgnore
)
703 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
704 static const char aExpectedPrefix
[]
705 = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { ";
706 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
708 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
709 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" } }"));
710 lcl_parsePathTextFrameValues(rPath
, aToken
);
712 else if (!o3tl::starts_with(aToken
, "Name =") && !o3tl::starts_with(aToken
, "Handle ="))
713 SAL_WARN("oox", "lcl_parsePathTextFrames: unexpected token: " << aToken
);
714 nStart
= i
+ strlen(", ");
719 void lcl_parsePathSubViewSizeValues(std::vector
<beans::PropertyValue
>& rPath
,
720 std::string_view rValue
)
722 std::vector
<awt::Size
> aSizes
;
723 sal_Int32 nLevel
= 0;
724 sal_Int32 nStart
= 0;
725 for (size_t i
= 0; i
< rValue
.size(); ++i
)
727 if (rValue
[i
] == '{')
733 else if (rValue
[i
] == '}')
737 aSizes
.push_back(lcl_parseSize(
738 rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"))));
742 beans::PropertyValue aPropertyValue
;
743 aPropertyValue
.Name
= "SubViewSize";
744 aPropertyValue
.Value
<<= comphelper::containerToSequence(aSizes
);
745 rPath
.push_back(aPropertyValue
);
748 void lcl_parsePathSubViewSize(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
750 sal_Int32 nLevel
= 0;
751 bool bIgnore
= false;
752 sal_Int32 nStart
= 0;
753 for (size_t i
= 0; i
< rValue
.size(); ++i
)
755 if (rValue
[i
] == '{')
761 else if (rValue
[i
] == '}')
767 else if (rValue
[i
] == ',' && !bIgnore
)
769 std::string_view aToken
= rValue
.substr(nStart
, i
- nStart
);
770 static const char aExpectedPrefix
[] = "Value = (any) { ([]com.sun.star.awt.Size) { ";
771 if (o3tl::starts_with(aToken
, aExpectedPrefix
))
773 aToken
= aToken
.substr(strlen(aExpectedPrefix
),
774 aToken
.size() - strlen(aExpectedPrefix
) - strlen(" } }"));
775 lcl_parsePathSubViewSizeValues(rPath
, aToken
);
777 else if (!o3tl::starts_with(aToken
, "Name =") && !o3tl::starts_with(aToken
, "Handle ="))
778 SAL_WARN("oox", "lcl_parsePathSubViewSize: unexpected token: " << aToken
);
779 nStart
= i
+ strlen(", ");
784 void lcl_parsePath(std::vector
<beans::PropertyValue
>& rPath
, std::string_view rValue
)
786 sal_Int32 nLevel
= 0;
787 sal_Int32 nStart
= 0;
788 for (size_t i
= 0; i
< rValue
.size(); ++i
)
790 if (rValue
[i
] == '{')
796 else if (rValue
[i
] == '}')
801 std::string_view aToken
802 = rValue
.substr(nStart
+ strlen("{ "), i
- nStart
- strlen(" },"));
803 if (o3tl::starts_with(aToken
, "Name = \"Coordinates\""))
804 lcl_parsePathCoordinates(rPath
, aToken
);
805 else if (o3tl::starts_with(aToken
, "Name = \"GluePoints\""))
806 lcl_parsePathGluePoints(rPath
, aToken
);
807 else if (o3tl::starts_with(aToken
, "Name = \"Segments\""))
808 lcl_parsePathSegments(rPath
, aToken
);
809 else if (o3tl::starts_with(aToken
, "Name = \"TextFrames\""))
810 lcl_parsePathTextFrames(rPath
, aToken
);
811 else if (o3tl::starts_with(aToken
, "Name = \"SubViewSize\""))
812 lcl_parsePathSubViewSize(rPath
, aToken
);
814 SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken
);
821 namespace oox::drawingml
823 void CustomShapeProperties::initializePresetDataMap()
825 OUString
aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER
"/filter/oox-drawingml-cs-presets");
826 rtl::Bootstrap::expandMacros(aPath
);
827 SvFileStream
aStream(aPath
, StreamMode::READ
);
828 if (aStream
.GetError() != ERRCODE_NONE
)
829 SAL_WARN("oox", "failed to open oox-drawingml-cs-presets");
832 bool bNotDone
= aStream
.ReadLine(aLine
);
833 PropertyMap aPropertyMap
;
837 static const char aCommentPrefix
[] = "/* ";
838 if (o3tl::starts_with(aLine
, aCommentPrefix
))
843 maPresetDataMap
[TokenMap::getTokenFromUnicode(aName
)] = aPropertyMap
;
844 aName
= OUString::fromUtf8(std::string_view(aLine
).substr(
845 strlen(aCommentPrefix
),
846 aLine
.getLength() - strlen(aCommentPrefix
) - strlen(" */")));
850 if (std::string_view(aLine
) == "AdjustmentValues")
852 aStream
.ReadLine(aLine
);
853 if (std::string_view(aLine
)
854 != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}")
856 std::vector
<drawing::EnhancedCustomShapeAdjustmentValue
> aAdjustmentValues
;
857 static constexpr std::string_view
aExpectedPrefix(
858 "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { ");
859 assert(o3tl::starts_with(aLine
, aExpectedPrefix
));
861 std::string_view aValue
= std::string_view(aLine
).substr(
862 aExpectedPrefix
.size(),
863 aLine
.getLength() - aExpectedPrefix
.size() - strlen(" }"));
864 lcl_parseAdjustmentValues(aAdjustmentValues
, aValue
);
865 aPropertyMap
.setProperty(PROP_AdjustmentValues
,
866 comphelper::containerToSequence(aAdjustmentValues
));
869 aPropertyMap
.setProperty(PROP_AdjustmentValues
, uno::Sequence
<OUString
>(0));
871 else if (std::string_view(aLine
) == "Equations")
873 aStream
.ReadLine(aLine
);
874 if (std::string_view(aLine
) != "([]string) {}")
876 std::vector
<OUString
> aEquations
;
877 static constexpr std::string_view
aExpectedPrefix("([]string) { ");
878 assert(o3tl::starts_with(aLine
, aExpectedPrefix
));
880 std::string_view aValue
= std::string_view(aLine
).substr(
881 aExpectedPrefix
.size(),
882 aLine
.getLength() - aExpectedPrefix
.size() - strlen(" }"));
883 lcl_parseEquations(aEquations
, aValue
);
884 aPropertyMap
.setProperty(PROP_Equations
,
885 comphelper::containerToSequence(aEquations
));
888 aPropertyMap
.setProperty(PROP_Equations
, uno::Sequence
<OUString
>(0));
890 else if (std::string_view(aLine
) == "Handles")
892 aStream
.ReadLine(aLine
);
893 if (std::string_view(aLine
) != "([][]com.sun.star.beans.PropertyValue) {}")
895 std::vector
<uno::Sequence
<beans::PropertyValue
>> aHandles
;
896 static constexpr std::string_view
aExpectedPrefix(
897 "([][]com.sun.star.beans.PropertyValue) { ");
898 assert(o3tl::starts_with(aLine
, aExpectedPrefix
));
900 std::string_view aValue
= std::string_view(aLine
).substr(
901 aExpectedPrefix
.size(),
902 aLine
.getLength() - aExpectedPrefix
.size() - strlen(" }"));
903 lcl_parseHandles(aHandles
, aValue
);
904 aPropertyMap
.setProperty(PROP_Handles
,
905 comphelper::containerToSequence(aHandles
));
908 aPropertyMap
.setProperty(PROP_Handles
, uno::Sequence
<OUString
>(0));
910 else if (std::string_view(aLine
) == "MirroredX")
912 aStream
.ReadLine(aLine
);
913 if (std::string_view(aLine
) == "true" || std::string_view(aLine
) == "false")
915 aPropertyMap
.setProperty(PROP_MirroredX
, std::string_view(aLine
) == "true");
918 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected "
919 "MirroredX parameter");
921 else if (std::string_view(aLine
) == "MirroredY")
923 aStream
.ReadLine(aLine
);
924 if (std::string_view(aLine
) == "true" || std::string_view(aLine
) == "false")
926 aPropertyMap
.setProperty(PROP_MirroredY
, std::string_view(aLine
) == "true");
929 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected "
930 "MirroredY parameter");
932 else if (std::string_view(aLine
) == "Path")
934 aStream
.ReadLine(aLine
);
935 static constexpr std::string_view
aExpectedPrefix(
936 "([]com.sun.star.beans.PropertyValue) { ");
937 assert(o3tl::starts_with(aLine
, aExpectedPrefix
));
939 std::vector
<beans::PropertyValue
> aPathValue
;
940 std::string_view aValue
= std::string_view(aLine
).substr(
941 aExpectedPrefix
.size(),
942 aLine
.getLength() - aExpectedPrefix
.size() - strlen(" }"));
943 lcl_parsePath(aPathValue
, aValue
);
944 aPropertyMap
.setProperty(PROP_Path
, comphelper::containerToSequence(aPathValue
));
946 else if (std::string_view(aLine
) == "Type")
948 // Just ignore the line here, we already know the correct type.
949 aStream
.ReadLine(aLine
);
950 aPropertyMap
.setProperty(PROP_Type
, "ooxml-" + aName
);
952 else if (std::string_view(aLine
) == "ViewBox")
954 aStream
.ReadLine(aLine
);
955 static constexpr std::string_view
aExpectedPrefix(
956 "(com.sun.star.awt.Rectangle) { ");
957 assert(o3tl::starts_with(aLine
, aExpectedPrefix
));
959 std::string_view aValue
= std::string_view(aLine
).substr(
960 aExpectedPrefix
.size(),
961 aLine
.getLength() - aExpectedPrefix
.size() - strlen(" }"));
962 aPropertyMap
.setProperty(PROP_ViewBox
, lcl_parseRectangle(aValue
));
965 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: "
966 << std::string_view(aLine
));
968 bNotDone
= aStream
.ReadLine(aLine
);
970 maPresetDataMap
[TokenMap::getTokenFromUnicode(aName
)] = aPropertyMap
;
974 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */