Bump version to 21.06.18.1
[LibreOffice.git] / starmath / source / ooxmlexport.cxx
bloba915596b67a211a58e5ffe27d1bb742c13090951
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"
11 #include <node.hxx>
13 #include <oox/token/tokens.hxx>
14 #include <rtl/ustring.hxx>
15 #include <sal/log.hxx>
16 #include <oox/mathml/export.hxx>
18 using namespace oox;
19 using namespace oox::core;
21 SmOoxmlExport::SmOoxmlExport(const SmNode *const pIn, OoxmlVersion const v,
22 drawingml::DocumentType const documentType)
23 : SmWordExportBase( pIn )
24 , version( v )
25 , m_DocumentType(documentType)
29 void SmOoxmlExport::ConvertFromStarMath( const ::sax_fastparser::FSHelperPtr& serializer, const sal_Int8 nAlign )
31 if( GetTree() == nullptr )
32 return;
33 m_pSerializer = serializer;
35 //Formula alignment situations:
37 // 1)Inline(as before):
39 // <m:oMath>
40 // <m:r> ... </m:r>
41 // </m:oMath>
43 // 2)Aligned:
45 // <m:oMathPara>
46 // <m:oMathParaPr>
47 // <m:jc m:val="left|right|center">
48 // </m:oMathParaPr>
49 // <m:oMath>
50 // <m:r> ... </m:r>
51 // </m:oMath>
52 // </m:oMathPara>
54 if (nAlign != FormulaExportBase::eFormulaAlign::INLINE)
56 m_pSerializer->startElementNS(XML_m, XML_oMathPara,
57 FSNS(XML_xmlns, XML_m), "http://schemas.openxmlformats.org/officeDocument/2006/math");
58 m_pSerializer->startElementNS(XML_m, XML_oMathParaPr);
59 if (nAlign == FormulaExportBase::eFormulaAlign::CENTER)
60 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "center");
61 if (nAlign == FormulaExportBase::eFormulaAlign::GROUPEDCENTER)
62 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "center");
63 if (nAlign == FormulaExportBase::eFormulaAlign::LEFT)
64 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "left");
65 if (nAlign == FormulaExportBase::eFormulaAlign::RIGHT)
66 m_pSerializer->singleElementNS(XML_m, XML_jc, FSNS(XML_m, XML_val), "right");
67 m_pSerializer->endElementNS(XML_m, XML_oMathParaPr);
68 m_pSerializer->startElementNS(XML_m, XML_oMath);
69 HandleNode(GetTree(), 0);
70 m_pSerializer->endElementNS(XML_m, XML_oMath);
71 m_pSerializer->endElementNS(XML_m, XML_oMathPara);
73 else //else, inline as was before
75 m_pSerializer->startElementNS(XML_m, XML_oMath,
76 FSNS(XML_xmlns, XML_m), "http://schemas.openxmlformats.org/officeDocument/2006/math");
77 HandleNode( GetTree(), 0 );
78 m_pSerializer->endElementNS( XML_m, XML_oMath );
82 // NOTE: This is still work in progress and unfinished, but it already covers a good
83 // part of the ooxml math stuff.
85 void SmOoxmlExport::HandleVerticalStack( const SmNode* pNode, int nLevel )
87 m_pSerializer->startElementNS(XML_m, XML_eqArr);
88 int size = pNode->GetNumSubNodes();
89 for( int i = 0;
90 i < size;
91 ++i )
93 m_pSerializer->startElementNS(XML_m, XML_e);
94 HandleNode( pNode->GetSubNode( i ), nLevel + 1 );
95 m_pSerializer->endElementNS( XML_m, XML_e );
97 m_pSerializer->endElementNS( XML_m, XML_eqArr );
100 void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/)
102 m_pSerializer->startElementNS(XML_m, XML_r);
104 if( pNode->GetToken().eType == TTEXT ) // literal text (in quotes)
106 m_pSerializer->startElementNS(XML_m, XML_rPr);
107 m_pSerializer->singleElementNS(XML_m, XML_lit);
108 m_pSerializer->singleElementNS(XML_m, XML_nor);
109 m_pSerializer->endElementNS( XML_m, XML_rPr );
111 if (drawingml::DOCUMENT_DOCX == m_DocumentType && ECMA_DIALECT == version)
112 { // HACK: MSOffice2007 does not import characters properly unless this font is explicitly given
113 m_pSerializer->startElementNS(XML_w, XML_rPr);
114 m_pSerializer->singleElementNS( XML_w, XML_rFonts, FSNS( XML_w, XML_ascii ), "Cambria Math",
115 FSNS( XML_w, XML_hAnsi ), "Cambria Math" );
116 m_pSerializer->endElementNS( XML_w, XML_rPr );
118 m_pSerializer->startElementNS(XML_m, XML_t, FSNS(XML_xml, XML_space), "preserve");
119 const SmTextNode* pTemp = static_cast<const SmTextNode* >(pNode);
120 SAL_INFO( "starmath.ooxml", "Text:" << pTemp->GetText());
121 OUStringBuffer buf(pTemp->GetText());
122 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
124 #if 0
125 if ((nPendingAttributes) &&
126 (i == ((pTemp->GetText().getLength()+1)/2)-1))
128 *pS << sal_uInt8(0x22); //char, with attributes right
129 //after the character
131 else
132 *pS << sal_uInt8(CHAR);
134 sal_uInt8 nFace = 0x1;
135 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
136 nFace = 0x3;
137 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
138 nFace = 0x7;
139 *pS << sal_uInt8(nFace+128); //typeface
140 #endif
141 buf[i] = SmTextNode::ConvertSymbolToUnicode(buf[i]);
142 #if 0
143 //Mathtype can only have these sort of character
144 //attributes on a single character, starmath can put them
145 //anywhere, when the entity involved is a text run this is
146 //a large effort to place the character attribute on the
147 //central mathtype character so that it does pretty much
148 //what the user probably has in mind. The attributes
149 //filled in here are dummy ones which are replaced in the
150 //ATTRIBUT handler if a suitable location for the
151 //attributes was found here. Unfortunately it is
152 //possible for starmath to place character attributes on
153 //entities which cannot occur in mathtype e.g. a Summation
154 //symbol so these attributes may be lost
155 if ((nPendingAttributes) &&
156 (i == ((pTemp->GetText().getLength()+1)/2)-1))
158 *pS << sal_uInt8(EMBEL);
159 while (nPendingAttributes)
161 *pS << sal_uInt8(2);
162 //wedge the attributes in here and clear
163 //the pending stack
164 nPendingAttributes--;
166 nInsertion=pS->Tell();
167 *pS << sal_uInt8(END); //end embel
168 *pS << sal_uInt8(END); //end embel
170 #endif
172 m_pSerializer->writeEscaped(buf.makeStringAndClear());
173 m_pSerializer->endElementNS( XML_m, XML_t );
174 m_pSerializer->endElementNS( XML_m, XML_r );
177 void SmOoxmlExport::HandleFractions( const SmNode* pNode, int nLevel, const char* type )
179 m_pSerializer->startElementNS(XML_m, XML_f);
180 if( type != nullptr )
182 m_pSerializer->startElementNS(XML_m, XML_fPr);
183 m_pSerializer->singleElementNS(XML_m, XML_type, FSNS(XML_m, XML_val), type);
184 m_pSerializer->endElementNS( XML_m, XML_fPr );
186 assert( pNode->GetNumSubNodes() == 3 );
187 m_pSerializer->startElementNS(XML_m, XML_num);
188 HandleNode( pNode->GetSubNode( 0 ), nLevel + 1 );
189 m_pSerializer->endElementNS( XML_m, XML_num );
190 m_pSerializer->startElementNS(XML_m, XML_den);
191 HandleNode( pNode->GetSubNode( 2 ), nLevel + 1 );
192 m_pSerializer->endElementNS( XML_m, XML_den );
193 m_pSerializer->endElementNS( XML_m, XML_f );
196 void SmOoxmlExport::HandleAttribute( const SmAttributNode* pNode, int nLevel )
198 switch( pNode->Attribute()->GetToken().eType )
200 case TCHECK:
201 case TACUTE:
202 case TGRAVE:
203 case TBREVE:
204 case TCIRCLE:
205 case TVEC:
206 case TTILDE:
207 case THAT:
208 case TDOT:
209 case TDDOT:
210 case TDDDOT:
211 case TWIDETILDE:
212 case TWIDEHAT:
213 case TWIDEHARPOON:
214 case TWIDEVEC:
215 case TBAR:
217 m_pSerializer->startElementNS(XML_m, XML_acc);
218 m_pSerializer->startElementNS(XML_m, XML_accPr);
219 OString value = OUStringToOString(
220 OUString( pNode->Attribute()->GetToken().cMathChar ), RTL_TEXTENCODING_UTF8 );
221 m_pSerializer->singleElementNS(XML_m, XML_chr, FSNS(XML_m, XML_val), value);
222 m_pSerializer->endElementNS( XML_m, XML_accPr );
223 m_pSerializer->startElementNS(XML_m, XML_e);
224 HandleNode( pNode->Body(), nLevel + 1 );
225 m_pSerializer->endElementNS( XML_m, XML_e );
226 m_pSerializer->endElementNS( XML_m, XML_acc );
227 break;
229 case TOVERLINE:
230 case TUNDERLINE:
231 m_pSerializer->startElementNS(XML_m, XML_bar);
232 m_pSerializer->startElementNS(XML_m, XML_barPr);
233 m_pSerializer->singleElementNS( XML_m, XML_pos, FSNS( XML_m, XML_val ),
234 ( pNode->Attribute()->GetToken().eType == TUNDERLINE ) ? "bot" : "top" );
235 m_pSerializer->endElementNS( XML_m, XML_barPr );
236 m_pSerializer->startElementNS(XML_m, XML_e);
237 HandleNode( pNode->Body(), nLevel + 1 );
238 m_pSerializer->endElementNS( XML_m, XML_e );
239 m_pSerializer->endElementNS( XML_m, XML_bar );
240 break;
241 case TOVERSTRIKE:
242 m_pSerializer->startElementNS(XML_m, XML_borderBox);
243 m_pSerializer->startElementNS(XML_m, XML_borderBoxPr);
244 m_pSerializer->singleElementNS(XML_m, XML_hideTop, FSNS(XML_m, XML_val), "1");
245 m_pSerializer->singleElementNS(XML_m, XML_hideBot, FSNS(XML_m, XML_val), "1");
246 m_pSerializer->singleElementNS(XML_m, XML_hideLeft, FSNS(XML_m, XML_val), "1");
247 m_pSerializer->singleElementNS(XML_m, XML_hideRight, FSNS(XML_m, XML_val), "1");
248 m_pSerializer->singleElementNS(XML_m, XML_strikeH, FSNS(XML_m, XML_val), "1");
249 m_pSerializer->endElementNS( XML_m, XML_borderBoxPr );
250 m_pSerializer->startElementNS(XML_m, XML_e);
251 HandleNode( pNode->Body(), nLevel + 1 );
252 m_pSerializer->endElementNS( XML_m, XML_e );
253 m_pSerializer->endElementNS( XML_m, XML_borderBox );
254 break;
255 default:
256 HandleAllSubNodes( pNode, nLevel );
257 break;
261 void SmOoxmlExport::HandleRoot( const SmRootNode* pNode, int nLevel )
263 m_pSerializer->startElementNS(XML_m, XML_rad);
264 if( const SmNode* argument = pNode->Argument())
266 m_pSerializer->startElementNS(XML_m, XML_deg);
267 HandleNode( argument, nLevel + 1 );
268 m_pSerializer->endElementNS( XML_m, XML_deg );
270 else
272 m_pSerializer->startElementNS(XML_m, XML_radPr);
273 m_pSerializer->singleElementNS(XML_m, XML_degHide, FSNS(XML_m, XML_val), "1");
274 m_pSerializer->endElementNS( XML_m, XML_radPr );
275 m_pSerializer->singleElementNS(XML_m, XML_deg); // empty but present
277 m_pSerializer->startElementNS(XML_m, XML_e);
278 HandleNode( pNode->Body(), nLevel + 1 );
279 m_pSerializer->endElementNS( XML_m, XML_e );
280 m_pSerializer->endElementNS( XML_m, XML_rad );
283 static OString mathSymbolToString( const SmNode* node )
285 assert( node->GetType() == SmNodeType::Math || node->GetType() == SmNodeType::MathIdent );
286 const SmTextNode* txtnode = static_cast< const SmTextNode* >( node );
287 assert( txtnode->GetText().getLength() == 1 );
288 sal_Unicode chr = SmTextNode::ConvertSymbolToUnicode( txtnode->GetText()[0] );
289 return OUStringToOString( OUString( chr ), RTL_TEXTENCODING_UTF8 );
292 void SmOoxmlExport::HandleOperator( const SmOperNode* pNode, int nLevel )
294 SAL_INFO( "starmath.ooxml", "Operator: " << int( pNode->GetToken().eType ));
295 switch( pNode->GetToken().eType )
297 case TINT:
298 case TINTD:
299 case TIINT:
300 case TIIINT:
301 case TLINT:
302 case TLLINT:
303 case TLLLINT:
304 case TPROD:
305 case TCOPROD:
306 case TSUM:
308 const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == SmNodeType::SubSup
309 ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr;
310 const SmNode* operation = subsup != nullptr ? subsup->GetBody() : pNode->GetSubNode( 0 );
311 m_pSerializer->startElementNS(XML_m, XML_nary);
312 m_pSerializer->startElementNS(XML_m, XML_naryPr);
313 m_pSerializer->singleElementNS( XML_m, XML_chr,
314 FSNS( XML_m, XML_val ), mathSymbolToString(operation) );
315 if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr )
316 m_pSerializer->singleElementNS(XML_m, XML_subHide, FSNS(XML_m, XML_val), "1");
317 if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr )
318 m_pSerializer->singleElementNS(XML_m, XML_supHide, FSNS(XML_m, XML_val), "1");
319 m_pSerializer->endElementNS( XML_m, XML_naryPr );
320 if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr )
321 m_pSerializer->singleElementNS(XML_m, XML_sub);
322 else
324 m_pSerializer->startElementNS(XML_m, XML_sub);
325 HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 );
326 m_pSerializer->endElementNS( XML_m, XML_sub );
328 if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr )
329 m_pSerializer->singleElementNS(XML_m, XML_sup);
330 else
332 m_pSerializer->startElementNS(XML_m, XML_sup);
333 HandleNode( subsup->GetSubSup( CSUP ), nLevel + 1 );
334 m_pSerializer->endElementNS( XML_m, XML_sup );
336 m_pSerializer->startElementNS(XML_m, XML_e);
337 HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body
338 m_pSerializer->endElementNS( XML_m, XML_e );
339 m_pSerializer->endElementNS( XML_m, XML_nary );
340 break;
342 case TLIM:
343 m_pSerializer->startElementNS(XML_m, XML_func);
344 m_pSerializer->startElementNS(XML_m, XML_fName);
345 m_pSerializer->startElementNS(XML_m, XML_limLow);
346 m_pSerializer->startElementNS(XML_m, XML_e);
347 HandleNode( pNode->GetSymbol(), nLevel + 1 );
348 m_pSerializer->endElementNS( XML_m, XML_e );
349 m_pSerializer->startElementNS(XML_m, XML_lim);
350 if( const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == SmNodeType::SubSup
351 ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr )
353 if( subsup->GetSubSup( CSUB ) != nullptr )
354 HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 );
356 m_pSerializer->endElementNS( XML_m, XML_lim );
357 m_pSerializer->endElementNS( XML_m, XML_limLow );
358 m_pSerializer->endElementNS( XML_m, XML_fName );
359 m_pSerializer->startElementNS(XML_m, XML_e);
360 HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body
361 m_pSerializer->endElementNS( XML_m, XML_e );
362 m_pSerializer->endElementNS( XML_m, XML_func );
363 break;
364 default:
365 SAL_WARN("starmath.ooxml", "Unhandled operation");
366 HandleAllSubNodes( pNode, nLevel );
367 break;
371 void SmOoxmlExport::HandleSubSupScriptInternal( const SmSubSupNode* pNode, int nLevel, int flags )
373 // docx supports only a certain combination of sub/super scripts, but LO can have any,
374 // so try to merge it using several tags if necessary
375 if( flags == 0 ) // none
376 return;
377 if(( flags & ( 1 << RSUP | 1 << RSUB )) == ( 1 << RSUP | 1 << RSUB ))
378 { // m:sSubSup
379 m_pSerializer->startElementNS(XML_m, XML_sSubSup);
380 m_pSerializer->startElementNS(XML_m, XML_e);
381 flags &= ~( 1 << RSUP | 1 << RSUB );
382 if( flags == 0 )
383 HandleNode( pNode->GetBody(), nLevel + 1 );
384 else
385 HandleSubSupScriptInternal( pNode, nLevel, flags );
386 m_pSerializer->endElementNS( XML_m, XML_e );
387 m_pSerializer->startElementNS(XML_m, XML_sub);
388 HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 );
389 m_pSerializer->endElementNS( XML_m, XML_sub );
390 m_pSerializer->startElementNS(XML_m, XML_sup);
391 HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 );
392 m_pSerializer->endElementNS( XML_m, XML_sup );
393 m_pSerializer->endElementNS( XML_m, XML_sSubSup );
395 else if(( flags & ( 1 << RSUB )) == 1 << RSUB )
396 { // m:sSub
397 m_pSerializer->startElementNS(XML_m, XML_sSub);
398 m_pSerializer->startElementNS(XML_m, XML_e);
399 flags &= ~( 1 << RSUB );
400 if( flags == 0 )
401 HandleNode( pNode->GetBody(), nLevel + 1 );
402 else
403 HandleSubSupScriptInternal( pNode, nLevel, flags );
404 m_pSerializer->endElementNS( XML_m, XML_e );
405 m_pSerializer->startElementNS(XML_m, XML_sub);
406 HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 );
407 m_pSerializer->endElementNS( XML_m, XML_sub );
408 m_pSerializer->endElementNS( XML_m, XML_sSub );
410 else if(( flags & ( 1 << RSUP )) == 1 << RSUP )
411 { // m:sSup
412 m_pSerializer->startElementNS(XML_m, XML_sSup);
413 m_pSerializer->startElementNS(XML_m, XML_e);
414 flags &= ~( 1 << RSUP );
415 if( flags == 0 )
416 HandleNode( pNode->GetBody(), nLevel + 1 );
417 else
418 HandleSubSupScriptInternal( pNode, nLevel, flags );
419 m_pSerializer->endElementNS( XML_m, XML_e );
420 m_pSerializer->startElementNS(XML_m, XML_sup);
421 HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 );
422 m_pSerializer->endElementNS( XML_m, XML_sup );
423 m_pSerializer->endElementNS( XML_m, XML_sSup );
425 else if(( flags & ( 1 << LSUP | 1 << LSUB )) == ( 1 << LSUP | 1 << LSUB ))
426 { // m:sPre
427 m_pSerializer->startElementNS(XML_m, XML_sPre);
428 m_pSerializer->startElementNS(XML_m, XML_sub);
429 HandleNode( pNode->GetSubSup( LSUB ), nLevel + 1 );
430 m_pSerializer->endElementNS( XML_m, XML_sub );
431 m_pSerializer->startElementNS(XML_m, XML_sup);
432 HandleNode( pNode->GetSubSup( LSUP ), nLevel + 1 );
433 m_pSerializer->endElementNS( XML_m, XML_sup );
434 m_pSerializer->startElementNS(XML_m, XML_e);
435 flags &= ~( 1 << LSUP | 1 << LSUB );
436 if( flags == 0 )
437 HandleNode( pNode->GetBody(), nLevel + 1 );
438 else
439 HandleSubSupScriptInternal( pNode, nLevel, flags );
440 m_pSerializer->endElementNS( XML_m, XML_e );
441 m_pSerializer->endElementNS( XML_m, XML_sPre );
443 else if(( flags & ( 1 << CSUB )) == ( 1 << CSUB ))
444 { // m:limLow looks like a good element for central superscript
445 m_pSerializer->startElementNS(XML_m, XML_limLow);
446 m_pSerializer->startElementNS(XML_m, XML_e);
447 flags &= ~( 1 << CSUB );
448 if( flags == 0 )
449 HandleNode( pNode->GetBody(), nLevel + 1 );
450 else
451 HandleSubSupScriptInternal( pNode, nLevel, flags );
452 m_pSerializer->endElementNS( XML_m, XML_e );
453 m_pSerializer->startElementNS(XML_m, XML_lim);
454 HandleNode( pNode->GetSubSup( CSUB ), nLevel + 1 );
455 m_pSerializer->endElementNS( XML_m, XML_lim );
456 m_pSerializer->endElementNS( XML_m, XML_limLow );
458 else if(( flags & ( 1 << CSUP )) == ( 1 << CSUP ))
459 { // m:limUpp looks like a good element for central superscript
460 m_pSerializer->startElementNS(XML_m, XML_limUpp);
461 m_pSerializer->startElementNS(XML_m, XML_e);
462 flags &= ~( 1 << CSUP );
463 if( flags == 0 )
464 HandleNode( pNode->GetBody(), nLevel + 1 );
465 else
466 HandleSubSupScriptInternal( pNode, nLevel, flags );
467 m_pSerializer->endElementNS( XML_m, XML_e );
468 m_pSerializer->startElementNS(XML_m, XML_lim);
469 HandleNode( pNode->GetSubSup( CSUP ), nLevel + 1 );
470 m_pSerializer->endElementNS( XML_m, XML_lim );
471 m_pSerializer->endElementNS( XML_m, XML_limUpp );
473 else
475 SAL_WARN("starmath.ooxml", "Unhandled sub/sup combination");
476 // TODO do not do anything, this should be probably an assert()
477 // HandleAllSubNodes( pNode, nLevel );
481 void SmOoxmlExport::HandleMatrix( const SmMatrixNode* pNode, int nLevel )
483 m_pSerializer->startElementNS(XML_m, XML_m);
484 for (size_t row = 0; row < pNode->GetNumRows(); ++row)
486 m_pSerializer->startElementNS(XML_m, XML_mr);
487 for (size_t col = 0; col < pNode->GetNumCols(); ++col)
489 m_pSerializer->startElementNS(XML_m, XML_e);
490 if( const SmNode* node = pNode->GetSubNode( row * pNode->GetNumCols() + col ))
491 HandleNode( node, nLevel + 1 );
492 m_pSerializer->endElementNS( XML_m, XML_e );
494 m_pSerializer->endElementNS( XML_m, XML_mr );
496 m_pSerializer->endElementNS( XML_m, XML_m );
499 void SmOoxmlExport::HandleBrace( const SmBraceNode* pNode, int nLevel )
501 m_pSerializer->startElementNS(XML_m, XML_d);
502 m_pSerializer->startElementNS(XML_m, XML_dPr);
504 //check if the node has an opening brace
505 if( TNONE == pNode->OpeningBrace()->GetToken().eType )
506 m_pSerializer->singleElementNS(XML_m, XML_begChr, FSNS(XML_m, XML_val), "");
507 else
508 m_pSerializer->singleElementNS( XML_m, XML_begChr,
509 FSNS( XML_m, XML_val ), mathSymbolToString( pNode->OpeningBrace()) );
511 std::vector< const SmNode* > subnodes;
512 if( pNode->Body()->GetType() == SmNodeType::Bracebody )
514 const SmBracebodyNode* body = static_cast< const SmBracebodyNode* >( pNode->Body());
515 bool separatorWritten = false; // assume all separators are the same
516 for (size_t i = 0; i < body->GetNumSubNodes(); ++i)
518 const SmNode* subnode = body->GetSubNode( i );
519 if (subnode->GetType() == SmNodeType::Math || subnode->GetType() == SmNodeType::MathIdent)
520 { // do not write, but write what separator it is
521 const SmMathSymbolNode* math = static_cast< const SmMathSymbolNode* >( subnode );
522 if( !separatorWritten )
524 m_pSerializer->singleElementNS( XML_m, XML_sepChr,
525 FSNS( XML_m, XML_val ), mathSymbolToString(math) );
526 separatorWritten = true;
529 else
530 subnodes.push_back( subnode );
533 else
534 subnodes.push_back( pNode->Body());
536 if( TNONE == pNode->ClosingBrace()->GetToken().eType )
537 m_pSerializer->singleElementNS(XML_m, XML_endChr, FSNS(XML_m, XML_val), "");
538 else
539 m_pSerializer->singleElementNS( XML_m, XML_endChr,
540 FSNS( XML_m, XML_val ), mathSymbolToString(pNode->ClosingBrace()) );
542 m_pSerializer->endElementNS( XML_m, XML_dPr );
543 for(const SmNode* subnode : subnodes)
545 m_pSerializer->startElementNS(XML_m, XML_e);
546 HandleNode( subnode, nLevel + 1 );
547 m_pSerializer->endElementNS( XML_m, XML_e );
549 m_pSerializer->endElementNS( XML_m, XML_d );
552 void SmOoxmlExport::HandleVerticalBrace( const SmVerticalBraceNode* pNode, int nLevel )
554 SAL_INFO( "starmath.ooxml", "Vertical: " << int( pNode->GetToken().eType ));
555 switch( pNode->GetToken().eType )
557 case TOVERBRACE:
558 case TUNDERBRACE:
560 bool top = ( pNode->GetToken().eType == TOVERBRACE );
561 m_pSerializer->startElementNS(XML_m, top ? XML_limUpp : XML_limLow);
562 m_pSerializer->startElementNS(XML_m, XML_e);
563 m_pSerializer->startElementNS(XML_m, XML_groupChr);
564 m_pSerializer->startElementNS(XML_m, XML_groupChrPr);
565 m_pSerializer->singleElementNS( XML_m, XML_chr,
566 FSNS( XML_m, XML_val ), mathSymbolToString(pNode->Brace()) );
567 // TODO not sure if pos and vertJc are correct
568 m_pSerializer->singleElementNS( XML_m, XML_pos,
569 FSNS( XML_m, XML_val ), top ? "top" : "bot" );
570 m_pSerializer->singleElementNS(XML_m, XML_vertJc, FSNS(XML_m, XML_val),
571 top ? "bot" : "top");
572 m_pSerializer->endElementNS( XML_m, XML_groupChrPr );
573 m_pSerializer->startElementNS(XML_m, XML_e);
574 HandleNode( pNode->Body(), nLevel + 1 );
575 m_pSerializer->endElementNS( XML_m, XML_e );
576 m_pSerializer->endElementNS( XML_m, XML_groupChr );
577 m_pSerializer->endElementNS( XML_m, XML_e );
578 m_pSerializer->startElementNS(XML_m, XML_lim);
579 HandleNode( pNode->Script(), nLevel + 1 );
580 m_pSerializer->endElementNS( XML_m, XML_lim );
581 m_pSerializer->endElementNS( XML_m, top ? XML_limUpp : XML_limLow );
582 break;
584 default:
585 SAL_WARN("starmath.ooxml", "Unhandled vertical brace");
586 HandleAllSubNodes( pNode, nLevel );
587 break;
591 void SmOoxmlExport::HandleBlank()
593 m_pSerializer->startElementNS(XML_m, XML_r);
594 m_pSerializer->startElementNS(XML_m, XML_t, FSNS(XML_xml, XML_space), "preserve");
595 m_pSerializer->write( " " );
596 m_pSerializer->endElementNS( XML_m, XML_t );
597 m_pSerializer->endElementNS( XML_m, XML_r );
600 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */