1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <mathmlattr.hxx>
12 #include <o3tl/safeint.hxx>
13 #include <o3tl/string_view.hxx>
17 #include <string_view>
18 #include <unordered_map>
20 static std::size_t ParseMathMLUnsignedNumber(std::u16string_view rStr
, Fraction
& rUN
)
22 auto nLen
= rStr
.length();
23 std::size_t nDecimalPoint
= std::u16string_view::npos
;
27 bool validNomDen
= true;
28 for (nIdx
= 0; nIdx
< nLen
; nIdx
++)
33 if (nDecimalPoint
!= std::u16string_view::npos
)
34 return std::u16string_view::npos
;
38 if (cD
< u
'0' || u
'9' < cD
)
41 && (o3tl::checked_multiply(nom
, sal_Int64(10), nom
)
42 || o3tl::checked_add(nom
, sal_Int64(cD
- u
'0'), nom
)
43 || nom
>= std::numeric_limits
<sal_Int32
>::max()
44 || (nDecimalPoint
!= std::u16string_view::npos
45 && o3tl::checked_multiply(den
, sal_Int64(10), den
))))
50 if (nIdx
== 0 || (nIdx
== 1 && nDecimalPoint
== 0))
51 return std::u16string_view::npos
;
53 // If the input "xx.yyy" can be represented with nom = xx*10^n + yyy and den = 10^n in sal_Int64
54 // (where n is the length of "yyy"), then use that to create an accurate Fraction (and TODO: we
55 // could even ignore trailing "0" characters in "yyy", for a smaller n and thus a greater chance
56 // of validNomDen); if not, use the less accurate approach of creating a Fraction from double:
59 rUN
= Fraction(nom
, den
);
64 rtl_math_uStringToDouble(rStr
.data(), rStr
.data() + nIdx
, '.', 0, nullptr, nullptr));
70 static std::size_t ParseMathMLNumber(std::u16string_view rStr
, Fraction
& rN
)
73 return std::u16string_view::npos
;
74 bool bNegative
= (rStr
[0] == '-');
75 std::size_t nOffset
= bNegative
? 1 : 0;
76 auto nIdx
= ParseMathMLUnsignedNumber(rStr
.substr(nOffset
), rN
);
77 if (nIdx
== std::u16string_view::npos
|| !rN
.IsValid())
78 return std::u16string_view::npos
;
81 return nOffset
+ nIdx
;
84 bool ParseMathMLAttributeLengthValue(std::u16string_view rStr
, MathMLAttributeLengthValue
& rV
)
86 auto nIdx
= ParseMathMLNumber(rStr
, rV
.aNumber
);
87 if (nIdx
== std::u16string_view::npos
)
89 std::u16string_view sRest
= rStr
.substr(nIdx
);
92 rV
.eUnit
= MathMLLengthUnit::None
;
94 if (o3tl::starts_with(sRest
, u
"em"))
96 rV
.eUnit
= MathMLLengthUnit::Em
;
98 if (o3tl::starts_with(sRest
, u
"ex"))
100 rV
.eUnit
= MathMLLengthUnit::Ex
;
102 if (o3tl::starts_with(sRest
, u
"px"))
104 rV
.eUnit
= MathMLLengthUnit::Px
;
106 if (o3tl::starts_with(sRest
, u
"in"))
108 rV
.eUnit
= MathMLLengthUnit::In
;
110 if (o3tl::starts_with(sRest
, u
"cm"))
112 rV
.eUnit
= MathMLLengthUnit::Cm
;
114 if (o3tl::starts_with(sRest
, u
"mm"))
116 rV
.eUnit
= MathMLLengthUnit::Mm
;
118 if (o3tl::starts_with(sRest
, u
"pt"))
120 rV
.eUnit
= MathMLLengthUnit::Pt
;
122 if (o3tl::starts_with(sRest
, u
"pc"))
124 rV
.eUnit
= MathMLLengthUnit::Pc
;
126 if (sRest
[0] == u
'%')
128 rV
.eUnit
= MathMLLengthUnit::Percent
;
133 bool GetMathMLMathvariantValue(const OUString
& rStr
, MathMLMathvariantValue
& rV
)
135 static const std::unordered_map
<OUString
, MathMLMathvariantValue
> aMap
{
136 { "normal", MathMLMathvariantValue::Normal
},
137 { "bold", MathMLMathvariantValue::Bold
},
138 { "italic", MathMLMathvariantValue::Italic
},
139 { "bold-italic", MathMLMathvariantValue::BoldItalic
},
140 { "double-struck", MathMLMathvariantValue::DoubleStruck
},
141 { "bold-fraktur", MathMLMathvariantValue::BoldFraktur
},
142 { "script", MathMLMathvariantValue::Script
},
143 { "bold-script", MathMLMathvariantValue::BoldScript
},
144 { "fraktur", MathMLMathvariantValue::Fraktur
},
145 { "sans-serif", MathMLMathvariantValue::SansSerif
},
146 { "bold-sans-serif", MathMLMathvariantValue::BoldSansSerif
},
147 { "sans-serif-italic", MathMLMathvariantValue::SansSerifItalic
},
148 { "sans-serif-bold-italic", MathMLMathvariantValue::SansSerifBoldItalic
},
149 { "monospace", MathMLMathvariantValue::Monospace
},
150 { "initial", MathMLMathvariantValue::Initial
},
151 { "tailed", MathMLMathvariantValue::Tailed
},
152 { "looped", MathMLMathvariantValue::Looped
},
153 { "stretched", MathMLMathvariantValue::Stretched
}
156 auto it
= aMap
.find(rStr
);
157 if (it
!= aMap
.end())
165 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */