[Libreoffice-commits] core.git: 4 commits - i18npool/inc i18npool/source include/oox oox/inc oox/source sd/qa starmath/qa starmath/source writerfilter/source
Michael Stahl
mstahl at redhat.com
Thu Jan 21 10:45:19 PST 2016
i18npool/inc/cclass_unicode.hxx | 26 -
i18npool/source/characterclassification/cclass_unicode_parser.cxx | 137 +++++-----
include/oox/mathml/import.hxx | 11
oox/inc/drawingml/textparagraph.hxx | 13
oox/source/core/xmlfilterbase.cxx | 4
oox/source/drawingml/shape.cxx | 51 +++
oox/source/drawingml/textbodycontext.cxx | 5
oox/source/drawingml/textparagraph.cxx | 10
oox/source/mathml/import.cxx | 92 ++++++
sd/qa/unit/data/pptx/Math.pptx |binary
sd/qa/unit/export-tests.cxx | 54 +++
starmath/qa/cppunit/test_nodetotextvisitors.cxx | 26 +
starmath/source/ooxmlexport.cxx | 6
writerfilter/source/dmapper/DomainMapper_Impl.cxx | 1
14 files changed, 348 insertions(+), 88 deletions(-)
New commits:
commit 9486dd0692e08b3770bee8f3be2292263c6e5d26
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Jan 21 19:00:26 2016 +0100
i18npool: why not document the state transitions
Change-Id: Ica5789dab22a49efb9e2da3a795e13aa7e2c4339
diff --git a/i18npool/inc/cclass_unicode.hxx b/i18npool/inc/cclass_unicode.hxx
index e88530a..cbcb6f9 100644
--- a/i18npool/inc/cclass_unicode.hxx
+++ b/i18npool/inc/cclass_unicode.hxx
@@ -75,16 +75,16 @@ private:
enum ScanState
{
- ssGetChar,
- ssGetValue,
- ssGetWord,
- ssGetWordFirstChar,
- ssGetString,
- ssGetBool,
- ssRewindFromValue,
- ssIgnoreLeadingInRewind,
- ssStopBack,
- ssBounce,
+ ssGetChar, // initial state; -> ssBounce, ssGetValue, ssRewindFromValue, ssGetWord, ssGetWordFirstChar, ssGetString, ssGetBool, ssStop
+ ssGetValue, // -> ssBounce, ssRewindFromValue, ssStopBack, ssGetWord
+ ssGetWord, // -> ssBounce, ssStop, ssStopBack
+ ssGetWordFirstChar, // -> ssBounce, ssGetWord, ssStop, ssStopBack
+ ssGetString, // -> ssBounce, ssStop
+ ssGetBool, // -> ssBounce, ssStop, ssStopBack
+ ssRewindFromValue, // -> ssBounce, ssGetValue, ssGetWord, ssGetWordFirstChar, ssGetString, ssGetBool, ssStop, ssIgnoreLeadingInRewind
+ ssIgnoreLeadingInRewind, // -> ssBounce, ssGetValue, ssRewindFromValue, ssGetWord, ssGetWordFirstChar, ssGetString, ssGetBool, ssStop
+ ssStopBack, // -> ssStop
+ ssBounce, // -> ssStopBack
ssStop
};
commit 331a0a347e2ed238ff41c8cd7815b946cc95ac0f
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Jan 21 18:20:12 2016 +0100
starmath: fix OOXML export of non-BMP Unicode
Change-Id: Iafaeb9ea2e96ee6d8cc96174731ba3845c230b5e
diff --git a/sd/qa/unit/data/pptx/Math.pptx b/sd/qa/unit/data/pptx/Math.pptx
new file mode 100644
index 0000000..fef2067
Binary files /dev/null and b/sd/qa/unit/data/pptx/Math.pptx differ
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index 2f9550a..211cff2 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -142,6 +142,7 @@ public:
void testTdf91378();
void testBnc822341();
void testMathObject();
+ void testMathObjectPPT2010();
void testTdf80224();
void testTdf92527();
@@ -182,6 +183,7 @@ public:
CPPUNIT_TEST(testBnc822341);
CPPUNIT_TEST(testMathObject);
+ CPPUNIT_TEST(testMathObjectPPT2010);
CPPUNIT_TEST(testTdf80224);
CPPUNIT_TEST(testExportTransitionsPPTX);
@@ -1202,6 +1204,33 @@ void SdExportTest::testMathObject()
xDocShRef->DoClose();
}
+void SdExportTest::testMathObjectPPT2010()
+{
+ // Check import / export of math object
+ ::sd::DrawDocShellRef xDocShRef = loadURL(getURLFromSrc("sd/qa/unit/data/pptx/Math.pptx"), PPTX);
+ utl::TempFile tempFile1;
+ xDocShRef = saveAndReload(xDocShRef, PPTX, &tempFile1);
+
+ // Export an MS specific ole object (imported from a PPTX document)
+ {
+ xmlDocPtr pXmlDocContent = parseExport(tempFile1, "ppt/slides/slide1.xml");
+ assertXPath(pXmlDocContent,
+ "/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Choice",
+ "Requires",
+ "a14");
+ assertXPathContent(pXmlDocContent,
+ "/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Choice/p:sp/p:txBody/a:p/a14:m/m:oMath/m:sSup/m:e/m:r[1]/m:t",
+ OUString::fromUtf8("\xf0\x9d\x91\x8e")); // non-BMP char
+
+ const SdrPage *pPage = GetPage(1, xDocShRef);
+ const SdrObject* pObj = dynamic_cast<SdrObject*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object", pObj != nullptr);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_OLE2), pObj->GetObjIdentifier());
+ }
+
+ xDocShRef->DoClose();
+}
+
void SdExportTest::testBulletMarginAndIndentation()
{
::sd::DrawDocShellRef xDocShRef = loadURL( getURLFromSrc("/sd/qa/unit/data/pptx/bulletMarginAndIndent.pptx"), PPTX );
diff --git a/starmath/source/ooxmlexport.cxx b/starmath/source/ooxmlexport.cxx
index 277fb25..63f7cd4 100644
--- a/starmath/source/ooxmlexport.cxx
+++ b/starmath/source/ooxmlexport.cxx
@@ -75,6 +75,7 @@ void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/)
m_pSerializer->startElementNS( XML_m, XML_t, FSNS( XML_xml, XML_space ), "preserve", FSEND );
const SmTextNode* pTemp = static_cast<const SmTextNode* >(pNode);
SAL_INFO( "starmath.ooxml", "Text:" << OUStringToOString( pTemp->GetText(), RTL_TEXTENCODING_UTF8 ).getStr());
+ OUStringBuffer buf(pTemp->GetText());
for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
{
#if 0
@@ -94,9 +95,7 @@ void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/)
nFace = 0x7;
*pS << sal_uInt8(nFace+128); //typeface
#endif
- sal_uInt16 nChar = pTemp->GetText()[i];
- m_pSerializer->writeEscaped( OUString( SmTextNode::ConvertSymbolToUnicode(nChar)));
-
+ buf[i] = SmTextNode::ConvertSymbolToUnicode(buf[i]);
#if 0
//Mathtype can only have these sort of character
//attributes on a single character, starmath can put them
@@ -127,6 +126,7 @@ void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/)
}
#endif
}
+ m_pSerializer->writeEscaped(buf.makeStringAndClear());
m_pSerializer->endElementNS( XML_m, XML_t );
m_pSerializer->endElementNS( XML_m, XML_r );
}
commit fefd1221be844a033e409a18e05e8c6e98f6d1a7
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Jan 21 18:11:12 2016 +0100
i18npool: handle non-BMP Unicode in cclass_Unicode::parseText()
The UTF-16 code unit limitation was mangling starmath import.
Change-Id: I087e5c5b7954799fdb73e7ee1a8d3d02669f8831
diff --git a/i18npool/inc/cclass_unicode.hxx b/i18npool/inc/cclass_unicode.hxx
index eb449e4..e88530a 100644
--- a/i18npool/inc/cclass_unicode.hxx
+++ b/i18npool/inc/cclass_unicode.hxx
@@ -135,13 +135,13 @@ private:
sal_Unicode cDecimalSep;
/// Get corresponding KParseTokens flag for a character
- static sal_Int32 getParseTokensType( const sal_Unicode* aStr, sal_Int32 nPos );
+ static sal_Int32 getParseTokensType(sal_uInt32 c, bool isFirst);
/// Access parser table flags.
- UPT_FLAG_TYPE getFlags( const sal_Unicode* aStr, sal_Int32 nPos );
+ UPT_FLAG_TYPE getFlags(sal_uInt32 c);
/// Access parser flags via International and special definitions.
- UPT_FLAG_TYPE getFlagsExtended( const sal_Unicode* aStr, sal_Int32 nPos );
+ UPT_FLAG_TYPE getFlagsExtended(sal_uInt32 c);
/// Access parser table flags for user defined start characters.
UPT_FLAG_TYPE getStartCharsFlags( sal_Unicode c );
diff --git a/i18npool/source/characterclassification/cclass_unicode_parser.cxx b/i18npool/source/characterclassification/cclass_unicode_parser.cxx
index 7321a7e..c003959 100644
--- a/i18npool/source/characterclassification/cclass_unicode_parser.cxx
+++ b/i18npool/source/characterclassification/cclass_unicode_parser.cxx
@@ -351,16 +351,15 @@ const sal_Unicode* cclass_Unicode::StrChr( const sal_Unicode* pStr, sal_Unicode
}
-sal_Int32 cclass_Unicode::getParseTokensType( const sal_Unicode* aStr, sal_Int32 nPos )
+sal_Int32 cclass_Unicode::getParseTokensType(sal_uInt32 const c, bool const isFirst)
{
- sal_Unicode c = aStr[nPos];
if ( c < nDefCnt )
return pParseTokensType[ sal_uInt8(c) ];
else
{
//! all KParseTokens::UNI_... must be matched
- switch ( u_charType( (sal_uInt32) c ) )
+ switch (u_charType(c))
{
case U_UPPERCASE_LETTER :
return KParseTokens::UNI_UPALPHA;
@@ -372,7 +371,7 @@ sal_Int32 cclass_Unicode::getParseTokensType( const sal_Unicode* aStr, sal_Int32
return KParseTokens::UNI_MODIFIER_LETTER;
case U_OTHER_LETTER :
// Non_Spacing_Mark could not be as leading character
- if (nPos == 0) break;
+ if (isFirst) break;
// fall through, treat it as Other_Letter.
case U_NON_SPACING_MARK :
return KParseTokens::UNI_OTHER_LETTER;
@@ -571,14 +570,13 @@ void cclass_Unicode::destroyParserTable()
}
-UPT_FLAG_TYPE cclass_Unicode::getFlags( const sal_Unicode* aStr, sal_Int32 nPos )
+UPT_FLAG_TYPE cclass_Unicode::getFlags(sal_uInt32 const c)
{
UPT_FLAG_TYPE nMask;
- sal_Unicode c = aStr[nPos];
if ( c < nDefCnt )
nMask = pTable[ sal_uInt8(c) ];
else
- nMask = getFlagsExtended( aStr, nPos );
+ nMask = getFlagsExtended(c);
switch ( eState )
{
case ssGetChar :
@@ -608,9 +606,8 @@ UPT_FLAG_TYPE cclass_Unicode::getFlags( const sal_Unicode* aStr, sal_Int32 nPos
}
-UPT_FLAG_TYPE cclass_Unicode::getFlagsExtended( const sal_Unicode* aStr, sal_Int32 nPos )
+UPT_FLAG_TYPE cclass_Unicode::getFlagsExtended(sal_uInt32 const c)
{
- sal_Unicode c = aStr[nPos];
if ( c == cGroupSep )
return TOKEN_VALUE;
else if ( c == cDecimalSep )
@@ -621,7 +618,7 @@ UPT_FLAG_TYPE cclass_Unicode::getFlagsExtended( const sal_Unicode* aStr, sal_Int
sal_Int32 nTypes = (bStart ? nStartTypes : nContTypes);
//! all KParseTokens::UNI_... must be matched
- switch ( u_charType( (sal_uInt32) c ) )
+ switch (u_charType(c))
{
case U_UPPERCASE_LETTER :
return (nTypes & KParseTokens::UNI_UPALPHA) ?
@@ -712,25 +709,29 @@ UPT_FLAG_TYPE cclass_Unicode::getContCharsFlags( sal_Unicode c )
void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32 nPos, sal_Int32 nTokenType )
{
+ assert(r.LeadingWhiteSpace == 0);
using namespace i18n;
- const sal_Unicode* const pTextStart = rText.getStr() + nPos;
eState = ssGetChar;
//! All the variables below (plus ParseResult) have to be resetted on ssRewindFromValue!
- const sal_Unicode* pSym = pTextStart;
- const sal_Unicode* pSrc = pSym;
OUString aSymbol;
- sal_Unicode c = *pSrc;
- sal_Unicode cLast = 0;
+ bool isFirst(true);
+ sal_Int32 index(nPos); // index of next code point after current
+ sal_Int32 postSymbolIndex(index); // index of code point following last quote
+ sal_uInt32 current((index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0);
+ sal_uInt32 cLast = 0;
+ sal_Int32 nCodePoints(0);
int nDecSeps = 0;
bool bQuote = false;
bool bMightBeWord = true;
bool bMightBeWordLast = true;
//! All the variables above (plus ParseResult) have to be resetted on ssRewindFromValue!
+ sal_Int32 nextCharIndex(0); // == index of nextChar
- while ( (c != 0) && (eState != ssStop) )
+ while ((current != 0) && (eState != ssStop))
{
- UPT_FLAG_TYPE nMask = getFlags( pTextStart, pSrc - pTextStart );
+ ++nCodePoints;
+ UPT_FLAG_TYPE nMask = getFlags(current);
if ( nMask & TOKEN_EXCLUDED )
eState = ssBounce;
if ( bMightBeWord )
@@ -741,8 +742,11 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
else
bMightBeWord = ((nMask & TOKEN_WORD) != 0);
}
- sal_Int32 nParseTokensType = getParseTokensType( pTextStart, pSrc - pTextStart );
- pSrc++;
+ sal_Int32 nParseTokensType = getParseTokensType(current, isFirst);
+ isFirst = false;
+ sal_Int32 const nextIndex(nextCharIndex); // == index of char following current
+ nextCharIndex = index; // == index of nextChar
+ sal_uInt32 nextChar((index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0);
switch (eState)
{
case ssGetChar :
@@ -755,14 +759,14 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
eState = ssGetValue;
if ( nMask & TOKEN_VALUE_DIGIT )
{
- if ( 128 <= c )
+ if (128 <= current)
r.TokenType = KParseType::UNI_NUMBER;
else
r.TokenType = KParseType::ASC_NUMBER;
}
- else if ( c == cDecimalSep )
+ else if (current == cDecimalSep)
{
- if ( *pSrc )
+ if (nextChar)
++nDecSeps;
else
eState = ssRewindFromValue;
@@ -778,14 +782,14 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
{
eState = ssGetWordFirstChar;
bQuote = true;
- pSym++;
+ postSymbolIndex = nextCharIndex;
nParseTokensType = 0; // will be taken of first real character
r.TokenType = KParseType::SINGLE_QUOTE_NAME;
}
else if ( nMask & TOKEN_CHAR_STRING )
{
eState = ssGetString;
- pSym++;
+ postSymbolIndex = nextCharIndex;
nParseTokensType = 0; // will be taken of first real character
r.TokenType = KParseType::DOUBLE_QUOTE_STRING;
}
@@ -795,8 +799,9 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
{
if (eState == ssRewindFromValue)
eState = ssIgnoreLeadingInRewind;
- r.LeadingWhiteSpace++;
- pSym++;
+ r.LeadingWhiteSpace = nextCharIndex - nPos;
+ nCodePoints--; // exclude leading whitespace
+ postSymbolIndex = nextCharIndex;
nParseTokensType = 0; // wait until real character
bMightBeWord = true;
}
@@ -821,16 +826,16 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
{
if ( nMask & TOKEN_VALUE_DIGIT )
{
- if ( 128 <= c )
+ if (128 <= current)
r.TokenType = KParseType::UNI_NUMBER;
else if ( r.TokenType != KParseType::UNI_NUMBER )
r.TokenType = KParseType::ASC_NUMBER;
}
if ( nMask & TOKEN_VALUE )
{
- if ( c == cDecimalSep && ++nDecSeps > 1 )
+ if (current == cDecimalSep && ++nDecSeps > 1)
{
- if ( pSrc - pTextStart == 2 )
+ if (nCodePoints == 2)
eState = ssRewindFromValue;
// consecutive separators
else
@@ -838,12 +843,12 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
}
// else keep it going
}
- else if ( c == 'E' || c == 'e' )
+ else if (current == 'E' || current == 'e')
{
- UPT_FLAG_TYPE nNext = getFlags( pTextStart, pSrc - pTextStart );
+ UPT_FLAG_TYPE nNext = getFlags(nextChar);
if ( nNext & TOKEN_VALUE_EXP )
; // keep it going
- else if ( bMightBeWord && ((nNext & TOKEN_WORD) || !*pSrc) )
+ else if (bMightBeWord && ((nNext & TOKEN_WORD) || !nextChar))
{ // might be a numerical name (1.2efg)
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
@@ -855,10 +860,10 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
{
if ( (cLast == 'E') || (cLast == 'e') )
{
- UPT_FLAG_TYPE nNext = getFlags( pTextStart, pSrc - pTextStart );
+ UPT_FLAG_TYPE nNext = getFlags(nextChar);
if ( nNext & TOKEN_VALUE_EXP_VALUE )
; // keep it going
- else if ( bMightBeWord && ((nNext & TOKEN_WORD) || !*pSrc) )
+ else if (bMightBeWord && ((nNext & TOKEN_WORD) || !nextChar))
{ // might be a numerical name (1.2e+fg)
eState = ssGetWord;
r.TokenType = KParseType::IDENTNAME;
@@ -896,15 +901,15 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
{
if ( cLast == '\\' )
{ // escaped
- aSymbol += OUString( pSym, pSrc - pSym - 2 );
- aSymbol += OUString( &c, 1);
+ aSymbol += rText.copy(postSymbolIndex, nextCharIndex - postSymbolIndex - 2);
+ aSymbol += OUString(¤t, 1);
}
else
{
eState = ssStop;
- aSymbol += OUString( pSym, pSrc - pSym - 1 );
+ aSymbol += rText.copy(postSymbolIndex, nextCharIndex - postSymbolIndex - 1);
}
- pSym = pSrc;
+ postSymbolIndex = nextCharIndex;
}
else
eState = ssStopBack;
@@ -921,21 +926,23 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
{
if ( cLast == '\\' )
{ // escaped
- aSymbol += OUString( pSym, pSrc - pSym - 2 );
- aSymbol += OUString( &c, 1);
+ aSymbol += rText.copy(postSymbolIndex, nextCharIndex - postSymbolIndex - 2);
+ aSymbol += OUString(¤t, 1);
}
- else if ( c == *pSrc &&
+ else if (current == nextChar &&
!(nContTypes & KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING) )
{ // "" => literal " escaped
- aSymbol += OUString( pSym, pSrc - pSym );
- pSrc++;
+ aSymbol += rText.copy(postSymbolIndex, nextCharIndex - postSymbolIndex);
+ nextCharIndex = index;
+ if (index < rText.getLength()) { ++nCodePoints; }
+ nextChar = (index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0;
}
else
{
eState = ssStop;
- aSymbol += OUString( pSym, pSrc - pSym - 1 );
+ aSymbol += rText.copy(postSymbolIndex, nextCharIndex - postSymbolIndex - 1);
}
- pSym = pSrc;
+ postSymbolIndex = nextCharIndex;
}
}
break;
@@ -956,10 +963,13 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
if ( eState == ssRewindFromValue )
{
r = ParseResult();
- pSym = pTextStart;
- pSrc = pSym;
+ index = nPos;
+ postSymbolIndex = nPos;
+ nextCharIndex = 0;
aSymbol.clear();
- c = *pSrc;
+ current = (index < rText.getLength()) ? rText.iterateCodePoints(&index) : 0;
+ nCodePoints = (nPos < rText.getLength()) ? 1 : 0;
+ isFirst = true;
cLast = 0;
nDecSeps = 0;
bQuote = false;
@@ -973,7 +983,7 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
if ( (r.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER))
&& (nTokenType & KParseType::IDENTNAME) && bMightBeWord )
; // keep a number that might be a word
- else if ( r.LeadingWhiteSpace == (pSrc - pTextStart) )
+ else if (r.LeadingWhiteSpace == (nextCharIndex - nPos))
; // keep ignored white space
else if ( !r.TokenType && eState == ssGetValue && (nMask & TOKEN_VALUE_SEP) )
; // keep uncertain value
@@ -987,7 +997,9 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
}
if ( eState == ssStopBack )
{ // put back
- pSrc--;
+ nextChar = rText.iterateCodePoints(&index, -1);
+ nextCharIndex = nextIndex;
+ --nCodePoints;
bMightBeWord = bMightBeWordLast;
eState = ssStop;
}
@@ -999,19 +1011,18 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
r.ContFlags |= nParseTokensType;
}
bMightBeWordLast = bMightBeWord;
- cLast = c;
- c = *pSrc;
+ cLast = current;
+ current = nextChar;
}
}
- // r.CharLen is the length in characters (not code points) of the parsed
- // token not including any leading white space, change this calculation if
- // multi-code-point Unicode characters are to be supported.
- r.CharLen = pSrc - pTextStart - r.LeadingWhiteSpace;
- r.EndPos = nPos + (pSrc - pTextStart);
+ // r.CharLen is the length in characters (not code units) of the parsed
+ // token not including any leading white space.
+ r.CharLen = nCodePoints;
+ r.EndPos = nextCharIndex;
if ( r.TokenType & KParseType::ASC_NUMBER )
{
- r.Value = rtl_math_uStringToDouble( pTextStart + r.LeadingWhiteSpace,
- pTextStart + r.EndPos, cDecimalSep, cGroupSep, nullptr, nullptr );
+ r.Value = rtl_math_uStringToDouble(rText.getStr() + nPos + r.LeadingWhiteSpace,
+ rText.getStr() + r.EndPos, cDecimalSep, cGroupSep, nullptr, nullptr);
if ( bMightBeWord )
r.TokenType |= KParseType::IDENTNAME;
}
@@ -1024,8 +1035,8 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
xNatNumSup = NativeNumberSupplier::create( m_xContext );
}
}
- OUString aTmp( pTextStart + r.LeadingWhiteSpace, r.EndPos - nPos +
- r.LeadingWhiteSpace );
+ OUString aTmp(rText.getStr() + nPos + r.LeadingWhiteSpace,
+ r.EndPos - nPos - r.LeadingWhiteSpace);
// transliterate to ASCII
aTmp = xNatNumSup->getNativeNumberString( aTmp, aParserLocale,
NativeNumberMode::NATNUM0 );
@@ -1035,9 +1046,9 @@ void cclass_Unicode::parseText( ParseResult& r, const OUString& rText, sal_Int32
}
else if ( r.TokenType & (KParseType::SINGLE_QUOTE_NAME | KParseType::DOUBLE_QUOTE_STRING) )
{
- if ( pSym < pSrc )
+ if (postSymbolIndex < nextCharIndex)
{ //! open quote
- aSymbol += OUString( pSym, pSrc - pSym );
+ aSymbol += rText.copy(postSymbolIndex, nextCharIndex - postSymbolIndex - 1);
r.TokenType |= KParseType::MISSING_QUOTE;
}
r.DequotedNameOrString = aSymbol;
diff --git a/starmath/qa/cppunit/test_nodetotextvisitors.cxx b/starmath/qa/cppunit/test_nodetotextvisitors.cxx
index a539761..91d7203 100644
--- a/starmath/qa/cppunit/test_nodetotextvisitors.cxx
+++ b/starmath/qa/cppunit/test_nodetotextvisitors.cxx
@@ -26,7 +26,6 @@ typedef tools::SvRef<SmDocShell> SmDocShellRef;
using namespace ::com::sun::star;
-namespace {
class Test : public test::BootstrapFixture {
@@ -53,6 +52,7 @@ public:
void testBinHorInSubSup();
void testUnaryInMixedNumberAsNumerator();
void testMiscEquivalent();
+ void testParser();
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(SimpleUnaryOp);
@@ -72,6 +72,7 @@ public:
CPPUNIT_TEST(testBinHorInSubSup);
CPPUNIT_TEST(testUnaryInMixedNumberAsNumerator);
CPPUNIT_TEST(testMiscEquivalent);
+ CPPUNIT_TEST(testParser);
CPPUNIT_TEST_SUITE_END();
private:
@@ -486,13 +487,13 @@ void Test::ParseAndCompare(const char *formula1, const char *formula2, const cha
SmNode *pNode1, *pNode2;
// parse formula1
- OUString sInput1 = OUString::createFromAscii(formula1);
+ OUString sInput1 = OUString(formula1, strlen(formula1), RTL_TEXTENCODING_UTF8);
pNode1 = SmParser().ParseExpression(sInput1);
pNode1->Prepare(xDocShRef->GetFormat(), *xDocShRef);
SmNodeToTextVisitor(pNode1, sOutput1);
// parse formula2
- OUString sInput2 = OUString::createFromAscii(formula2);
+ OUString sInput2 = OUString(formula2, strlen(formula2), RTL_TEXTENCODING_UTF8);
pNode2 = SmParser().ParseExpression(sInput2);
pNode2->Prepare(xDocShRef->GetFormat(), *xDocShRef);
SmNodeToTextVisitor(pNode2, sOutput2);
@@ -652,10 +653,27 @@ void Test::testMiscEquivalent()
// fdo#66081
ParseAndCompare("{x}", "x", "Variable in brace");
ParseAndCompare("{{x+{{y}}}}", "x+y", "Nested braces");
+
+ // check non-BMP Unicode char
+ ParseAndCompare("{\xf0\x9d\x91\x8e}", "\xf0\x9d\x91\x8e", "non-BMP variable in brace");
+ ParseAndCompare("{ \xf0\x9d\x91\x8e }", "\xf0\x9d\x91\x8e", "non-BMP variable in brace");
}
-CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+void Test::testParser()
+{
+ char const* formula = "{ \xf0\x9d\x91\x8e }"; // non-BMP Unicode
+ char const* expected = "\xf0\x9d\x91\x8e";
+ OUString sOutput;
+ OUString sInput = OUString(formula, strlen(formula), RTL_TEXTENCODING_UTF8);
+ OUString sExpected = OUString(expected, strlen(expected), RTL_TEXTENCODING_UTF8);
+ std::unique_ptr<SmNode> pNode(SmParser().ParseExpression(sInput));
+ pNode->Prepare(xDocShRef->GetFormat(), *xDocShRef);
+ SmNodeToTextVisitor(pNode.get(), sOutput);
+ CPPUNIT_ASSERT_EQUAL(sExpected, sOutput);
}
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 332a796366b7cb91dff41de4b9ffb17843112a3e
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Jan 21 17:39:26 2016 +0100
oox: import Math objects from PPTX files
This is quite hacky and limited: in OOXML these are not OLE objects but
occur inside text boxes, and PPT 2010 allows inserting multiple Math
objects into one text box but Impress does not have as-character
anchored objects, so we can't import that properly; for now only import
Math if there is nothing else in the text box.
Also for now only import them as children of TextParagraphContext (a:p);
it's not clear what the possible parent elements could be since the
OOXML standard only lists WordProcessingML parent elements :(
Change-Id: I847f810084c9ddae4b60f93896fb73a742683cc2
diff --git a/include/oox/mathml/import.hxx b/include/oox/mathml/import.hxx
index 2617ff5..b2ed99b 100644
--- a/include/oox/mathml/import.hxx
+++ b/include/oox/mathml/import.hxx
@@ -9,10 +9,11 @@
#ifndef INCLUDED_OOX_MATHML_IMPORT_HXX
#define INCLUDED_OOX_MATHML_IMPORT_HXX
-#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <oox/dllapi.h>
+
#include <tools/gen.hxx>
-#include <oox/dllapi.h>
+#include <rtl/ref.hxx>
namespace oox
{
@@ -39,6 +40,12 @@ protected:
~FormulaImportBase() {}
};
+namespace core { class ContextHandler; }
+namespace drawingml { class TextParagraph; }
+
+::rtl::Reference<core::ContextHandler> CreateLazyMathBufferingContext(
+ core::ContextHandler const& rParent, drawingml::TextParagraph & rPara);
+
} // namespace
#endif
diff --git a/oox/inc/drawingml/textparagraph.hxx b/oox/inc/drawingml/textparagraph.hxx
index f96989c..43bf51a 100644
--- a/oox/inc/drawingml/textparagraph.hxx
+++ b/oox/inc/drawingml/textparagraph.hxx
@@ -28,6 +28,11 @@
#include <drawingml/textliststyle.hxx>
#include <drawingml/textparagraphproperties.hxx>
+
+namespace oox { namespace formulaimport {
+ class XmlStreamBuilder;
+} }
+
namespace oox { namespace drawingml {
typedef RefVector< TextRun > TextRunVector;
@@ -57,10 +62,18 @@ public:
bool bFirst = false,
float nDefaultCharHeight = 0) const;
+ bool HasMathXml() const
+ {
+ return m_pMathXml != nullptr;
+ }
+ formulaimport::XmlStreamBuilder & GetMathXml();
+
private:
TextParagraphProperties maProperties;
TextCharacterProperties maEndProperties;
TextRunVector maRuns;
+ // temporarily store this here
+ std::unique_ptr<formulaimport::XmlStreamBuilder> m_pMathXml;
};
} }
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index ea1721d..062a600 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -129,11 +129,15 @@ struct NamespaceIds: public rtl::StaticWithInit<
NMSP_mce},
{"http://schemas.openxmlformats.org/spreadsheetml/2006/main/v2",
NMSP_mceTest},
+ {"http://schemas.openxmlformats.org/officeDocument/2006/math",
+ NMSP_officeMath},
{"http://schemas.microsoft.com/office/drawing/2008/diagram",
NMSP_dsp},
{"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main",
NMSP_xls14Lst},
{"http://schemas.libreoffice.org/", NMSP_loext},
+ {"http://schemas.microsoft.com/office/drawing/2010/main",
+ NMSP_a14},
{"http://schemas.microsoft.com/office/powerpoint/2010/main",
NMSP_p14},
{"http://schemas.microsoft.com/office/powerpoint/2012/main",
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index b744bb1..9d12b50 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -27,6 +27,7 @@
#include "effectproperties.hxx"
#include "oox/drawingml/shapepropertymap.hxx"
#include "drawingml/textbody.hxx"
+#include <drawingml/textparagraph.hxx>
#include <drawingml/ThemeOverrideFragmentHandler.hxx>
#include "drawingml/table/tableproperties.hxx"
#include "oox/drawingml/chart/chartconverter.hxx"
@@ -40,8 +41,12 @@
#include "oox/helper/graphichelper.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/helper/modelobjecthelper.hxx"
+#include <oox/mathml/importutils.hxx>
+#include <oox/mathml/import.hxx>
+#include <comphelper/classids.hxx>
#include <tools/gen.hxx>
+#include <tools/globname.hxx>
#include <tools/mapunit.hxx>
#include <editeng/unoprnms.hxx>
#include <com/sun/star/awt/Size.hpp>
@@ -55,6 +60,7 @@
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/drawing/GraphicExportFilter.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/table/BorderLine2.hpp>
#include <com/sun/star/table/ShadowFormat.hpp>
@@ -407,6 +413,25 @@ Reference< XShape > Shape::createAndInsert(
bool bIsEmbMedia = false;
SAL_INFO("oox.drawingml", OSL_THIS_FUNC << " id: " << msId);
+ formulaimport::XmlStreamBuilder * pMathXml(nullptr);
+ if (mpTextBody.get())
+ {
+ for (auto const& it : mpTextBody->getParagraphs())
+ {
+ if (it->HasMathXml())
+ {
+ if (!mpTextBody->isEmpty() || pMathXml != nullptr)
+ {
+ SAL_WARN("oox.drawingml", "losing a Math object...");
+ }
+ else
+ {
+ pMathXml = &it->GetMathXml();
+ }
+ }
+ }
+ }
+
// tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height
if ( mpTablePropertiesPtr.get() && rServiceName == "com.sun.star.drawing.TableShape" )
{
@@ -427,7 +452,15 @@ Reference< XShape > Shape::createAndInsert(
awt::Rectangle aShapeRectHmm( maPosition.X / EMU_PER_HMM, maPosition.Y / EMU_PER_HMM, maSize.Width / EMU_PER_HMM, maSize.Height / EMU_PER_HMM );
OUString aServiceName;
- if( rServiceName == "com.sun.star.drawing.GraphicObjectShape" &&
+ if (pMathXml)
+ {
+ // convert this shape to OLE
+ aServiceName = "com.sun.star.drawing.OLE2Shape";
+ msServiceName = aServiceName;
+ meFrameType = FRAMETYPE_GENERIC; // not OLEOBJECT, no stream in package
+ mnSubType = 0;
+ }
+ else if (rServiceName == "com.sun.star.drawing.GraphicObjectShape" &&
mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->m_sMediaPackageURL.isEmpty())
{
aServiceName = finalizeServiceName( rFilterBase, "com.sun.star.presentation.MediaShape", aShapeRectHmm );
@@ -605,6 +638,22 @@ Reference< XShape > Shape::createAndInsert(
}
}
+ if (pMathXml)
+ {
+ // the "EmbeddedObject" property is read-only, so we have to create
+ // the shape first, and it can be read only after the shape is
+ // inserted into the document, so delay the actual import until here
+ SvGlobalName name(SO3_SM_CLASSID);
+ xSet->setPropertyValue("CLSID", uno::makeAny(name.GetHexName()));
+ uno::Reference<embed::XEmbeddedObject> const xObj(
+ xSet->getPropertyValue("EmbeddedObject"), uno::UNO_QUERY);
+ uno::Reference<uno::XInterface> const xMathModel(xObj->getComponent());
+ oox::FormulaImportBase *const pMagic(
+ dynamic_cast<oox::FormulaImportBase*>(xMathModel.get()));
+ assert(pMagic);
+ pMagic->readFormulaOoxml(*pMathXml);
+ }
+
const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper();
LineProperties aLineProperties;
diff --git a/oox/source/drawingml/textbodycontext.cxx b/oox/source/drawingml/textbodycontext.cxx
index 20d3b26..84fc769 100644
--- a/oox/source/drawingml/textbodycontext.cxx
+++ b/oox/source/drawingml/textbodycontext.cxx
@@ -26,6 +26,8 @@
#include "drawingml/textfield.hxx"
#include "drawingml/textfieldcontext.hxx"
+#include <oox/mathml/import.hxx>
+
using namespace ::oox::core;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
@@ -90,6 +92,9 @@ ContextHandlerRef TextParagraphContext::onCreateContext( sal_Int32 aElementToken
case W_TOKEN( ins ):
return this;
break;
+ case OOX_TOKEN(a14, m):
+ return CreateLazyMathBufferingContext(*this, mrParagraph);
+ break;
default:
SAL_WARN("oox", "TextParagraphContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
}
diff --git a/oox/source/drawingml/textparagraph.cxx b/oox/source/drawingml/textparagraph.cxx
index 76d299a..5d49659 100644
--- a/oox/source/drawingml/textparagraph.cxx
+++ b/oox/source/drawingml/textparagraph.cxx
@@ -22,6 +22,7 @@
#include "drawingml/textcharacterproperties.hxx"
#include <rtl/ustring.hxx>
+#include <oox/mathml/importutils.hxx>
#include "oox/helper/propertyset.hxx"
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextCursor.hpp>
@@ -138,6 +139,15 @@ void TextParagraph::insertAt(
}
}
+formulaimport::XmlStreamBuilder & TextParagraph::GetMathXml()
+{
+ if (!m_pMathXml)
+ {
+ m_pMathXml.reset(new formulaimport::XmlStreamBuilder);
+ }
+ return *m_pMathXml;
+}
+
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/mathml/import.cxx b/oox/source/mathml/import.cxx
index bf49de2..5b80dc4 100644
--- a/oox/source/mathml/import.cxx
+++ b/oox/source/mathml/import.cxx
@@ -9,6 +9,14 @@
#include "oox/mathml/import.hxx"
+#include <oox/mathml/importutils.hxx>
+#include <oox/core/contexthandler.hxx>
+
+#include <drawingml/textparagraph.hxx>
+
+
+using namespace ::com::sun::star;
+
namespace oox
{
@@ -16,6 +24,88 @@ FormulaImportBase::FormulaImportBase()
{
}
-} // namespace
+namespace formulaimport {
+
+class LazyMathBufferingContext : public core::ContextHandler
+{
+private:
+ XmlStreamBuilder & m_rBuilder;
+ long m_Counter;
+
+public:
+ LazyMathBufferingContext(core::ContextHandler const& rParent,
+ drawingml::TextParagraph & rPara);
+
+ // com.sun.star.xml.sax.XFastContextHandler interface ---------------------
+
+ virtual void SAL_CALL startFastElement(::sal_Int32 Element, const uno::Reference<xml::sax::XFastAttributeList>& xAttribs) throw (xml::sax::SAXException, uno::RuntimeException, std::exception) override;
+ virtual void SAL_CALL endFastElement(::sal_Int32 Element) throw (xml::sax::SAXException, uno::RuntimeException, std::exception) override;
+ virtual uno::Reference< xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(::sal_Int32 Element, const uno::Reference<xml::sax::XFastAttributeList >& xAttribs) throw (xml::sax::SAXException, uno::RuntimeException, std::exception) override;
+ virtual void SAL_CALL characters(const OUString& rChars) throw (xml::sax::SAXException, uno::RuntimeException, std::exception) override;
+
+};
+
+LazyMathBufferingContext::LazyMathBufferingContext(
+ core::ContextHandler const& rParent, drawingml::TextParagraph & rPara)
+ : core::ContextHandler(rParent)
+ , m_rBuilder(rPara.GetMathXml())
+ , m_Counter(0)
+{
+}
+
+void SAL_CALL LazyMathBufferingContext::startFastElement(
+ sal_Int32 const nElement,
+ uno::Reference<xml::sax::XFastAttributeList> const& xAttrs)
+ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
+{
+ if (0 < m_Counter) // ignore a14:m
+ { // ignore outer oMathPara
+ if (1 != m_Counter || OOX_TOKEN(officeMath, oMathPara) != nElement)
+ {
+ m_rBuilder.appendOpeningTag(nElement, xAttrs);
+ }
+ }
+ ++m_Counter;
+}
+
+void SAL_CALL LazyMathBufferingContext::endFastElement(sal_Int32 const nElement)
+ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
+{
+ --m_Counter;
+ if (0 < m_Counter) // ignore a14:m
+ { // ignore outer oMathPara
+ if (1 != m_Counter || OOX_TOKEN(officeMath, oMathPara) != nElement)
+ {
+ m_rBuilder.appendClosingTag(nElement);
+ }
+ }
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SAL_CALL
+LazyMathBufferingContext::createFastChildContext(sal_Int32 const,
+ uno::Reference<xml::sax::XFastAttributeList> const&)
+ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
+{
+ return this;
+}
+
+void SAL_CALL LazyMathBufferingContext::characters(OUString const& rChars)
+ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
+{
+ if (0 < m_Counter) // ignore a14:m
+ {
+ m_rBuilder.appendCharacters(rChars);
+ }
+}
+
+} // namespace formulaimport
+
+core::ContextHandlerRef CreateLazyMathBufferingContext(
+ core::ContextHandler const& rParent, drawingml::TextParagraph & rPara)
+{
+ return new formulaimport::LazyMathBufferingContext(rParent, rPara);
+}
+
+} // namespace oox
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index 818ea21..2f9550a 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -1173,7 +1173,30 @@ void SdExportTest::testMathObject()
"/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Choice/p:sp/p:txBody/a:p/a14:m/m:oMath/m:r[1]/m:t",
"a");
- // TODO can't import yet
+ const SdrPage *pPage = GetPage(1, xDocShRef);
+ const SdrObject* pObj = dynamic_cast<SdrObject*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object", pObj != nullptr);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_OLE2), pObj->GetObjIdentifier());
+ }
+
+ utl::TempFile tempFile2;
+ xDocShRef = saveAndReload( xDocShRef, PPTX, &tempFile2 );
+
+ // Export an MS specific ole object (imported from a PPTX document)
+ {
+ xmlDocPtr pXmlDocContent = parseExport(tempFile1, "ppt/slides/slide1.xml");
+ assertXPath(pXmlDocContent,
+ "/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Choice",
+ "Requires",
+ "a14");
+ assertXPathContent(pXmlDocContent,
+ "/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Choice/p:sp/p:txBody/a:p/a14:m/m:oMath/m:r[1]/m:t",
+ "a");
+
+ const SdrPage *pPage = GetPage(1, xDocShRef);
+ const SdrObject* pObj = dynamic_cast<SdrObject*>(pPage->GetObj(0));
+ CPPUNIT_ASSERT_MESSAGE("no object", pObj != nullptr);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(OBJ_OLE2), pObj->GetObjIdentifier());
}
xDocShRef->DoClose();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 4cdd7c0..eeb11a0 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -32,6 +32,7 @@
#include <com/sun/star/document/PrinterIndependentLayout.hpp>
#include <com/sun/star/document/IndexedPropertyValues.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/style/LineNumberPosition.hpp>
More information about the Libreoffice-commits
mailing list