LibreOffice Module oox (master) 1
customshapepresetdata.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <config_folders.h>
11#include <rtl/bootstrap.hxx>
12#include <sal/log.hxx>
13#include <tools/stream.hxx>
15
17#include <oox/token/properties.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>
24
25using namespace ::com::sun::star;
26
27namespace
28{
29// Parses a string like: Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj"
30void lcl_parseAdjustmentValue(
31 std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues,
32 std::string_view rValue)
33{
34 sal_Int32 nIndex = 0;
35 drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue;
36 do
37 {
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))
42 {
43 OString aName = aToken.copy(strlen(aNamePrefix),
44 aToken.getLength() - strlen(aNamePrefix) - strlen("\""));
45 aAdjustmentValue.Name = OUString::fromUtf8(aName);
46 }
47 else if (o3tl::starts_with(aToken, aValuePrefix))
48 {
49 OString aValue = aToken.copy(strlen(aValuePrefix),
50 aToken.getLength() - strlen(aValuePrefix) - strlen(" }"));
51 aAdjustmentValue.Value <<= aValue.toInt32();
52 }
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);
57}
58
59// Parses a string like: { Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj" }, { Value = ..., State = ..., Name = ... }
60void lcl_parseAdjustmentValues(
61 std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues,
62 std::string_view rValue)
63{
64 sal_Int32 nLevel = 0;
65 sal_Int32 nStart = 0;
66 for (size_t i = 0; i < rValue.size(); ++i)
67 {
68 if (rValue[i] == '{')
69 {
70 if (!nLevel)
71 nStart = i;
72 nLevel++;
73 }
74 else if (rValue[i] == '}')
75 {
76 nLevel--;
77 if (!nLevel)
78 {
79 lcl_parseAdjustmentValue(
80 rAdjustmentValues,
81 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")));
82 }
83 }
84 }
85}
86
87drawing::EnhancedCustomShapeParameterPair
88lcl_parseEnhancedCustomShapeParameterPair(std::string_view rValue)
89{
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)));
98
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)));
104
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)));
112
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;
119}
120
121drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(std::string_view rValue)
122{
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)));
130
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;
136}
137
138awt::Rectangle lcl_parseRectangle(std::string_view rValue)
139{
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));
146
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));
151
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));
156
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));
161
162 return aRectangle;
163}
164
165awt::Size lcl_parseSize(std::string_view rValue)
166{
167 awt::Size aSize;
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));
173
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));
178
179 return aSize;
180}
181
182drawing::EnhancedCustomShapeTextFrame lcl_parseEnhancedCustomShapeTextFrame(std::string_view rValue)
183{
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)
189 {
190 if (rValue[i] == '{')
191 {
192 if (!nLevel)
193 bIgnore = true;
194 nLevel++;
195 }
196 else if (rValue[i] == '}')
197 {
198 nLevel--;
199 if (!nLevel)
200 bIgnore = false;
201 }
202 else if (rValue[i] == ',' && !bIgnore)
203 {
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))
208 {
209 aToken = aToken.substr(strlen(aExpectedPrefix),
210 aToken.size() - strlen(aExpectedPrefix) - strlen(" }"));
211 aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken);
212 }
213 else
214 SAL_WARN("oox",
215 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken);
216 nStart = i + strlen(", ");
217 }
218 }
219
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))
224 {
225 aToken = aToken.substr(strlen(aExpectedPrefix),
226 aToken.size() - strlen(aExpectedPrefix) - strlen(" }"));
227 aTextFrame.BottomRight = lcl_parseEnhancedCustomShapeParameterPair(aToken);
228 }
229 else
230 SAL_WARN("oox",
231 "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken);
232
233 return aTextFrame;
234}
235
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.
238void lcl_parseHandlePosition(std::vector<beans::PropertyValue>& rHandle, std::string_view rValue)
239{
240 sal_Int32 nLevel = 0;
241 bool bIgnore = false;
242 sal_Int32 nStart = 0;
243 for (size_t i = 0; i < rValue.size(); ++i)
244 {
245 if (rValue[i] == '{')
246 {
247 if (!nLevel)
248 bIgnore = true;
249 nLevel++;
250 }
251 else if (rValue[i] == '}')
252 {
253 nLevel--;
254 if (!nLevel)
255 bIgnore = false;
256 }
257 else if (rValue[i] == ',' && !bIgnore)
258 {
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))
263 {
264 aToken = aToken.substr(strlen(aExpectedPrefix),
265 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
266
267 beans::PropertyValue aPropertyValue;
268 aPropertyValue.Name = "Position";
269 aPropertyValue.Value <<= lcl_parseEnhancedCustomShapeParameterPair(aToken);
270 rHandle.push_back(aPropertyValue);
271 }
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(", ");
275 }
276 }
277}
278
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.
281void lcl_parseHandleRange(std::vector<beans::PropertyValue>& rHandle, std::string_view rValue,
282 const OUString& rName)
283{
284 sal_Int32 nLevel = 0;
285 bool bIgnore = false;
286 sal_Int32 nStart = 0;
287 for (size_t i = 0; i < rValue.size(); ++i)
288 {
289 if (rValue[i] == '{')
290 {
291 if (!nLevel)
292 bIgnore = true;
293 nLevel++;
294 }
295 else if (rValue[i] == '}')
296 {
297 nLevel--;
298 if (!nLevel)
299 bIgnore = false;
300 }
301 else if (rValue[i] == ',' && !bIgnore)
302 {
303 static const char aExpectedPrefix[]
304 = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { ";
305 if (o3tl::starts_with(rValue.substr(nStart), aExpectedPrefix))
306 {
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));
314
315 static const char aExpectedTPrefix[] = ", Type = (short) ";
316 assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedTPrefix));
317 nIndex += strlen(aExpectedTPrefix);
318 aParameter.Type
319 = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)));
320
321 beans::PropertyValue aPropertyValue;
322 aPropertyValue.Name = rName;
323 aPropertyValue.Value <<= aParameter;
324 rHandle.push_back(aPropertyValue);
325 }
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(", ");
331 }
332 }
333}
334
335// Parses a string like: Name = "RefY", Handle = (long) 0, Value = (any) { (long) 0 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE
336void lcl_parseHandleRef(std::vector<beans::PropertyValue>& rHandle, std::string_view rValue,
337 const OUString& rName)
338{
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();
341
342 if (rValue.substr(nStart, aPrefix.size()) == aPrefix)
343 {
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);
350 }
351 else
352 SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue);
353}
354
355uno::Sequence<beans::PropertyValue> lcl_parseHandle(std::string_view rValue)
356{
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)
361 {
362 if (rValue[i] == '{')
363 {
364 if (!nLevel)
365 nStart = i;
366 nLevel++;
367 }
368 else if (rValue[i] == '}')
369 {
370 nLevel--;
371 if (!nLevel)
372 {
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");
397 else
398 SAL_WARN("oox", "lcl_parseHandle: unexpected token: " << aToken);
399 }
400 }
401 }
403}
404
405void lcl_parseHandles(std::vector<uno::Sequence<beans::PropertyValue>>& rHandles,
406 std::string_view rValue)
407{
408 sal_Int32 nLevel = 0;
409 sal_Int32 nStart = 0;
410 for (size_t i = 0; i < rValue.size(); ++i)
411 {
412 if (rValue[i] == '{')
413 {
414 if (!nLevel)
415 nStart = i;
416 nLevel++;
417 }
418 else if (rValue[i] == '}')
419 {
420 nLevel--;
421 if (!nLevel)
422 {
423 uno::Sequence<beans::PropertyValue> aHandle = lcl_parseHandle(
424 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")));
425 rHandles.push_back(aHandle);
426 }
427 }
428 }
429}
430
431void lcl_parseEquations(std::vector<OUString>& rEquations, std::string_view rValue)
432{
433 bool bInString = false;
434 sal_Int32 nStart = 0;
435 for (size_t i = 0; i < rValue.size(); ++i)
436 {
437 if (rValue[i] == '"' && !bInString)
438 {
439 nStart = i;
440 bInString = true;
441 }
442 else if (rValue[i] == '"' && bInString)
443 {
444 bInString = false;
445 rEquations.push_back(OUString::fromUtf8(
446 rValue.substr(nStart + strlen("\""), i - nStart - strlen("\""))));
447 }
448 }
449}
450
451void lcl_parsePathCoordinateValues(std::vector<beans::PropertyValue>& rPath,
452 std::string_view rValue)
453{
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)
458 {
459 if (rValue[i] == '{')
460 {
461 if (!nLevel)
462 nStart = i;
463 nLevel++;
464 }
465 else if (rValue[i] == '}')
466 {
467 nLevel--;
468 if (!nLevel)
469 aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair(
470 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
471 }
472 }
473
474 beans::PropertyValue aPropertyValue;
475 aPropertyValue.Name = "Coordinates";
476 aPropertyValue.Value <<= comphelper::containerToSequence(aPairs);
477 rPath.push_back(aPropertyValue);
478}
479
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.
482void lcl_parsePathCoordinates(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
483{
484 sal_Int32 nLevel = 0;
485 bool bIgnore = false;
486 sal_Int32 nStart = 0;
487 for (size_t i = 0; i < rValue.size(); ++i)
488 {
489 if (rValue[i] == '{')
490 {
491 if (!nLevel)
492 bIgnore = true;
493 nLevel++;
494 }
495 else if (rValue[i] == '}')
496 {
497 nLevel--;
498 if (!nLevel)
499 bIgnore = false;
500 }
501 else if (rValue[i] == ',' && !bIgnore)
502 {
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))
507 {
508 aToken = aToken.substr(strlen(aExpectedPrefix),
509 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
510 lcl_parsePathCoordinateValues(rPath, aToken);
511 }
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(", ");
515 }
516 }
517}
518
519void lcl_parsePathGluePointsValues(std::vector<beans::PropertyValue>& rPath,
520 std::string_view rValue)
521{
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)
526 {
527 if (rValue[i] == '{')
528 {
529 if (!nLevel)
530 nStart = i;
531 nLevel++;
532 }
533 else if (rValue[i] == '}')
534 {
535 nLevel--;
536 if (!nLevel)
537 aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair(
538 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
539 }
540 }
541
542 beans::PropertyValue aPropertyValue;
543 aPropertyValue.Name = "GluePoints";
544 aPropertyValue.Value <<= comphelper::containerToSequence(aPairs);
545 rPath.push_back(aPropertyValue);
546}
547
548void lcl_parsePathGluePoints(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
549{
550 sal_Int32 nLevel = 0;
551 bool bIgnore = false;
552 sal_Int32 nStart = 0;
553 for (size_t i = 0; i < rValue.size(); ++i)
554 {
555 if (rValue[i] == '{')
556 {
557 if (!nLevel)
558 bIgnore = true;
559 nLevel++;
560 }
561 else if (rValue[i] == '}')
562 {
563 nLevel--;
564 if (!nLevel)
565 bIgnore = false;
566 }
567 else if (rValue[i] == ',' && !bIgnore)
568 {
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))
573 {
574 aToken = aToken.substr(strlen(aExpectedPrefix),
575 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
576 lcl_parsePathGluePointsValues(rPath, aToken);
577 }
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(", ");
581 }
582 }
583}
584
585void lcl_parsePathSegmentValues(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
586{
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)
591 {
592 if (rValue[i] == '{')
593 {
594 if (!nLevel)
595 nStart = i;
596 nLevel++;
597 }
598 else if (rValue[i] == '}')
599 {
600 nLevel--;
601 if (!nLevel)
602 aSegments.push_back(lcl_parseEnhancedCustomShapeSegment(
603 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
604 }
605 }
606
607 beans::PropertyValue aPropertyValue;
608 aPropertyValue.Name = "Segments";
609 aPropertyValue.Value <<= comphelper::containerToSequence(aSegments);
610 rPath.push_back(aPropertyValue);
611}
612
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.
615void lcl_parsePathSegments(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
616{
617 sal_Int32 nLevel = 0;
618 bool bIgnore = false;
619 sal_Int32 nStart = 0;
620 for (size_t i = 0; i < rValue.size(); ++i)
621 {
622 if (rValue[i] == '{')
623 {
624 if (!nLevel)
625 bIgnore = true;
626 nLevel++;
627 }
628 else if (rValue[i] == '}')
629 {
630 nLevel--;
631 if (!nLevel)
632 bIgnore = false;
633 }
634 else if (rValue[i] == ',' && !bIgnore)
635 {
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))
640 {
641 aToken = aToken.substr(strlen(aExpectedPrefix),
642 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
643 lcl_parsePathSegmentValues(rPath, aToken);
644 }
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(", ");
648 }
649 }
650}
651
652void lcl_parsePathTextFrameValues(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
653{
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)
658 {
659 if (rValue[i] == '{')
660 {
661 if (!nLevel)
662 nStart = i;
663 nLevel++;
664 }
665 else if (rValue[i] == '}')
666 {
667 nLevel--;
668 if (!nLevel)
669 aTextFrames.push_back(lcl_parseEnhancedCustomShapeTextFrame(
670 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
671 }
672 }
673
674 beans::PropertyValue aPropertyValue;
675 aPropertyValue.Name = "TextFrames";
676 aPropertyValue.Value <<= comphelper::containerToSequence(aTextFrames);
677 rPath.push_back(aPropertyValue);
678}
679
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.
682void lcl_parsePathTextFrames(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
683{
684 sal_Int32 nLevel = 0;
685 bool bIgnore = false;
686 sal_Int32 nStart = 0;
687 for (size_t i = 0; i < rValue.size(); ++i)
688 {
689 if (rValue[i] == '{')
690 {
691 if (!nLevel)
692 bIgnore = true;
693 nLevel++;
694 }
695 else if (rValue[i] == '}')
696 {
697 nLevel--;
698 if (!nLevel)
699 bIgnore = false;
700 }
701 else if (rValue[i] == ',' && !bIgnore)
702 {
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))
707 {
708 aToken = aToken.substr(strlen(aExpectedPrefix),
709 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
710 lcl_parsePathTextFrameValues(rPath, aToken);
711 }
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(", ");
715 }
716 }
717}
718
719void lcl_parsePathSubViewSizeValues(std::vector<beans::PropertyValue>& rPath,
720 std::string_view rValue)
721{
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)
726 {
727 if (rValue[i] == '{')
728 {
729 if (!nLevel)
730 nStart = i;
731 nLevel++;
732 }
733 else if (rValue[i] == '}')
734 {
735 nLevel--;
736 if (!nLevel)
737 aSizes.push_back(lcl_parseSize(
738 rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))));
739 }
740 }
741
742 beans::PropertyValue aPropertyValue;
743 aPropertyValue.Name = "SubViewSize";
744 aPropertyValue.Value <<= comphelper::containerToSequence(aSizes);
745 rPath.push_back(aPropertyValue);
746}
747
748void lcl_parsePathSubViewSize(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
749{
750 sal_Int32 nLevel = 0;
751 bool bIgnore = false;
752 sal_Int32 nStart = 0;
753 for (size_t i = 0; i < rValue.size(); ++i)
754 {
755 if (rValue[i] == '{')
756 {
757 if (!nLevel)
758 bIgnore = true;
759 nLevel++;
760 }
761 else if (rValue[i] == '}')
762 {
763 nLevel--;
764 if (!nLevel)
765 bIgnore = false;
766 }
767 else if (rValue[i] == ',' && !bIgnore)
768 {
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))
772 {
773 aToken = aToken.substr(strlen(aExpectedPrefix),
774 aToken.size() - strlen(aExpectedPrefix) - strlen(" } }"));
775 lcl_parsePathSubViewSizeValues(rPath, aToken);
776 }
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(", ");
780 }
781 }
782}
783
784void lcl_parsePath(std::vector<beans::PropertyValue>& rPath, std::string_view rValue)
785{
786 sal_Int32 nLevel = 0;
787 sal_Int32 nStart = 0;
788 for (size_t i = 0; i < rValue.size(); ++i)
789 {
790 if (rValue[i] == '{')
791 {
792 if (!nLevel)
793 nStart = i;
794 nLevel++;
795 }
796 else if (rValue[i] == '}')
797 {
798 nLevel--;
799 if (!nLevel)
800 {
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);
813 else
814 SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken);
815 }
816 }
817 }
818}
819}
820
821namespace oox::drawingml
822{
824{
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");
830 OStringBuffer aLine;
831 OUString aName;
832 bool bNotDone = aStream.ReadLine(aLine);
833 PropertyMap aPropertyMap;
834 bool bFirst = true;
835 while (bNotDone)
836 {
837 static const char aCommentPrefix[] = "/* ";
838 if (o3tl::starts_with(aLine, aCommentPrefix))
839 {
840 if (bFirst)
841 bFirst = false;
842 else
844 aName = OUString::fromUtf8(std::string_view(aLine).substr(
845 strlen(aCommentPrefix),
846 aLine.getLength() - strlen(aCommentPrefix) - strlen(" */")));
847 }
848 else
849 {
850 if (std::string_view(aLine) == "AdjustmentValues")
851 {
852 aStream.ReadLine(aLine);
853 if (std::string_view(aLine)
854 != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}")
855 {
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));
860
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));
867 }
868 else
869 aPropertyMap.setProperty(PROP_AdjustmentValues, uno::Sequence<OUString>(0));
870 }
871 else if (std::string_view(aLine) == "Equations")
872 {
873 aStream.ReadLine(aLine);
874 if (std::string_view(aLine) != "([]string) {}")
875 {
876 std::vector<OUString> aEquations;
877 static constexpr std::string_view aExpectedPrefix("([]string) { ");
878 assert(o3tl::starts_with(aLine, aExpectedPrefix));
879
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,
886 }
887 else
888 aPropertyMap.setProperty(PROP_Equations, uno::Sequence<OUString>(0));
889 }
890 else if (std::string_view(aLine) == "Handles")
891 {
892 aStream.ReadLine(aLine);
893 if (std::string_view(aLine) != "([][]com.sun.star.beans.PropertyValue) {}")
894 {
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));
899
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,
906 }
907 else
908 aPropertyMap.setProperty(PROP_Handles, uno::Sequence<OUString>(0));
909 }
910 else if (std::string_view(aLine) == "MirroredX")
911 {
912 aStream.ReadLine(aLine);
913 if (std::string_view(aLine) == "true" || std::string_view(aLine) == "false")
914 {
915 aPropertyMap.setProperty(PROP_MirroredX, std::string_view(aLine) == "true");
916 }
917 else
918 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected "
919 "MirroredX parameter");
920 }
921 else if (std::string_view(aLine) == "MirroredY")
922 {
923 aStream.ReadLine(aLine);
924 if (std::string_view(aLine) == "true" || std::string_view(aLine) == "false")
925 {
926 aPropertyMap.setProperty(PROP_MirroredY, std::string_view(aLine) == "true");
927 }
928 else
929 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected "
930 "MirroredY parameter");
931 }
932 else if (std::string_view(aLine) == "Path")
933 {
934 aStream.ReadLine(aLine);
935 static constexpr std::string_view aExpectedPrefix(
936 "([]com.sun.star.beans.PropertyValue) { ");
937 assert(o3tl::starts_with(aLine, aExpectedPrefix));
938
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));
945 }
946 else if (std::string_view(aLine) == "Type")
947 {
948 // Just ignore the line here, we already know the correct type.
949 aStream.ReadLine(aLine);
950 aPropertyMap.setProperty(PROP_Type, "ooxml-" + aName);
951 }
952 else if (std::string_view(aLine) == "ViewBox")
953 {
954 aStream.ReadLine(aLine);
955 static constexpr std::string_view aExpectedPrefix(
956 "(com.sun.star.awt.Rectangle) { ");
957 assert(o3tl::starts_with(aLine, aExpectedPrefix));
958
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));
963 }
964 else
965 SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: "
966 << std::string_view(aLine));
967 }
968 bNotDone = aStream.ReadLine(aLine);
969 }
971}
972}
973
974/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool ReadLine(OStringBuffer &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
ErrCode GetError() const
A helper that maps property identifiers to property values.
Definition: propertymap.hxx:52
bool setProperty(sal_Int32 nPropId, Type &&rValue)
Sets the specified property to the passed value.
Definition: propertymap.hxx:72
static sal_Int32 getTokenFromUnicode(std::u16string_view rUnicodeName)
Returns the token identifier for the passed Unicode token name.
Definition: tokenmap.cxx:77
#define ERRCODE_NONE
sal_Int32 nIndex
OUString aName
#define SAL_WARN(area, stream)
#define SAL_N_ELEMENTS(arr)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::u16string_view trim(std::u16string_view str)
std::vector< ISegmentProgressBarRef > aSegments