LibreOffice Module starmath (master) 1
mathmlattr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <mathmlattr.hxx>
11
12#include <o3tl/safeint.hxx>
13#include <o3tl/string_view.hxx>
14#include <rtl/math.h>
15
16#include <cstddef>
17#include <string_view>
18#include <unordered_map>
19
20static std::size_t ParseMathMLUnsignedNumber(std::u16string_view rStr, Fraction& rUN)
21{
22 auto nLen = rStr.length();
23 std::size_t nDecimalPoint = std::u16string_view::npos;
24 std::size_t nIdx;
25 sal_Int64 nom = 0;
26 sal_Int64 den = 1;
27 bool validNomDen = true;
28 for (nIdx = 0; nIdx < nLen; nIdx++)
29 {
30 auto cD = rStr[nIdx];
31 if (cD == u'.')
32 {
33 if (nDecimalPoint != std::u16string_view::npos)
34 return std::u16string_view::npos;
35 nDecimalPoint = nIdx;
36 continue;
37 }
38 if (cD < u'0' || u'9' < cD)
39 break;
40 if (validNomDen
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))))
46 {
47 validNomDen = false;
48 }
49 }
50 if (nIdx == 0 || (nIdx == 1 && nDecimalPoint == 0))
51 return std::u16string_view::npos;
52
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:
57 if (validNomDen)
58 {
59 rUN = Fraction(nom, den);
60 }
61 else
62 {
63 rUN = Fraction(
64 rtl_math_uStringToDouble(rStr.data(), rStr.data() + nIdx, '.', 0, nullptr, nullptr));
65 }
66
67 return nIdx;
68}
69
70static std::size_t ParseMathMLNumber(std::u16string_view rStr, Fraction& rN)
71{
72 if (rStr.empty())
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;
79 if (bNegative)
80 rN *= -1;
81 return nOffset + nIdx;
82}
83
85{
86 auto nIdx = ParseMathMLNumber(rStr, rV.aNumber);
87 if (nIdx == std::u16string_view::npos)
88 return false;
89 std::u16string_view sRest = rStr.substr(nIdx);
90 if (sRest.empty())
91 {
93 }
94 if (o3tl::starts_with(sRest, u"em"))
95 {
97 }
98 if (o3tl::starts_with(sRest, u"ex"))
99 {
101 }
102 if (o3tl::starts_with(sRest, u"px"))
103 {
105 }
106 if (o3tl::starts_with(sRest, u"in"))
107 {
109 }
110 if (o3tl::starts_with(sRest, u"cm"))
111 {
113 }
114 if (o3tl::starts_with(sRest, u"mm"))
115 {
117 }
118 if (o3tl::starts_with(sRest, u"pt"))
119 {
121 }
122 if (o3tl::starts_with(sRest, u"pc"))
123 {
125 }
126 if (sRest[0] == u'%')
127 {
129 }
130 return true;
131}
132
134{
135 static const std::unordered_map<OUString, MathMLMathvariantValue> aMap{
136 { "normal", MathMLMathvariantValue::Normal },
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 }
154 };
155
156 auto it = aMap.find(rStr);
157 if (it != aMap.end())
158 {
159 rV = it->second;
160 return true;
161 }
162 return false;
163}
164
165/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
bool IsValid() const
float u
bool ParseMathMLAttributeLengthValue(std::u16string_view rStr, MathMLAttributeLengthValue &rV)
Definition: mathmlattr.cxx:84
static std::size_t ParseMathMLNumber(std::u16string_view rStr, Fraction &rN)
Definition: mathmlattr.cxx:70
bool GetMathMLMathvariantValue(const OUString &rStr, MathMLMathvariantValue &rV)
Definition: mathmlattr.cxx:133
static std::size_t ParseMathMLUnsignedNumber(std::u16string_view rStr, Fraction &rUN)
Definition: mathmlattr.cxx:20
MathMLMathvariantValue
Definition: mathmlattr.hxx:56
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
HashMap_OWString_Interface aMap
MathMLLengthUnit eUnit
Definition: mathmlattr.hxx:43