// Set base URI
OUString const baseURI(rMedium.GetBaseURL()); // needed for relative URLs; but it's OK to import e.g. MathML from the // clipboard without one
SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL");
xInfoSet->setPropertyValue(u"BaseURI"_ustr, Any(baseURI));
sal_Int32 nSteps = 3; if (!(rMedium.IsStorage()))
nSteps = 1;
sal_Int32 nProgressRange(nSteps); if (xStatusIndicator.is())
{
xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
}
nSteps = 0; if (xStatusIndicator.is())
xStatusIndicator->setValue(nSteps++);
if (rMedium.IsStorage())
{ // TODO/LATER: handle the case of embedded links gracefully if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
{
OUString aName(u"dummyObjName"_ustr); const SfxStringItem* pDocHierarchItem
= rMedium.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME); if (pDocHierarchItem)
aName = pDocHierarchItem->GetValue();
if (!aName.isEmpty())
{
xInfoSet->setPropertyValue(u"StreamRelPath"_ustr, Any(aName));
}
}
bool bOASIS = (SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60); if (xStatusIndicator.is())
xStatusIndicator->setValue(nSteps++);
// determine if stream is encrypted or not
uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
Any aAny = xProps->getPropertyValue(u"Encrypted"_ustr); bool bEncrypted = false; if (aAny.getValueType() == cppu::UnoType<bool>::get())
aAny >>= bEncrypted;
// set Base URL if (rPropSet.is())
{
rPropSet->setPropertyValue(u"StreamName"_ustr, Any(sStreamName));
}
void SmXMLImport::endDocument()
{ //Set the resulted tree into the SmDocShell where it belongs
std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack); if (pTree && pTree->GetType() == SmNodeType::Table)
{
uno::Reference<frame::XModel> xModel = GetModel();
SmModel* pModel = dynamic_cast<SmModel*>(xModel.get());
if (pModel)
{
SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); auto pTreeTmp = pTree.get();
pDocShell->SetFormulaTree(static_cast<SmTableNode*>(pTree.release())); if (aText.isEmpty()) //If we picked up no annotation text
{ // Get text from imported formula
SmNodeToTextVisitor tmpvisitor(pTreeTmp, aText);
}
void SmXMLContext_Helper::RetrieveAttrs( const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
{ bool bMvFound = false; for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
{ // sometimes they have namespace, sometimes not? switch (aIter.getToken() & TOKEN_MASK)
{ case XML_FONTWEIGHT:
nIsBold = sal_Int8(IsXMLToken(aIter, XML_BOLD)); break; case XML_FONTSTYLE:
nIsItalic = sal_Int8(IsXMLToken(aIter, XML_ITALIC)); break; case XML_FONTSIZE: case XML_MATHSIZE:
{
OUString sValue = aIter.toString();
::sax::Converter::convertDouble(nFontSize, sValue);
rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
util::MeasureUnit::POINT); if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
{ if (-1 == sValue.indexOf('%'))
nFontSize = 0.0; else
{
rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
util::MeasureUnit::PERCENT);
}
} break;
} case XML_FONTFAMILY:
sFontFamily = aIter.toString(); break; case XML_COLOR: case XML_MATHCOLOR:
sColor = aIter.toString(); break; case XML_MATHVARIANT:
bMvFound = true; break; default:
XMLOFF_WARN_UNKNOWN("starmath", aIter); break;
}
}
if (bMvFound)
{ // Ignore deprecated attributes fontfamily, fontweight, and fontstyle // in favor of mathvariant, as specified in // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
sFontFamily.clear();
nIsBold = -1;
nIsItalic = -1;
}
}
pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
rNodeStack.push_front(std::move(pFontNode));
} if (!sColor.isEmpty())
{
SmColorTokenTableEntry aSmColorTokenTableEntry;
aSmColorTokenTableEntry = starmathdatabase::Identify_ColorName_HTML(sColor); if (aSmColorTokenTableEntry.eType == TRGB)
aSmColorTokenTableEntry = starmathdatabase::Identify_Color_Parser(
sal_uInt32(aSmColorTokenTableEntry.cColor)); if (aSmColorTokenTableEntry.eType != TERROR)
{
aToken = aSmColorTokenTableEntry;
std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
rNodeStack.push_front(std::move(pFontNode));
} // If not known, not implemented yet. Giving up.
} if (sFontFamily.isEmpty()) return;
if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
aToken.eType = TFIXED; elseif (sFontFamily.equalsIgnoreAsciiCase("sans"))
aToken.eType = TSANS; elseif (sFontFamily.equalsIgnoreAsciiCase("serif"))
aToken.eType = TSERIF; else//Just give up, we need to extend our font mechanism to be //more general return;
std::vector<SmTokenType> vVariant;
MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv; switch (eMv)
{ case MathMLMathvariantValue::Normal:
vVariant.push_back(TNITALIC); break; case MathMLMathvariantValue::Bold: case MathMLMathvariantValue::BoldFraktur: // TODO: Fraktur case MathMLMathvariantValue::BoldScript: // TODO: Script
vVariant.push_back(TBOLD); break; case MathMLMathvariantValue::Italic: // nothing to do break; case MathMLMathvariantValue::BoldItalic:
vVariant.push_back(TITALIC);
vVariant.push_back(TBOLD); break; case MathMLMathvariantValue::DoubleStruck: // TODO break; case MathMLMathvariantValue::Script: // TODO break; case MathMLMathvariantValue::Fraktur: // TODO break; case MathMLMathvariantValue::SansSerif:
vVariant.push_back(TSANS); break; case MathMLMathvariantValue::BoldSansSerif:
vVariant.push_back(TSANS);
vVariant.push_back(TBOLD); break; case MathMLMathvariantValue::SansSerifItalic:
vVariant.push_back(TITALIC);
vVariant.push_back(TSANS); break; case MathMLMathvariantValue::SansSerifBoldItalic:
vVariant.push_back(TITALIC);
vVariant.push_back(TBOLD);
vVariant.push_back(TSANS); break; case MathMLMathvariantValue::Monospace:
vVariant.push_back(TFIXED); break; case MathMLMathvariantValue::Initial: case MathMLMathvariantValue::Tailed: case MathMLMathvariantValue::Looped: case MathMLMathvariantValue::Stretched: // TODO break;
} if (vVariant.empty()) return;
SmNodeStack& rNodeStack = mrContext.GetSmImport().GetNodeStack(); for (auto eType : vVariant)
{
SmToken aToken;
aToken.eType = eType;
aToken.cMathChar = u""_ustr;
aToken.nLevel = 5;
std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
rNodeStack.push_front(std::move(pFontNode));
}
}
namespace
{ class SmXMLDocContext_Impl : public SmXMLImportContext
{ public:
SmXMLDocContext_Impl(SmXMLImport& rImport)
: SmXMLImportContext(rImport)
{
}
class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl
{ public: // TODO/LATER: convert <menclose notation="horizontalstrike"> into // "overstrike{}" and extend the Math syntax to support more notations
SmXMLEncloseContext_Impl(SmXMLImport& rImport)
: SmXMLRowContext_Impl(rImport)
{
}
class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
{ protected:
SmXMLContext_Helper aStyleHelper;
public: /*Right now the style tag is completely ignored*/
SmXMLStyleContext_Impl(SmXMLImport& rImport)
: SmXMLRowContext_Impl(rImport)
, aStyleHelper(*this)
{
}
namespace
{ class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
{ public: /*Right now the style tag is completely ignored*/
SmXMLPaddedContext_Impl(SmXMLImport& rImport)
: SmXMLRowContext_Impl(rImport)
{
}
namespace
{ class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
{ public: /*Right now the style tag is completely ignored*/
SmXMLPhantomContext_Impl(SmXMLImport& rImport)
: SmXMLRowContext_Impl(rImport)
{
}
pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight)); // mfenced is always scalable. Stretchy keyword is not official, but in case of been in there // can be used as a hint.
pSNode->SetScaleMode(SmScaleMode::Height);
GetSmImport().GetNodeStack().push_front(std::move(pSNode));
}
namespace
{ class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
{ public:
SmXMLErrorContext_Impl(SmXMLImport& rImport)
: SmXMLRowContext_Impl(rImport)
{
}
void SmXMLOperatorContext_Impl::endFastElement(sal_Int32)
{
std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken)); //For stretchy scaling the scaling must be retrieved from this node //and applied to the expression itself so as to get the expression //to scale the operator to the height of the expression itself if (bIsStretchy)
pNode->SetScaleMode(SmScaleMode::Height);
GetSmImport().GetNodeStack().push_front(std::move(pNode));
// TODO: apply to non-alphabetic characters too if (rtl::isAsciiAlpha(aToken.cMathChar[0]))
maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
}
bool lcl_CountBlanks(const MathMLAttributeLengthValue& rLV, sal_Int32* pWide, sal_Int32* pNarrow)
{
assert(pWide);
assert(pNarrow); if (rLV.aNumber.GetNumerator() == 0)
{
*pWide = *pNarrow = 0; returntrue;
} // TODO: honor other units than em if (rLV.eUnit != MathMLLengthUnit::Em) returnfalse; if (rLV.aNumber.GetNumerator() < 0) returnfalse; const Fraction aTwo(2, 1); auto aWide = rLV.aNumber / aTwo; auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide)); if (nWide < 0) returnfalse; const Fraction aPointFive(1, 2); auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive; auto nNarrow = static_cast<sal_Int32>(static_cast<tools::Long>(aNarrow)); if (nNarrow < 0) returnfalse;
*pWide = nWide;
*pNarrow = nNarrow; returntrue;
}
}
void SmXMLSpaceContext_Impl::startFastElement(
sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
{ // There is no syntax in Math to specify blank nodes of arbitrary size yet.
MathMLAttributeLengthValue aLV;
sal_Int32 nWide = 0, nNarrow = 0;
void SmXMLUnderContext_Impl::HandleAccent()
{ constbool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); if (!bNodeCheck) return;
/*Just one special case for the underline thing*/
SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack);
SmToken aToken;
aToken.cMathChar = u""_ustr;
aToken.eType = TUNDERLINE;
void SmXMLOverContext_Impl::endFastElement(sal_Int32)
{ if (!nAttrCount)
GenericEndElement(TCSUP, CSUP); else
HandleAccent();
}
void SmXMLOverContext_Impl::HandleAccent()
{ constbool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); if (!bNodeCheck) return;
uno::Reference<xml::sax::XFastContextHandler> SmXMLOfficeContext_Impl::createFastChildContext(
sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
{ if (nElement == XML_ELEMENT(OFFICE, XML_META))
{
SAL_WARN("starmath", "XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
} elseif (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
{ returnnew XMLDocumentSettingsContext(GetImport());
} return nullptr;
}
namespace
{ // context for flat file xml format class SmXMLFlatDocContext_Impl : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
{ public:
SmXMLFlatDocContext_Impl(SmXMLImport& i_rImport, const uno::Reference<document::XDocumentProperties>& i_xDocProps);
switch (nElement)
{ //Consider semantics a dummy except for any starmath annotations case XML_ELEMENT(MATH, XML_SEMANTICS): /*General Layout Schemata*/ case XML_ELEMENT(MATH, XML_MROW):
xContext = new SmXMLRowContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MENCLOSE):
xContext = new SmXMLEncloseContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MFRAC):
xContext = new SmXMLFracContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MSQRT):
xContext = new SmXMLSqrtContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MROOT):
xContext = new SmXMLRootContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MSTYLE):
xContext = new SmXMLStyleContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MERROR):
xContext = new SmXMLErrorContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MPADDED):
xContext = new SmXMLPaddedContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MPHANTOM):
xContext = new SmXMLPhantomContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MFENCED):
xContext = new SmXMLFencedContext_Impl(GetSmImport()); break; /*Script and Limit Schemata*/ case XML_ELEMENT(MATH, XML_MSUB):
xContext = new SmXMLSubContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MSUP):
xContext = new SmXMLSupContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MSUBSUP):
xContext = new SmXMLSubSupContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MUNDER):
xContext = new SmXMLUnderContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MOVER):
xContext = new SmXMLOverContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MUNDEROVER):
xContext = new SmXMLUnderOverContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MMULTISCRIPTS):
xContext = new SmXMLMultiScriptsContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MTABLE):
xContext = new SmXMLTableContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MACTION):
xContext = new SmXMLActionContext_Impl(GetSmImport()); break; default: /*Basically there's an implicit mrow around certain bare *elements,useaRowContexttoseeifthisisoneof
*those ones*/
rtl::Reference<SmXMLRowContext_Impl> aTempContext( new SmXMLRowContext_Impl(GetSmImport()));
//If the first or last element is an operator with stretchyness //set then we must create a brace node here from those elements, //removing the stretchness from the operators and applying it to //ourselves, and creating the appropriate dummy StarMath none bracket //to balance the arrangement if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
&& (aRelationArray[0]->GetType() == SmNodeType::Math))
|| ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
&& (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math)))
{
SmToken aToken;
aToken.cMathChar = u""_ustr;
aToken.nLevel = 5;
return;
}
} else
{ // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math // treat their content as a single inferred mrow in case their content is empty. // Here an empty group {} is used to catch those cases and transform them without error // to StarMath.
aRelationArray.resize(2);
SmToken aToken;
aToken.setChar(MS_LBRACE);
aToken.nLevel = 5;
aToken.eType = TLGROUP;
aToken.nGroup = TG::NONE;
aToken.aText = "{";
aRelationArray[0] = new SmLineNode(aToken);
switch (nElement)
{ /*Note that these should accept malignmark subelements, but do not*/ case XML_ELEMENT(MATH, XML_MN):
pContext = new SmXMLNumberContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MI):
pContext = new SmXMLIdentifierContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MO):
pContext = new SmXMLOperatorContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MTEXT):
pContext = new SmXMLTextContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MSPACE):
pContext = new SmXMLSpaceContext_Impl(GetSmImport()); break; case XML_ELEMENT(MATH, XML_MS):
pContext = new SmXMLStringContext_Impl(GetSmImport()); break;
/*Note: The maligngroup should only be seen when the row
* (or descendants) are in a table*/ case XML_ELEMENT(MATH, XML_MALIGNGROUP):
pContext = new SmXMLAlignGroupContext_Impl(GetSmImport()); break;
case XML_ELEMENT(MATH, XML_ANNOTATION):
pContext = new SmXMLAnnotationContext_Impl(GetSmImport()); break;
if (!xContext)
{ //Hmm, unrecognized for this level, check to see if it's //an element that can have an implicit schema around it
xContext = SmXMLDocContext_Impl::createFastChildContext(nElement, xAttrList);
} return xContext;
}
/*On each loop the base and its sub sup pair becomes the baseforthenextlooptowhichthenextsubsuppairis
attached, i.e. wheels within wheels*/
aSubNodes[0] = popOrZero(aReverseStack).release();
for (size_t i = nRows; i > 0; --i)
{
SmNode* pArray = rNodeStack.front().release();
rNodeStack.pop_front(); if (pArray->GetNumSubNodes() == 0)
{ //This is a little tricky, it is possible that there was //be elements that were not inside a <mtd> pair, in which //case they will not be in a row, i.e. they will not have //SubNodes, so we have to wait until here before we can //resolve the situation. Implicit surrounding tags are //surprisingly difficult to get right within this //architecture
void SmXMLActionContext_Impl::startFastElement(
sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
{ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
{ switch (aIter.getToken())
{ case XML_SELECTION:
{
sal_Int32 n = aIter.toInt32(); if (n > 0)
mnSelection = static_cast<size_t>(n);
} break; default:
XMLOFF_WARN_UNKNOWN("starmath", aIter); break;
}
}
}
void SmXMLActionContext_Impl::endFastElement(sal_Int32)
{
SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); auto nSize = rNodeStack.size(); if (nSize <= nElementCount)
{ // not compliant to maction's specification, e.g., no subexpressions return;
}
assert(mnSelection > 0); if (nSize < nElementCount + mnSelection)
{ // No selected subexpression exists, which is a MathML error; // fallback to selecting the first
mnSelection = 1;
}
assert(nSize >= nElementCount + mnSelection); for (auto i = nSize - (nElementCount + mnSelection); i > 0; i--)
{
rNodeStack.pop_front();
} auto pSelected = std::move(rNodeStack.front());
rNodeStack.pop_front(); for (auto i = rNodeStack.size() - nElementCount; i > 0; i--)
{
rNodeStack.pop_front();
}
rNodeStack.push_front(std::move(pSelected));
}
switch (nElement)
{ case XML_ELEMENT(OFFICE, XML_DOCUMENT): case XML_ELEMENT(OFFICE, XML_DOCUMENT_META):
{
uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
uno::UNO_QUERY_THROW);
pContext = ((nElement & TOKEN_MASK) == XML_DOCUMENT_META)
? new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties()) // flat OpenDocument file format -- this has not been tested...
: new SmXMLFlatDocContext_Impl(*this, xDPS->getDocumentProperties());
} break; default: if (IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE))
pContext = new SmXMLOfficeContext_Impl(*this); else
pContext = new SmXMLDocContext_Impl(*this);
} return pContext;
}
//SetLoading hack because the document properties will be re-initted //by the xml filter and during the init, while it's considered uninitialized, //setting a property will inform the document it's modified, which attempts //to update the properties, which throws cause the properties are uninitialized
xDocSh->SetLoading(SfxLoadedFlags::NONE);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.