LibreOffice Module svgio (master) 1
svgcharacternode.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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <svgcharacternode.hxx>
28#include <utility>
29#include <o3tl/string_view.hxx>
30#include <osl/diagnose.h>
31
32using namespace drawinglayer::primitive2d;
33
34namespace svgio::svgreader
35{
37 : mbLengthAdjust(true)
38 {
39 }
40
41 void SvgTextPositions::parseTextPositionAttributes(SVGToken aSVGToken, std::u16string_view aContent)
42 {
43 // parse own
44 switch(aSVGToken)
45 {
46 case SVGToken::X:
47 {
48 if(!aContent.empty())
49 {
50 SvgNumberVector aVector;
51
52 if(readSvgNumberVector(aContent, aVector))
53 {
54 setX(std::move(aVector));
55 }
56 }
57 break;
58 }
59 case SVGToken::Y:
60 {
61 if(!aContent.empty())
62 {
63 SvgNumberVector aVector;
64
65 if(readSvgNumberVector(aContent, aVector))
66 {
67 setY(std::move(aVector));
68 }
69 }
70 break;
71 }
72 case SVGToken::Dx:
73 {
74 if(!aContent.empty())
75 {
76 SvgNumberVector aVector;
77
78 if(readSvgNumberVector(aContent, aVector))
79 {
80 setDx(std::move(aVector));
81 }
82 }
83 break;
84 }
85 case SVGToken::Dy:
86 {
87 if(!aContent.empty())
88 {
89 SvgNumberVector aVector;
90
91 if(readSvgNumberVector(aContent, aVector))
92 {
93 setDy(std::move(aVector));
94 }
95 }
96 break;
97 }
99 {
100 if(!aContent.empty())
101 {
102 SvgNumberVector aVector;
103
104 if(readSvgNumberVector(aContent, aVector))
105 {
106 setRotate(std::move(aVector));
107 }
108 }
109 break;
110 }
112 {
113 SvgNumber aNum;
114
115 if(readSingleNumber(aContent, aNum))
116 {
117 if(aNum.isPositive())
118 {
119 setTextLength(aNum);
120 }
121 }
122 break;
123 }
125 {
126 if(!aContent.empty())
127 {
128 if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"spacing"))
129 {
130 setLengthAdjust(true);
131 }
132 else if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"spacingAndGlyphs"))
133 {
134 setLengthAdjust(false);
135 }
136 }
137 break;
138 }
139 default:
140 {
141 break;
142 }
143 }
144 }
145
146 namespace {
147
148 class localTextBreakupHelper : public TextBreakupHelper
149 {
150 private:
151 SvgTextPosition& mrSvgTextPosition;
152
153 protected:
156 virtual bool allowChange(sal_uInt32 nCount, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 nIndex, sal_uInt32 nLength) override;
157
158 public:
159 localTextBreakupHelper(
160 const TextSimplePortionPrimitive2D& rSource,
161 SvgTextPosition& rSvgTextPosition)
162 : TextBreakupHelper(rSource),
163 mrSvgTextPosition(rSvgTextPosition)
164 {
165 }
166 };
167
168 }
169
170 bool localTextBreakupHelper::allowChange(sal_uInt32 /*nCount*/, basegfx::B2DHomMatrix& rNewTransform, sal_uInt32 /*nIndex*/, sal_uInt32 /*nLength*/)
171 {
172 const double fRotation(mrSvgTextPosition.consumeRotation());
173
174 if(0.0 != fRotation)
175 {
176 const basegfx::B2DPoint aBasePoint(rNewTransform * basegfx::B2DPoint(0.0, 0.0));
177
178 rNewTransform.translate(-aBasePoint.getX(), -aBasePoint.getY());
179 rNewTransform.rotate(fRotation);
180 rNewTransform.translate(aBasePoint.getX(), aBasePoint.getY());
181 }
182
183 return true;
184 }
185
187 SvgDocument& rDocument,
188 SvgNode* pParent,
189 OUString aText)
190 : SvgNode(SVGToken::Character, rDocument, pParent),
191 maText(std::move(aText))
192 {
193 }
194
196 {
197 }
198
200 {
201 // no own style, use parent's
202 if(getParent())
203 {
205 }
206 else
207 {
208 return nullptr;
209 }
210 }
211
213 SvgTextPosition& rSvgTextPosition,
214 const SvgStyleAttributes& rSvgStyleAttributes) const
215 {
216 // prepare retval, index and length
218 sal_uInt32 nLength(getText().getLength());
219
220 if(nLength)
221 {
222 sal_uInt32 nIndex(0);
223 // prepare FontAttribute
224 const SvgStringVector& rFontFamilyVector = rSvgStyleAttributes.getFontFamily();
225 OUString aFontFamily("Times New Roman");
226 if(!rFontFamilyVector.empty())
227 aFontFamily=rFontFamilyVector[0];
228
229 // #i122324# if the FontFamily name ends on ' embedded' it is probably a re-import
230 // of a SVG export with font embedding. Remove this to make font matching work. This
231 // is pretty safe since there should be no font family names ending on ' embedded'.
232 // Remove again when FontEmbedding is implemented in SVG import
233 if(aFontFamily.endsWith(" embedded"))
234 {
235 aFontFamily = aFontFamily.copy(0, aFontFamily.getLength() - 9);
236 }
237
238 const ::FontWeight nFontWeight(getVclFontWeight(rSvgStyleAttributes.getFontWeight()));
239 bool bItalic(FontStyle::italic == rSvgStyleAttributes.getFontStyle() || FontStyle::oblique == rSvgStyleAttributes.getFontStyle());
240
241 const drawinglayer::attribute::FontAttribute aFontAttribute(
242 aFontFamily,
243 OUString(),
244 nFontWeight,
245 false/*bSymbol*/,
246 false/*bVertical*/,
247 bItalic,
248 false/*bMonospaced*/,
249 false/*bOutline*/,
250 false/*bRTL*/,
251 false/*bBiDiStrong*/);
252
253 // prepare FontSizeNumber
254 double fFontWidth(rSvgStyleAttributes.getFontSizeNumber().solve(*this));
255 double fFontHeight(fFontWidth);
256
257 // prepare locale
258 css::lang::Locale aLocale;
259
260 // prepare TextLayouterDevice
261 TextLayouterDevice aTextLayouterDevice;
262 aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale);
263
264 // prepare TextArray
265 ::std::vector< double > aTextArray(rSvgTextPosition.getX());
266 if(!aTextArray.empty() && aTextArray.size() < nLength)
267 {
268 const sal_uInt32 nArray(aTextArray.size());
269
270 double fStartX(0.0);
271
272 if(rSvgTextPosition.getParent() && rSvgTextPosition.getParent()->getAbsoluteX())
273 {
274 fStartX = rSvgTextPosition.getParent()->getPosition().getX();
275 }
276 else
277 {
278 fStartX = aTextArray[nArray - 1];
279 }
280
281 ::std::vector< double > aExtendArray(aTextLayouterDevice.getTextArray(getText(), nArray, nLength - nArray));
282 aTextArray.reserve(nLength);
283
284 for(const auto &a : aExtendArray)
285 {
286 aTextArray.push_back(a + fStartX);
287 }
288 }
289
290 // get current TextPosition and TextWidth in units
291 basegfx::B2DPoint aPosition(rSvgTextPosition.getPosition());
292 double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength));
293
294 // check for user-given TextLength
295 if(0.0 != rSvgTextPosition.getTextLength()
296 && !basegfx::fTools::equal(fTextWidth, rSvgTextPosition.getTextLength()))
297 {
298 const double fFactor(rSvgTextPosition.getTextLength() / fTextWidth);
299
300 if(rSvgTextPosition.getLengthAdjust())
301 {
302 // spacing, need to create and expand TextArray
303 if(aTextArray.empty())
304 {
305 aTextArray = aTextLayouterDevice.getTextArray(getText(), nIndex, nLength);
306 }
307
308 for(auto &a : aTextArray)
309 {
310 a *= fFactor;
311 }
312 }
313 else
314 {
315 // spacing and glyphs, just apply to FontWidth
316 fFontWidth *= fFactor;
317 }
318
319 fTextWidth = rSvgTextPosition.getTextLength();
320 }
321
322 // get TextAlign
323 TextAlign aTextAlign(rSvgStyleAttributes.getTextAlign());
324
325 // map TextAnchor to TextAlign, there seems not to be a difference
326 if(TextAnchor::notset != rSvgStyleAttributes.getTextAnchor())
327 {
328 switch(rSvgStyleAttributes.getTextAnchor())
329 {
331 {
332 aTextAlign = TextAlign::left;
333 break;
334 }
336 {
337 aTextAlign = TextAlign::center;
338 break;
339 }
340 case TextAnchor::end:
341 {
342 aTextAlign = TextAlign::right;
343 break;
344 }
345 default:
346 {
347 break;
348 }
349 }
350 }
351
352 // apply TextAlign
353 switch(aTextAlign)
354 {
355 case TextAlign::right:
356 {
357 aPosition.setX(aPosition.getX() - fTextWidth);
358 break;
359 }
361 {
362 aPosition.setX(aPosition.getX() - (fTextWidth * 0.5));
363 break;
364 }
366 case TextAlign::left:
368 {
369 // TextAlign::notset, TextAlign::left: nothing to do
370 // TextAlign::justify is not clear currently; handle as TextAlign::left
371 break;
372 }
373 }
374
375 // get BaselineShift
376 const BaselineShift aBaselineShift(rSvgStyleAttributes.getBaselineShift());
377
378 // apply BaselineShift
379 switch(aBaselineShift)
380 {
382 {
383 aPosition.setY(aPosition.getY() + aTextLayouterDevice.getUnderlineOffset());
384 break;
385 }
387 {
388 aPosition.setY(aPosition.getY() + aTextLayouterDevice.getOverlineOffset());
389 break;
390 }
393 {
394 const SvgNumber aNumber(rSvgStyleAttributes.getBaselineShiftNumber());
395 const double mfBaselineShift(aNumber.solve(*this));
396
397 aPosition.setY(aPosition.getY() + mfBaselineShift);
398 break;
399 }
400 default: // BaselineShift::Baseline
401 {
402 // nothing to do
403 break;
404 }
405 }
406
407 // get fill color
408 basegfx::BColor aFill(0, 0, 0);
409 if(rSvgStyleAttributes.getFill())
410 aFill = *rSvgStyleAttributes.getFill();
411
412 // get fill opacity
413 double fFillOpacity = 1.0;
414 if (rSvgStyleAttributes.getFillOpacity().isSet())
415 {
416 fFillOpacity = rSvgStyleAttributes.getFillOpacity().getNumber();
417 }
418
419 // prepare TextTransformation
420 basegfx::B2DHomMatrix aTextTransform;
421
422 aTextTransform.scale(fFontWidth, fFontHeight);
423 aTextTransform.translate(aPosition.getX(), aPosition.getY());
424
425 // check TextDecoration and if TextDecoratedPortionPrimitive2D is needed
426 const TextDecoration aDeco(rSvgStyleAttributes.getTextDecoration());
427
428 if(TextDecoration::underline == aDeco
429 || TextDecoration::overline == aDeco
431 {
432 // get the fill for decoration as described by SVG. We cannot
433 // have different stroke colors/definitions for those, though
434 const SvgStyleAttributes* pDecoDef = rSvgStyleAttributes.getTextDecorationDefiningSvgStyleAttributes();
435
436 basegfx::BColor aDecoColor(aFill);
437 if(pDecoDef && pDecoDef->getFill())
438 aDecoColor = *pDecoDef->getFill();
439
440 TextLine eFontOverline = TEXT_LINE_NONE;
441 if(TextDecoration::overline == aDeco)
442 eFontOverline = TEXT_LINE_SINGLE;
443
444 TextLine eFontUnderline = TEXT_LINE_NONE;
445 if(TextDecoration::underline == aDeco)
446 eFontUnderline = TEXT_LINE_SINGLE;
447
448 TextStrikeout eTextStrikeout = TEXT_STRIKEOUT_NONE;
450 eTextStrikeout = TEXT_STRIKEOUT_SINGLE;
451
452 // create decorated text primitive
454 aTextTransform,
455 getText(),
456 nIndex,
457 nLength,
458 std::move(aTextArray),
459 {},
460 aFontAttribute,
461 aLocale,
462 aFill,
464
465 // extra props for decorated
466 aDecoColor,
467 aDecoColor,
468 eFontOverline,
469 eFontUnderline,
470 false,
471 eTextStrikeout,
472 false,
474 true,
475 false,
477 false);
478 }
479 else
480 {
481 // create text primitive
482 pRetval = new TextSimplePortionPrimitive2D(
483 aTextTransform,
484 getText(),
485 nIndex,
486 nLength,
487 std::move(aTextArray),
488 {},
489 aFontAttribute,
490 aLocale,
491 aFill);
492 }
493
494 if (fFillOpacity != 1.0)
495 {
496 pRetval = new UnifiedTransparencePrimitive2D(
498 1.0 - fFillOpacity);
499 }
500
501 // advance current TextPosition
502 rSvgTextPosition.setPosition(rSvgTextPosition.getPosition() + basegfx::B2DVector(fTextWidth, 0.0));
503 }
504
505 return pRetval;
506 }
507
509 Primitive2DContainer& rTarget,
510 SvgTextPosition& rSvgTextPosition,
511 const SvgStyleAttributes& rSvgStyleAttributes) const
512 {
513 const Primitive2DReference xRef(
515 rSvgTextPosition,
516 rSvgStyleAttributes));
517
518 if(!(xRef.is() && (Visibility::visible == rSvgStyleAttributes.getVisibility())))
519 return;
520
521 if(!rSvgTextPosition.isRotated())
522 {
523 rTarget.push_back(xRef);
524 }
525 else
526 {
527 // need to apply rotations to each character as given
528 const TextSimplePortionPrimitive2D* pCandidate =
529 dynamic_cast< const TextSimplePortionPrimitive2D* >(xRef.get());
530
531 if(pCandidate)
532 {
533 localTextBreakupHelper alocalTextBreakupHelper(*pCandidate, rSvgTextPosition);
534 Primitive2DContainer aResult = alocalTextBreakupHelper.extractResult();
535
536 if(!aResult.empty())
537 {
538 rTarget.append(std::move(aResult));
539 }
540
541 // also consume for the implied single space
542 rSvgTextPosition.consumeRotation();
543 }
544 else
545 {
546 OSL_ENSURE(false, "Used primitive is not a text primitive (!)");
547 }
548 }
549 }
550
552 {
553 bool bIsDefault(XmlSpace::Default == getXmlSpace());
554 // if xml:space="default" then remove all newline characters, otherwise convert them to space
555 // convert tab to space too
556 maText = maTextBeforeSpaceHandling = maText.replaceAll(u"\n", bIsDefault ? u"" : u" ").replaceAll(u"\t", u" ");
557
558 if(bIsDefault)
559 {
560 // strip of all leading and trailing spaces
561 // and consolidate contiguous space
563 }
564 }
565
567 {
568 maText += " ";
569 }
570
571 void SvgCharacterNode::concatenate(std::u16string_view rText)
572 {
573 maText += rText;
574 }
575
577 {
578 if(!getText().isEmpty())
579 {
580 const SvgStyleAttributes* pSvgStyleAttributes = getSvgStyleAttributes();
581
582 if(pSvgStyleAttributes)
583 {
584 decomposeTextWithStyle(rTarget, rSvgTextPosition, *pSvgStyleAttributes);
585 }
586 }
587 }
588
589
591 SvgTextPosition* pParent,
592 const InfoProvider& rInfoProvider,
593 const SvgTextPositions& rSvgTextPositions)
594 : mpParent(pParent),
595 maRotate(solveSvgNumberVector(rSvgTextPositions.getRotate(), rInfoProvider)),
596 mfTextLength(0.0),
597 mnRotationIndex(0),
598 mbLengthAdjust(rSvgTextPositions.getLengthAdjust()),
599 mbAbsoluteX(false)
600 {
601 // get TextLength if provided
602 if(rSvgTextPositions.getTextLength().isSet())
603 {
604 mfTextLength = rSvgTextPositions.getTextLength().solve(rInfoProvider);
605 }
606
607 // SVG does not really define in which units a \91rotate\92 for Text/TSpan is given,
608 // but it seems to be degrees. Convert here to radians
609 if(!maRotate.empty())
610 {
611 for (double& f : maRotate)
612 {
613 f = basegfx::deg2rad(f);
614 }
615 }
616
617 // get text positions X
618 const sal_uInt32 nSizeX(rSvgTextPositions.getX().size());
619
620 if(nSizeX)
621 {
622 // we have absolute positions, get first one as current text position X
623 maPosition.setX(rSvgTextPositions.getX()[0].solve(rInfoProvider, NumberType::xcoordinate));
624 mbAbsoluteX = true;
625 }
626 else
627 {
628 // no absolute position, get from parent
629 if(pParent)
630 {
631 maPosition.setX(pParent->getPosition().getX());
632 }
633 }
634
635 const sal_uInt32 nSizeDx(rSvgTextPositions.getDx().size());
636 if(nSizeDx)
637 {
638 // relative positions given, translate position derived from parent
639 maPosition.setX(maPosition.getX() + rSvgTextPositions.getDx()[0].solve(rInfoProvider, NumberType::xcoordinate));
640 }
641
642 // fill deltas to maX
643 maX.reserve(nSizeX);
644
645 for(sal_uInt32 a(1); a < nSizeX; a++)
646 {
647 double nPos = rSvgTextPositions.getX()[a].solve(rInfoProvider, NumberType::xcoordinate) - maPosition.getX();
648
649 if(a < nSizeDx)
650 {
651 nPos += rSvgTextPositions.getDx()[a].solve(rInfoProvider, NumberType::xcoordinate);
652 }
653
654 maX.push_back(nPos);
655 }
656
657 // get text positions Y
658 const sal_uInt32 nSizeY(rSvgTextPositions.getY().size());
659
660 if(nSizeY)
661 {
662 // we have absolute positions, get first one as current text position Y
663 maPosition.setY(rSvgTextPositions.getY()[0].solve(rInfoProvider, NumberType::ycoordinate));
664 mbAbsoluteX = true;
665 }
666 else
667 {
668 // no absolute position, get from parent
669 if(pParent)
670 {
671 maPosition.setY(pParent->getPosition().getY());
672 }
673 }
674
675 const sal_uInt32 nSizeDy(rSvgTextPositions.getDy().size());
676
677 if(nSizeDy)
678 {
679 // relative positions given, translate position derived from parent
680 maPosition.setY(maPosition.getY() + rSvgTextPositions.getDy()[0].solve(rInfoProvider, NumberType::ycoordinate));
681 }
682
683 // fill deltas to maY
684 maY.reserve(nSizeY);
685
686 for(sal_uInt32 a(1); a < nSizeY; a++)
687 {
688 double nPos = rSvgTextPositions.getY()[a].solve(rInfoProvider, NumberType::ycoordinate) - maPosition.getY();
689
690 if(a < nSizeDy)
691 {
692 nPos += rSvgTextPositions.getDy()[a].solve(rInfoProvider, NumberType::ycoordinate);
693 }
694
695 maY.push_back(nPos);
696 }
697 }
698
700 {
701 if(maRotate.empty())
702 {
703 if(getParent())
704 {
705 return getParent()->isRotated();
706 }
707 else
708 {
709 return false;
710 }
711 }
712 else
713 {
714 return true;
715 }
716 }
717
719 {
720 double fRetval(0.0);
721
722 if(maRotate.empty())
723 {
724 if(getParent())
725 {
726 fRetval = mpParent->consumeRotation();
727 }
728 else
729 {
730 fRetval = 0.0;
731 }
732 }
733 else
734 {
735 const sal_uInt32 nSize(maRotate.size());
736
737 if(mnRotationIndex < nSize)
738 {
739 fRetval = maRotate[mnRotationIndex++];
740 }
741 else
742 {
743 fRetval = maRotate[nSize - 1];
744 }
745 }
746
747 return fRetval;
748 }
749
750} // end of namespace svgio
751
752/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Text maText
void rotate(double fRadiant)
void translate(double fX, double fY)
void scale(double fX, double fY)
TYPE getX() const
void setY(TYPE fY)
TYPE getY() const
void setX(TYPE fX)
void setFontAttribute(const attribute::FontAttribute &rFontAttribute, double fFontScaleX, double fFontScaleY, const css::lang::Locale &rLocale)
double getTextWidth(const OUString &rText, sal_uInt32 nIndex, sal_uInt32 nLength) const
::std::vector< double > getTextArray(const OUString &rText, sal_uInt32 nIndex, sal_uInt32 nLength, bool bCaret=false) const
void decomposeTextWithStyle(drawinglayer::primitive2d::Primitive2DContainer &rTarget, SvgTextPosition &rSvgTextPosition, const SvgStyleAttributes &rSvgStyleAttributes) const
void concatenate(std::u16string_view rText)
SvgCharacterNode(SvgDocument &rDocument, SvgNode *pParent, OUString aText)
virtual const SvgStyleAttributes * getSvgStyleAttributes() const override
void decomposeText(drawinglayer::primitive2d::Primitive2DContainer &rTarget, SvgTextPosition &rSvgTextPosition) const
const OUString & getText() const
Text content.
rtl::Reference< drawinglayer::primitive2d::BasePrimitive2D > createSimpleTextPrimitive(SvgTextPosition &rSvgTextPosition, const SvgStyleAttributes &rSvgStyleAttributes) const
local helpers
XmlSpace getXmlSpace() const
XmlSpace access.
Definition: svgnode.cxx:779
const SvgNode * getParent() const
Definition: svgnode.hxx:158
virtual const SvgStyleAttributes * getSvgStyleAttributes() const
Definition: svgnode.cxx:37
double solve(const InfoProvider &rInfoProvider, NumberType aNumberType=NumberType::length) const
Definition: SvgNumber.cxx:69
double getNumber() const
Definition: SvgNumber.hxx:85
SvgNumber getFillOpacity() const
fill opacity content
const basegfx::BColor * getFill() const
const SvgStyleAttributes * getTextDecorationDefiningSvgStyleAttributes() const
TextDecoration content.
const SvgStringVector & getFontFamily() const
Font content.
TextAlign getTextAlign() const
TextAlign content.
FontStyle getFontStyle() const
FontStyle content.
FontWeight getFontWeight() const
FontWeight content.
Visibility getVisibility() const
Visibility.
TextAnchor getTextAnchor() const
TextAnchor content.
::std::vector< double > maRotate
const SvgTextPosition * getParent() const
const ::std::vector< double > & getX() const
void setPosition(const basegfx::B2DPoint &rNew)
const basegfx::B2DPoint & getPosition() const
SvgTextPosition(SvgTextPosition *pParent, const InfoProvider &rInfoProvider, const SvgTextPositions &rSvgTextPositions)
const SvgNumberVector & getY() const
Y content.
void setDx(SvgNumberVector &&aDx)
const SvgNumberVector & getX() const
X content.
void setY(SvgNumberVector &&aY)
const SvgNumberVector & getDy() const
Dy content.
void parseTextPositionAttributes(SVGToken aSVGToken, std::u16string_view aContent)
const SvgNumber & getTextLength() const
TextLength content.
void setX(SvgNumberVector &&aX)
void setDy(SvgNumberVector &&aDy)
void setTextLength(const SvgNumber &rTextLength)
void setRotate(SvgNumberVector &&aRotate)
const SvgNumberVector & getDx() const
Dx content.
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
RegionData_Impl * mpParent
float u
FilterGroup & rTarget
sal_Int32 nIndex
uno_Any a
sal_uInt16 nPos
bool equal(T const &rfValA, T const &rfValB)
double getLength(const B2DPolygon &rCandidate)
constexpr double deg2rad(double v)
TEXT_RELIEF_NONE
TEXT_FONT_EMPHASIS_MARK_NONE
TEXT_LINE_SINGLE
TEXT_LINE_NONE
TextStrikeout
TEXT_STRIKEOUT_SINGLE
TEXT_STRIKEOUT_NONE
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
::std::vector< double > solveSvgNumberVector(const SvgNumberVector &rInput, const InfoProvider &rInfoProvider)
Definition: svgtools.cxx:1499
::std::vector< OUString > SvgStringVector
Definition: svgtools.hxx:124
::FontWeight getVclFontWeight(FontWeight aSource)
OUString consolidateContiguousSpace(const OUString &rCandidate)
Definition: svgtools.cxx:1452
bool readSingleNumber(std::u16string_view rCandidate, SvgNumber &aNum)
Definition: svgtools.cxx:1076
std::vector< SvgNumber > SvgNumberVector
Definition: SvgNumber.hxx:111
bool readSvgNumberVector(std::u16string_view rCandidate, SvgNumberVector &rSvgNumberVector)
Definition: svgtools.cxx:1174
SvgTextPosition & mrSvgTextPosition
sal_Int32 nLength