Files
libreoffice/starmath/source/mathmlattr.cxx
Takeshi Abe 2bad9f1cd8 tdf#103430 Apply mathvariant attribute to <mi> and <mo>
by emulating it with SmFontNode.
In case of <mo>, current implementation supports only the one named
with an alphabet.

Change-Id: I827a7e80f5aa94e243098a6e50eb758cf915c282
Reviewed-on: https://gerrit.libreoffice.org/31240
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Takeshi Abe <tabe@fixedpoint.jp>
2016-11-29 01:04:08 +00:00

183 lines
5.1 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "mathmlattr.hxx"
#include <cassert>
#include <unordered_map>
namespace {
sal_Int32 lcl_GetPowerOf10(sal_Int32 nPower)
{
assert(nPower > 0);
sal_Int32 nResult = 1;
while (nPower--)
nResult *= 10;
return nResult;
}
}
sal_Int32 ParseMathMLUnsignedNumber(const OUString &rStr, Fraction *pUN)
{
assert(pUN);
auto nLen = rStr.getLength();
sal_Int32 nDecimalPoint = -1;
sal_Int32 nIdx;
for (nIdx = 0; nIdx < nLen; nIdx++)
{
auto cD = rStr[nIdx];
if (cD == sal_Unicode('.'))
{
if (nDecimalPoint >= 0)
return -1;
nDecimalPoint = nIdx;
continue;
}
if (cD < sal_Unicode('0') || sal_Unicode('9') < cD)
break;
}
if (nIdx == 0 || (nIdx == 1 && nDecimalPoint == 0))
return -1;
if (nDecimalPoint == -1)
{
assert(nIdx > 0);
*pUN = Fraction(rStr.copy(0, nIdx).toInt32(), 1);
return nIdx;
}
if (nDecimalPoint == 0)
{
assert(nIdx > 1);
*pUN = Fraction(rStr.copy(1, nIdx-1).toInt32(), lcl_GetPowerOf10(nIdx-1));
return nIdx;
}
assert(0 < nDecimalPoint);
assert(nDecimalPoint < nIdx);
*pUN = Fraction(rStr.copy(0, nDecimalPoint).toInt32(), 1);
if (++nDecimalPoint < nIdx)
*pUN += Fraction(rStr.copy(nDecimalPoint, nIdx-nDecimalPoint).toInt32(),
lcl_GetPowerOf10(nIdx-nDecimalPoint));
return nIdx;
}
sal_Int32 ParseMathMLNumber(const OUString &rStr, Fraction *pN)
{
assert(pN);
if (rStr.isEmpty())
return -1;
bool bNegative = (rStr[0] == sal_Unicode('-'));
sal_Int32 nOffset = bNegative ? 1 : 0;
Fraction aF;
auto nIdx = ParseMathMLUnsignedNumber(rStr.copy(nOffset), &aF);
if (nIdx <= 0)
return -1;
if (bNegative)
*pN = Fraction(aF.GetNumerator(), aF.GetDenominator());
else
*pN = aF;
return nOffset + nIdx;
}
sal_Int32 ParseMathMLAttributeLengthValue(const OUString &rStr, MathMLAttributeLengthValue *pV)
{
assert(pV);
auto nIdx = ParseMathMLNumber(rStr, &pV->aNumber);
if (nIdx <= 0)
return -1;
OUString sRest = rStr.copy(nIdx);
if (sRest.isEmpty())
{
pV->eUnit = MathMLLengthUnit::None;
return nIdx;
}
if (sRest.startsWith("em"))
{
pV->eUnit = MathMLLengthUnit::Em;
return nIdx + 2;
}
if (sRest.startsWith("ex"))
{
pV->eUnit = MathMLLengthUnit::Ex;
return nIdx + 2;
}
if (sRest.startsWith("px"))
{
pV->eUnit = MathMLLengthUnit::Px;
return nIdx + 2;
}
if (sRest.startsWith("in"))
{
pV->eUnit = MathMLLengthUnit::In;
return nIdx + 2;
}
if (sRest.startsWith("cm"))
{
pV->eUnit = MathMLLengthUnit::Cm;
return nIdx + 2;
}
if (sRest.startsWith("mm"))
{
pV->eUnit = MathMLLengthUnit::Mm;
return nIdx + 2;
}
if (sRest.startsWith("pt"))
{
pV->eUnit = MathMLLengthUnit::Pt;
return nIdx + 2;
}
if (sRest.startsWith("pc"))
{
pV->eUnit = MathMLLengthUnit::Pc;
return nIdx + 2;
}
if (sRest[0] == sal_Unicode('%'))
{
pV->eUnit = MathMLLengthUnit::Percent;
return nIdx + 2;
}
return nIdx;
}
bool GetMathMLMathvariantValue(const OUString &rStr, MathMLMathvariantValue *pV)
{
static const std::unordered_map<OUString, MathMLMathvariantValue, OUStringHash> aMap{
{"normal", MathMLMathvariantValue::Normal},
{"bold", MathMLMathvariantValue::Bold},
{"italic", MathMLMathvariantValue::Italic},
{"bold-italic", MathMLMathvariantValue::BoldItalic},
{"double-struck", MathMLMathvariantValue::DoubleStruck},
{"bold-fraktur", MathMLMathvariantValue::BoldFraktur},
{"script", MathMLMathvariantValue::Script},
{"bold-script", MathMLMathvariantValue::BoldScript},
{"fraktur", MathMLMathvariantValue::Fraktur},
{"sans-serif", MathMLMathvariantValue::SansSerif},
{"bold-sans-serif", MathMLMathvariantValue::BoldSansSerif},
{"sans-serif-italic", MathMLMathvariantValue::SansSerifItalic},
{"sans-serif-bold-italic", MathMLMathvariantValue::SansSerifBoldItalic},
{"monospace", MathMLMathvariantValue::Monospace},
{"initial", MathMLMathvariantValue::Initial},
{"tailed", MathMLMathvariantValue::Tailed},
{"looped", MathMLMathvariantValue::Looped},
{"stretched", MathMLMathvariantValue::Stretched}
};
assert(pV);
auto it = aMap.find(rStr);
if (it != aMap.end())
{
*pV = it->second;
return true;
}
return false;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */