bump product version to 7.6.3.2-android
[LibreOffice.git] / starmath / source / ooxmlexport.cxx
blobfd3a9498a681c6b0b615b2c50192021f226b13c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "ooxmlexport.hxx"
12 #include <oox/token/tokens.hxx>
13 #include <rtl/ustring.hxx>
14 #include <sal/log.hxx>
15 #include <oox/mathml/imexport.hxx>
17 using namespace oox;
18 using namespace oox::core;
20 SmOoxmlExport::SmOoxmlExport(const SmNode *const pIn, OoxmlVersion const v,
21 drawingml::DocumentType const documentType)
22 : SmWordExportBase( pIn )
23 , version( v )
24 , m_DocumentType(documentType)
28 void SmOoxmlExport::ConvertFromStarMath( const ::sax_fastparser::FSHelperPtr& serializer, const sal_Int8 nAlign )
30 if( GetTree() == nullptr )
31 return;
32 m_pSerializer = serializer;
34 //Formula alignment situations:
36 // 1)Inline(as before):
38 // <m:oMath>
39 // <m:r> ... </m:r>
40 // </m:oMath>
42 // 2)Aligned:
44 // <m:oMathPara>
45 // <m:oMathParaPr>
46 // <m:jc m:val="left|right|center">
47 // </m:oMathParaPr>
48 // <m:oMath>
49 // <m:r> ... </m:r>
50 // </m:oMath>
51 // </m:oMathPara>
53 if (nAlign != FormulaImExportBase::eFormulaAlign::INLINE)
55 m_pSerializer->startElementNS(XML_m, XML_oMathPara,
56 FSNS(XML_xmlns, XML_m), "http://schemas.openxmlformats.org/officeDocument/2006/math");
57 m_pSerializer->startElementNS(XML_m, XML_oMathParaPr);
58 if (nAlign == FormulaImExportBase::eFormulaAlign::CENTER)
59 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "center");
60 if (nAlign == FormulaImExportBase::eFormulaAlign::GROUPEDCENTER)
61 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "center");
62 if (nAlign == FormulaImExportBase::eFormulaAlign::LEFT)
63 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "left");
64 if (nAlign == FormulaImExportBase::eFormulaAlign::RIGHT)
65 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "right");
66 m_pSerializer->endElementNS(XML_m, XML_oMathParaPr);
67 m_pSerializer->startElementNS(XML_m, XML_oMath);
68 HandleNode(GetTree(), 0);
69 m_pSerializer->endElementNS(XML_m, XML_oMath);
70 m_pSerializer->endElementNS(XML_m, XML_oMathPara);
72 else //else, inline as was before
74 m_pSerializer->startElementNS(XML_m, XML_oMath,
75 FSNS(XML_xmlns, XML_m), "http://schemas.openxmlformats.org/officeDocument/2006/math");
76 HandleNode( GetTree(), 0 );
77 m_pSerializer->endElementNS( XML_m, XML_oMath );
81 // NOTE: This is still work in progress and unfinished, but it already covers a good
82 // part of the ooxml math stuff.
84 void SmOoxmlExport::HandleVerticalStack( const SmNode* pNode, int nLevel )
86 m_pSerializer->startElementNS(XML_m, XML_eqArr);
87 int size = pNode->GetNumSubNodes();
88 for( int i = 0;
89 i < size;
90 ++i )
92 m_pSerializer->startElementNS(XML_m, XML_e);
93 HandleNode( pNode->GetSubNode( i ), nLevel + 1 );
94 m_pSerializer->endElementNS( XML_m, XML_e );
96 m_pSerializer->endElementNS( XML_m, XML_eqArr );
99 void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/)
101 m_pSerializer->startElementNS(XML_m, XML_r);
103 if( pNode->GetToken().eType == TTEXT ) // literal text (in quotes)
105 m_pSerializer->startElementNS(XML_m, XML_rPr);
106 m_pSerializer->singleElementNS(XML_m, XML_lit);
107 m_pSerializer->singleElementNS(XML_m, XML_nor);
108 m_pSerializer->endElementNS( XML_m, XML_rPr );
110 if (drawingml::DOCUMENT_DOCX == m_DocumentType && ECMA_376_1ST_EDITION == version)
111 { // HACK: MSOffice2007 does not import characters properly unless this font is explicitly given
112 m_pSerializer->startElementNS(XML_w, XML_rPr);
113 m_pSerializer->singleElementNS( XML_w, XML_rFonts, FSNS( XML_w, XML_ascii ), "Cambria Math",
114 FSNS( XML_w, XML_hAnsi ), "Cambria Math" );
115 m_pSerializer->endElementNS( XML_w, XML_rPr );
117 m_pSerializer->startElementNS(XML_m, XML_t, FSNS(XML_xml, XML_space), "preserve");
118 const SmTextNode* pTemp = static_cast<const SmTextNode* >(pNode);
119 SAL_INFO( "starmath.ooxml", "Text:" << pTemp->GetText());
120 OUStringBuffer buf(pTemp->GetText());
121 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
123 #if 0
124 if ((nPendingAttributes) &&
125 (i == ((pTemp->GetText().getLength()+1)/2)-1))
127 *pS << sal_uInt8(0x22); //char, with attributes right
128 //after the character
130 else
131 *pS << sal_uInt8(CHAR);
133 sal_uInt8 nFace = 0x1;
134 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
135 nFace = 0x3;
136 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
137 nFace = 0x7;
138 *pS << sal_uInt8(nFace+128); //typeface
139 #endif
140 buf[i] = SmTextNode::ConvertSymbolToUnicode(buf[i]);
141 #if 0
142 //Mathtype can only have these sort of character
143 //attributes on a single character, starmath can put them
144 //anywhere, when the entity involved is a text run this is
145 //a large effort to place the character attribute on the
146 //central mathtype character so that it does pretty much
147 //what the user probably has in mind. The attributes
148 //filled in here are dummy ones which are replaced in the
149 //ATTRIBUTE handler if a suitable location for the
150 //attributes was found here. Unfortunately it is
151 //possible for starmath to place character attributes on
152 //entities which cannot occur in mathtype e.g. a Summation
153 //symbol so these attributes may be lost
154 if ((nPendingAttributes) &&
155 (i == ((pTemp->GetText().getLength()+1)/2)-1))
157 *pS << sal_uInt8(EMBEL);
158 while (nPendingAttributes)
160 *pS << sal_uInt8(2);
161 //wedge the attributes in here and clear
162 //the pending stack
163 nPendingAttributes--;
165 nInsertion=pS->Tell();
166 *pS << sal_uInt8(END); //end embel
167 *pS << sal_uInt8(END); //end embel
169 #endif
171 m_pSerializer->writeEscaped(buf);
172 m_pSerializer->endElementNS( XML_m, XML_t );
173 m_pSerializer->endElementNS( XML_m, XML_r );
176 void SmOoxmlExport::HandleFractions( const SmNode* pNode, int nLevel, const char* type )
178 m_pSerializer->startElementNS(XML_m, XML_f);
179 if( type != nullptr )
181 m_pSerializer->startElementNS(XML_m, XML_fPr);
182 m_pSerializer->singleElementNS(XML_m, XML_type, FSNS(XML_m, XML_val), type);
183 m_pSerializer->endElementNS( XML_m, XML_fPr );
185 assert( pNode->GetNumSubNodes() == 3 );
186 m_pSerializer->startElementNS(XML_m, XML_num);
187 HandleNode( pNode->GetSubNode( 0 ), nLevel + 1 );
188 m_pSerializer->endElementNS( XML_m, XML_num );
189 m_pSerializer->startElementNS(XML_m, XML_den);
190 HandleNode( pNode->GetSubNode( 2 ), nLevel + 1 );
191 m_pSerializer->endElementNS( XML_m, XML_den );
192 m_pSerializer->endElementNS( XML_m, XML_f );
195 void SmOoxmlExport::HandleAttribute( const SmAttributeNode* pNode, int nLevel )
197 switch( pNode->Attribute()->GetToken().eType )
199 case TCHECK:
200 case TACUTE:
201 case TGRAVE:
202 case TBREVE:
203 case TCIRCLE:
204 case TVEC:
205 case TTILDE:
206 case THAT:
207 case TDOT:
208 case TDDOT:
209 case TDDDOT:
210 case TWIDETILDE:
211 case TWIDEHAT:
212 case TWIDEHARPOON:
213 case TWIDEVEC:
214 case TBAR:
216 m_pSerializer->startElementNS(XML_m, XML_acc);
217 m_pSerializer->startElementNS(XML_m, XML_accPr);
218 OString value = OUStringToOString(pNode->Attribute()->GetToken().cMathChar, RTL_TEXTENCODING_UTF8 );
219 m_pSerializer->singleElementNS(XML_m, XML_chr, FSNS(XML_m, XML_val), value);
220 m_pSerializer->endElementNS( XML_m, XML_accPr );
221 m_pSerializer->startElementNS(XML_m, XML_e);
222 HandleNode( pNode->Body(), nLevel + 1 );
223 m_pSerializer->endElementNS( XML_m, XML_e );
224 m_pSerializer->endElementNS( XML_m, XML_acc );
225 break;
227 case TOVERLINE:
228 case TUNDERLINE:
229 m_pSerializer->startElementNS(XML_m, XML_bar);
230 m_pSerializer->startElementNS(XML_m, XML_barPr);
231 m_pSerializer->singleElementNS( XML_m, XML_pos, FSNS( XML_m, XML_val ),
232 ( pNode->Attribute()->GetToken().eType == TUNDERLINE ) ? "bot" : "top" );
233 m_pSerializer->endElementNS( XML_m, XML_barPr );
234 m_pSerializer->startElementNS(XML_m, XML_e);
235 HandleNode( pNode->Body(), nLevel + 1 );
236 m_pSerializer->endElementNS( XML_m, XML_e );
237 m_pSerializer->endElementNS( XML_m, XML_bar );
238 break;
239 case TOVERSTRIKE:
240 m_pSerializer->startElementNS(XML_m, XML_borderBox);
241 m_pSerializer->startElementNS(XML_m, XML_borderBoxPr);
242 m_pSerializer->singleElementNS(XML_m, XML_hideTop, FSNS(XML_m, XML_val), "1");
243 m_pSerializer->singleElementNS(XML_m, XML_hideBot, FSNS(XML_m, XML_val), "1");
244 m_pSerializer->singleElementNS(XML_m, XML_hideLeft, FSNS(XML_m, XML_val), "1");
245 m_pSerializer->singleElementNS(XML_m, XML_hideRight, FSNS(XML_m, XML_val), "1");
246 m_pSerializer->singleElementNS(XML_m, XML_strikeH, FSNS(XML_m, XML_val), "1");
247 m_pSerializer->endElementNS( XML_m, XML_borderBoxPr );
248 m_pSerializer->startElementNS(XML_m, XML_e);
249 HandleNode( pNode->Body(), nLevel + 1 );
250 m_pSerializer->endElementNS( XML_m, XML_e );
251 m_pSerializer->endElementNS( XML_m, XML_borderBox );
252 break;
253 default:
254 HandleAllSubNodes( pNode, nLevel );
255 break;
259 void SmOoxmlExport::HandleRoot( const SmRootNode* pNode, int nLevel )
261 m_pSerializer->startElementNS(XML_m, XML_rad);
262 if( const SmNode* argument = pNode->Argument())
264 m_pSerializer->startElementNS(XML_m, XML_deg);
265 HandleNode( argument, nLevel + 1 );
266 m_pSerializer->endElementNS( XML_m, XML_deg );
268 else
270 m_pSerializer->startElementNS(XML_m, XML_radPr);
271 m_pSerializer->singleElementNS(XML_m, XML_degHide, FSNS(XML_m, XML_val), "1");
272 m_pSerializer->endElementNS( XML_m, XML_radPr );
273 m_pSerializer->singleElementNS(XML_m, XML_deg); // empty but present
275 m_pSerializer->startElementNS(XML_m, XML_e);
276 HandleNode( pNode->Body(), nLevel + 1 );
277 m_pSerializer->endElementNS( XML_m, XML_e );
278 m_pSerializer->endElementNS( XML_m, XML_rad );
281 static OString mathSymbolToString( const SmNode* node )
283 assert( node->GetType() == SmNodeType::Math || node->GetType() == SmNodeType::MathIdent );
284 const SmTextNode* txtnode = static_cast< const SmTextNode* >( node );
285 assert( txtnode->GetText().getLength() == 1 );
286 sal_Unicode chr = SmTextNode::ConvertSymbolToUnicode( txtnode->GetText()[0] );
287 return OUStringToOString( OUStringChar( chr ), RTL_TEXTENCODING_UTF8 );
290 void SmOoxmlExport::HandleOperator( const SmOperNode* pNode, int nLevel )
292 SAL_INFO( "starmath.ooxml", "Operator: " << int( pNode->GetToken().eType ));
293 switch( pNode->GetToken().eType )
295 case TINT:
296 case TINTD:
297 case TIINT:
298 case TIIINT:
299 case TLINT:
300 case TLLINT:
301 case TLLLINT:
302 case TPROD:
303 case TCOPROD:
304 case TSUM:
306 const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == SmNodeType::SubSup
307 ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr;
308 const SmNode* operation = subsup != nullptr ? subsup->GetBody() : pNode->GetSubNode( 0 );
309 m_pSerializer->startElementNS(XML_m, XML_nary);
310 m_pSerializer->startElementNS(XML_m, XML_naryPr);
311 m_pSerializer->singleElementNS( XML_m, XML_chr,
312 FSNS( XML_m, XML_val ), mathSymbolToString(operation) );
313 if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr )
314 m_pSerializer->singleElementNS(XML_m, XML_subHide, FSNS(XML_m, XML_val), "1");
315 if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr )
316 m_pSerializer->singleElementNS(XML_m, XML_supHide, FSNS(XML_m, XML_val), "1");
317 m_pSerializer->endElementNS( XML_m, XML_naryPr );
318 if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr )
319 m_pSerializer->singleElementNS(XML_m, XML_sub);
320 else
322 m_pSerializer->startElementNS(XML_m, XML_sub);
323 HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 );
324 m_pSerializer->endElementNS( XML_m, XML_sub );
326 if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr )
327 m_pSerializer->singleElementNS(XML_m, XML_sup);
328 else
330 m_pSerializer->startElementNS(XML_m, XML_sup);
331 HandleNode( subsup->GetSubSup( CSUP ), nLevel + 1 );
332 m_pSerializer->endElementNS( XML_m, XML_sup );
334 m_pSerializer->startElementNS(XML_m, XML_e);
335 HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body
336 m_pSerializer->endElementNS( XML_m, XML_e );
337 m_pSerializer->endElementNS( XML_m, XML_nary );
338 break;
340 case TLIM:
341 m_pSerializer->startElementNS(XML_m, XML_func);
342 m_pSerializer->startElementNS(XML_m, XML_fName);
343 m_pSerializer->startElementNS(XML_m, XML_limLow);
344 m_pSerializer->startElementNS(XML_m, XML_e);
345 HandleNode( pNode->GetSymbol(), nLevel + 1 );
346 m_pSerializer->endElementNS( XML_m, XML_e );
347 m_pSerializer->startElementNS(XML_m, XML_lim);
348 if( const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == SmNodeType::SubSup
349 ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr )
351 if( subsup->GetSubSup( CSUB ) != nullptr )
352 HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 );
354 m_pSerializer->endElementNS( XML_m, XML_lim );
355 m_pSerializer->endElementNS( XML_m, XML_limLow );
356 m_pSerializer->endElementNS( XML_m, XML_fName );
357 m_pSerializer->startElementNS(XML_m, XML_e);
358 HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body
359 m_pSerializer->endElementNS( XML_m, XML_e );
360 m_pSerializer->endElementNS( XML_m, XML_func );
361 break;
362 default:
363 SAL_WARN("starmath.ooxml", "Unhandled operation");
364 HandleAllSubNodes( pNode, nLevel );
365 break;
369 void SmOoxmlExport::HandleSubSupScriptInternal( const SmSubSupNode* pNode, int nLevel, int flags )
371 // docx supports only a certain combination of sub/super scripts, but LO can have any,
372 // so try to merge it using several tags if necessary
373 if( flags == 0 ) // none
374 return;
375 if(( flags & ( 1 << RSUP | 1 << RSUB )) == ( 1 << RSUP | 1 << RSUB ))
376 { // m:sSubSup
377 m_pSerializer->startElementNS(XML_m, XML_sSubSup);
378 m_pSerializer->startElementNS(XML_m, XML_e);
379 flags &= ~( 1 << RSUP | 1 << RSUB );
380 if( flags == 0 )
381 HandleNode( pNode->GetBody(), nLevel + 1 );
382 else
383 HandleSubSupScriptInternal( pNode, nLevel, flags );
384 m_pSerializer->endElementNS( XML_m, XML_e );
385 m_pSerializer->startElementNS(XML_m, XML_sub);
386 HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 );
387 m_pSerializer->endElementNS( XML_m, XML_sub );
388 m_pSerializer->startElementNS(XML_m, XML_sup);
389 HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 );
390 m_pSerializer->endElementNS( XML_m, XML_sup );
391 m_pSerializer->endElementNS( XML_m, XML_sSubSup );
393 else if(( flags & ( 1 << RSUB )) == 1 << RSUB )
394 { // m:sSub
395 m_pSerializer->startElementNS(XML_m, XML_sSub);
396 m_pSerializer->startElementNS(XML_m, XML_e);
397 flags &= ~( 1 << RSUB );
398 if( flags == 0 )
399 HandleNode( pNode->GetBody(), nLevel + 1 );
400 else
401 HandleSubSupScriptInternal( pNode, nLevel, flags );
402 m_pSerializer->endElementNS( XML_m, XML_e );
403 m_pSerializer->startElementNS(XML_m, XML_sub);
404 HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 );
405 m_pSerializer->endElementNS( XML_m, XML_sub );
406 m_pSerializer->endElementNS( XML_m, XML_sSub );
408 else if(( flags & ( 1 << RSUP )) == 1 << RSUP )
409 { // m:sSup
410 m_pSerializer->startElementNS(XML_m, XML_sSup);
411 m_pSerializer->startElementNS(XML_m, XML_e);
412 flags &= ~( 1 << RSUP );
413 if( flags == 0 )
414 HandleNode( pNode->GetBody(), nLevel + 1 );
415 else
416 HandleSubSupScriptInternal( pNode, nLevel, flags );
417 m_pSerializer->endElementNS( XML_m, XML_e );
418 m_pSerializer->startElementNS(XML_m, XML_sup);
419 HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 );
420 m_pSerializer->endElementNS( XML_m, XML_sup );
421 m_pSerializer->endElementNS( XML_m, XML_sSup );
423 else if(( flags & ( 1 << LSUP | 1 << LSUB )) == ( 1 << LSUP | 1 << LSUB ))
424 { // m:sPre
425 m_pSerializer->startElementNS(XML_m, XML_sPre);
426 m_pSerializer->startElementNS(XML_m, XML_sub);
427 HandleNode( pNode->GetSubSup( LSUB ), nLevel + 1 );
428 m_pSerializer->endElementNS( XML_m, XML_sub );
429 m_pSerializer->startElementNS(XML_m, XML_sup);
430 HandleNode( pNode->GetSubSup( LSUP ), nLevel + 1 );
431 m_pSerializer->endElementNS( XML_m, XML_sup );
432 m_pSerializer->startElementNS(XML_m, XML_e);
433 flags &= ~( 1 << LSUP | 1 << LSUB );
434 if( flags == 0 )
435 HandleNode( pNode->GetBody(), nLevel + 1 );
436 else
437 HandleSubSupScriptInternal( pNode, nLevel, flags );
438 m_pSerializer->endElementNS( XML_m, XML_e );
439 m_pSerializer->endElementNS( XML_m, XML_sPre );
441 else if(( flags & ( 1 << CSUB )) == ( 1 << CSUB ))
442 { // m:limLow looks like a good element for central superscript
443 m_pSerializer->startElementNS(XML_m, XML_limLow);
444 m_pSerializer->startElementNS(XML_m, XML_e);
445 flags &= ~( 1 << CSUB );
446 if( flags == 0 )
447 HandleNode( pNode->GetBody(), nLevel + 1 );
448 else
449 HandleSubSupScriptInternal( pNode, nLevel, flags );
450 m_pSerializer->endElementNS( XML_m, XML_e );
451 m_pSerializer->startElementNS(XML_m, XML_lim);
452 HandleNode( pNode->GetSubSup( CSUB ), nLevel + 1 );
453 m_pSerializer->endElementNS( XML_m, XML_lim );
454 m_pSerializer->endElementNS( XML_m, XML_limLow );
456 else if(( flags & ( 1 << CSUP )) == ( 1 << CSUP ))
457 { // m:limUpp looks like a good element for central superscript
458 m_pSerializer->startElementNS(XML_m, XML_limUpp);
459 m_pSerializer->startElementNS(XML_m, XML_e);
460 flags &= ~( 1 << CSUP );
461 if( flags == 0 )
462 HandleNode( pNode->GetBody(), nLevel + 1 );
463 else
464 HandleSubSupScriptInternal( pNode, nLevel, flags );
465 m_pSerializer->endElementNS( XML_m, XML_e );
466 m_pSerializer->startElementNS(XML_m, XML_lim);
467 HandleNode( pNode->GetSubSup( CSUP ), nLevel + 1 );
468 m_pSerializer->endElementNS( XML_m, XML_lim );
469 m_pSerializer->endElementNS( XML_m, XML_limUpp );
471 else
473 SAL_WARN("starmath.ooxml", "Unhandled sub/sup combination");
474 // TODO do not do anything, this should be probably an assert()
475 // HandleAllSubNodes( pNode, nLevel );
479 void SmOoxmlExport::HandleMatrix( const SmMatrixNode* pNode, int nLevel )
481 m_pSerializer->startElementNS(XML_m, XML_m);
482 for (size_t row = 0; row < pNode->GetNumRows(); ++row)
484 m_pSerializer->startElementNS(XML_m, XML_mr);
485 for (size_t col = 0; col < pNode->GetNumCols(); ++col)
487 m_pSerializer->startElementNS(XML_m, XML_e);
488 if( const SmNode* node = pNode->GetSubNode( row * pNode->GetNumCols() + col ))
489 HandleNode( node, nLevel + 1 );
490 m_pSerializer->endElementNS( XML_m, XML_e );
492 m_pSerializer->endElementNS( XML_m, XML_mr );
494 m_pSerializer->endElementNS( XML_m, XML_m );
497 void SmOoxmlExport::HandleBrace( const SmBraceNode* pNode, int nLevel )
499 m_pSerializer->startElementNS(XML_m, XML_d);
500 m_pSerializer->startElementNS(XML_m, XML_dPr);
502 //check if the node has an opening brace
503 if( TNONE == pNode->OpeningBrace()->GetToken().eType )
504 m_pSerializer->singleElementNS(XML_m, XML_begChr, FSNS(XML_m, XML_val), "");
505 else
506 m_pSerializer->singleElementNS( XML_m, XML_begChr,
507 FSNS( XML_m, XML_val ), mathSymbolToString( pNode->OpeningBrace()) );
509 std::vector< const SmNode* > subnodes;
510 if( pNode->Body()->GetType() == SmNodeType::Bracebody )
512 const SmBracebodyNode* body = static_cast< const SmBracebodyNode* >( pNode->Body());
513 bool separatorWritten = false; // assume all separators are the same
514 for (size_t i = 0; i < body->GetNumSubNodes(); ++i)
516 const SmNode* subnode = body->GetSubNode( i );
517 if (subnode->GetType() == SmNodeType::Math || subnode->GetType() == SmNodeType::MathIdent)
518 { // do not write, but write what separator it is
519 const SmMathSymbolNode* math = static_cast< const SmMathSymbolNode* >( subnode );
520 if( !separatorWritten )
522 m_pSerializer->singleElementNS( XML_m, XML_sepChr,
523 FSNS( XML_m, XML_val ), mathSymbolToString(math) );
524 separatorWritten = true;
527 else
528 subnodes.push_back( subnode );
531 else
532 subnodes.push_back( pNode->Body());
534 if( TNONE == pNode->ClosingBrace()->GetToken().eType )
535 m_pSerializer->singleElementNS(XML_m, XML_endChr, FSNS(XML_m, XML_val), "");
536 else
537 m_pSerializer->singleElementNS( XML_m, XML_endChr,
538 FSNS( XML_m, XML_val ), mathSymbolToString(pNode->ClosingBrace()) );
540 m_pSerializer->endElementNS( XML_m, XML_dPr );
541 for(const SmNode* subnode : subnodes)
543 m_pSerializer->startElementNS(XML_m, XML_e);
544 HandleNode( subnode, nLevel + 1 );
545 m_pSerializer->endElementNS( XML_m, XML_e );
547 m_pSerializer->endElementNS( XML_m, XML_d );
550 void SmOoxmlExport::HandleVerticalBrace( const SmVerticalBraceNode* pNode, int nLevel )
552 SAL_INFO( "starmath.ooxml", "Vertical: " << int( pNode->GetToken().eType ));
553 switch( pNode->GetToken().eType )
555 case TOVERBRACE:
556 case TUNDERBRACE:
558 bool top = ( pNode->GetToken().eType == TOVERBRACE );
559 m_pSerializer->startElementNS(XML_m, top ? XML_limUpp : XML_limLow);
560 m_pSerializer->startElementNS(XML_m, XML_e);
561 m_pSerializer->startElementNS(XML_m, XML_groupChr);
562 m_pSerializer->startElementNS(XML_m, XML_groupChrPr);
563 m_pSerializer->singleElementNS( XML_m, XML_chr,
564 FSNS( XML_m, XML_val ), mathSymbolToString(pNode->Brace()) );
565 // TODO not sure if pos and vertJc are correct
566 m_pSerializer->singleElementNS( XML_m, XML_pos,
567 FSNS( XML_m, XML_val ), top ? "top" : "bot" );
568 m_pSerializer->singleElementNS(XML_m, XML_vertJc, FSNS(XML_m, XML_val),
569 top ? "bot" : "top");
570 m_pSerializer->endElementNS( XML_m, XML_groupChrPr );
571 m_pSerializer->startElementNS(XML_m, XML_e);
572 HandleNode( pNode->Body(), nLevel + 1 );
573 m_pSerializer->endElementNS( XML_m, XML_e );
574 m_pSerializer->endElementNS( XML_m, XML_groupChr );
575 m_pSerializer->endElementNS( XML_m, XML_e );
576 m_pSerializer->startElementNS(XML_m, XML_lim);
577 HandleNode( pNode->Script(), nLevel + 1 );
578 m_pSerializer->endElementNS( XML_m, XML_lim );
579 m_pSerializer->endElementNS( XML_m, top ? XML_limUpp : XML_limLow );
580 break;
582 default:
583 SAL_WARN("starmath.ooxml", "Unhandled vertical brace");
584 HandleAllSubNodes( pNode, nLevel );
585 break;
589 void SmOoxmlExport::HandleBlank()
591 m_pSerializer->startElementNS(XML_m, XML_r);
592 m_pSerializer->startElementNS(XML_m, XML_t, FSNS(XML_xml, XML_space), "preserve");
593 m_pSerializer->write( " " );
594 m_pSerializer->endElementNS( XML_m, XML_t );
595 m_pSerializer->endElementNS( XML_m, XML_r );
598 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */