cURL: follow redirects
[LibreOffice.git] / starmath / source / ooxmlexport.cxx
blob23529ebd8906a9b3982c6f146b1d7c85c6b54955
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 */
11 #include "ooxmlexport.hxx"
13 #include <oox/token/tokens.hxx>
14 #include <rtl/ustring.hxx>
16 using namespace oox;
17 using namespace oox::core;
19 SmOoxmlExport::SmOoxmlExport(const SmNode *const pIn, OoxmlVersion const v,
20 drawingml::DocumentType const documentType)
21 : SmWordExportBase( pIn )
22 , version( v )
23 , m_DocumentType(documentType)
27 bool SmOoxmlExport::ConvertFromStarMath( const ::sax_fastparser::FSHelperPtr& serializer )
29 if( m_pTree == nullptr )
30 return false;
31 m_pSerializer = serializer;
32 m_pSerializer->startElementNS( XML_m, XML_oMath,
33 FSNS( XML_xmlns, XML_m ), "http://schemas.openxmlformats.org/officeDocument/2006/math", FSEND );
34 HandleNode( m_pTree, 0 );
35 m_pSerializer->endElementNS( XML_m, XML_oMath );
36 return true;
39 // NOTE: This is still work in progress and unfinished, but it already covers a good
40 // part of the ooxml math stuff.
42 void SmOoxmlExport::HandleVerticalStack( const SmNode* pNode, int nLevel )
44 m_pSerializer->startElementNS( XML_m, XML_eqArr, FSEND );
45 int size = pNode->GetNumSubNodes();
46 for( int i = 0;
47 i < size;
48 ++i )
50 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
51 HandleNode( pNode->GetSubNode( i ), nLevel + 1 );
52 m_pSerializer->endElementNS( XML_m, XML_e );
54 m_pSerializer->endElementNS( XML_m, XML_eqArr );
57 void SmOoxmlExport::HandleText( const SmNode* pNode, int /*nLevel*/)
59 m_pSerializer->startElementNS( XML_m, XML_r, FSEND );
61 if( pNode->GetToken().eType == TTEXT ) // literal text (in quotes)
63 m_pSerializer->startElementNS( XML_m, XML_rPr, FSEND );
64 m_pSerializer->singleElementNS( XML_m, XML_lit, FSEND );
65 m_pSerializer->singleElementNS( XML_m, XML_nor, FSEND );
66 m_pSerializer->endElementNS( XML_m, XML_rPr );
68 if (drawingml::DOCUMENT_DOCX == m_DocumentType && ECMA_DIALECT == version)
69 { // HACK: MSOffice2007 does not import characters properly unless this font is explicitly given
70 m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
71 m_pSerializer->singleElementNS( XML_w, XML_rFonts, FSNS( XML_w, XML_ascii ), "Cambria Math",
72 FSNS( XML_w, XML_hAnsi ), "Cambria Math", FSEND );
73 m_pSerializer->endElementNS( XML_w, XML_rPr );
75 m_pSerializer->startElementNS( XML_m, XML_t, FSNS( XML_xml, XML_space ), "preserve", FSEND );
76 const SmTextNode* pTemp = static_cast<const SmTextNode* >(pNode);
77 SAL_INFO( "starmath.ooxml", "Text:" << OUStringToOString( pTemp->GetText(), RTL_TEXTENCODING_UTF8 ).getStr());
78 OUStringBuffer buf(pTemp->GetText());
79 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
81 #if 0
82 if ((nPendingAttributes) &&
83 (i == ((pTemp->GetText().getLength()+1)/2)-1))
85 *pS << sal_uInt8(0x22); //char, with attributes right
86 //after the character
88 else
89 *pS << sal_uInt8(CHAR);
91 sal_uInt8 nFace = 0x1;
92 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
93 nFace = 0x3;
94 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
95 nFace = 0x7;
96 *pS << sal_uInt8(nFace+128); //typeface
97 #endif
98 buf[i] = SmTextNode::ConvertSymbolToUnicode(buf[i]);
99 #if 0
100 //Mathtype can only have these sort of character
101 //attributes on a single character, starmath can put them
102 //anywhere, when the entity involved is a text run this is
103 //a large effort to place the character attribute on the
104 //central mathtype character so that it does pretty much
105 //what the user probably has in mind. The attributes
106 //filled in here are dummy ones which are replaced in the
107 //ATTRIBUT handler if a suitable location for the
108 //attributes was found here. Unfortunately it is
109 //possible for starmath to place character attributes on
110 //entities which cannot occur in mathtype e.g. a Summation
111 //symbol so these attributes may be lost
112 if ((nPendingAttributes) &&
113 (i == ((pTemp->GetText().getLength()+1)/2)-1))
115 *pS << sal_uInt8(EMBEL);
116 while (nPendingAttributes)
118 *pS << sal_uInt8(2);
119 //wedge the attributes in here and clear
120 //the pending stack
121 nPendingAttributes--;
123 nInsertion=pS->Tell();
124 *pS << sal_uInt8(END); //end embel
125 *pS << sal_uInt8(END); //end embel
127 #endif
129 m_pSerializer->writeEscaped(buf.makeStringAndClear());
130 m_pSerializer->endElementNS( XML_m, XML_t );
131 m_pSerializer->endElementNS( XML_m, XML_r );
134 void SmOoxmlExport::HandleFractions( const SmNode* pNode, int nLevel, const char* type )
136 m_pSerializer->startElementNS( XML_m, XML_f, FSEND );
137 if( type != nullptr )
139 m_pSerializer->startElementNS( XML_m, XML_fPr, FSEND );
140 m_pSerializer->singleElementNS( XML_m, XML_type, FSNS( XML_m, XML_val ), type, FSEND );
141 m_pSerializer->endElementNS( XML_m, XML_fPr );
143 assert( pNode->GetNumSubNodes() == 3 );
144 m_pSerializer->startElementNS( XML_m, XML_num, FSEND );
145 HandleNode( pNode->GetSubNode( 0 ), nLevel + 1 );
146 m_pSerializer->endElementNS( XML_m, XML_num );
147 m_pSerializer->startElementNS( XML_m, XML_den, FSEND );
148 HandleNode( pNode->GetSubNode( 2 ), nLevel + 1 );
149 m_pSerializer->endElementNS( XML_m, XML_den );
150 m_pSerializer->endElementNS( XML_m, XML_f );
153 void SmOoxmlExport::HandleAttribute( const SmAttributNode* pNode, int nLevel )
155 switch( pNode->Attribute()->GetToken().eType )
157 case TCHECK:
158 case TACUTE:
159 case TGRAVE:
160 case TBREVE:
161 case TCIRCLE:
162 case TVEC:
163 case TTILDE:
164 case THAT:
165 case TDOT:
166 case TDDOT:
167 case TDDDOT:
168 case TWIDETILDE:
169 case TWIDEHAT:
170 case TWIDEVEC:
171 case TBAR:
173 m_pSerializer->startElementNS( XML_m, XML_acc, FSEND );
174 m_pSerializer->startElementNS( XML_m, XML_accPr, FSEND );
175 OString value = OUStringToOString(
176 OUString( pNode->Attribute()->GetToken().cMathChar ), RTL_TEXTENCODING_UTF8 );
177 m_pSerializer->singleElementNS( XML_m, XML_chr, FSNS( XML_m, XML_val ), value.getStr(), FSEND );
178 m_pSerializer->endElementNS( XML_m, XML_accPr );
179 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
180 HandleNode( pNode->Body(), nLevel + 1 );
181 m_pSerializer->endElementNS( XML_m, XML_e );
182 m_pSerializer->endElementNS( XML_m, XML_acc );
183 break;
185 case TOVERLINE:
186 case TUNDERLINE:
187 m_pSerializer->startElementNS( XML_m, XML_bar, FSEND );
188 m_pSerializer->startElementNS( XML_m, XML_barPr, FSEND );
189 m_pSerializer->singleElementNS( XML_m, XML_pos, FSNS( XML_m, XML_val ),
190 ( pNode->Attribute()->GetToken().eType == TUNDERLINE ) ? "bot" : "top", FSEND );
191 m_pSerializer->endElementNS( XML_m, XML_barPr );
192 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
193 HandleNode( pNode->Body(), nLevel + 1 );
194 m_pSerializer->endElementNS( XML_m, XML_e );
195 m_pSerializer->endElementNS( XML_m, XML_bar );
196 break;
197 case TOVERSTRIKE:
198 m_pSerializer->startElementNS( XML_m, XML_borderBox, FSEND );
199 m_pSerializer->startElementNS( XML_m, XML_borderBoxPr, FSEND );
200 m_pSerializer->singleElementNS( XML_m, XML_hideTop, FSNS( XML_m, XML_val ), "1", FSEND );
201 m_pSerializer->singleElementNS( XML_m, XML_hideBot, FSNS( XML_m, XML_val ), "1", FSEND );
202 m_pSerializer->singleElementNS( XML_m, XML_hideLeft, FSNS( XML_m, XML_val ), "1", FSEND );
203 m_pSerializer->singleElementNS( XML_m, XML_hideRight, FSNS( XML_m, XML_val ), "1", FSEND );
204 m_pSerializer->singleElementNS( XML_m, XML_strikeH, FSNS( XML_m, XML_val ), "1", FSEND );
205 m_pSerializer->endElementNS( XML_m, XML_borderBoxPr );
206 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
207 HandleNode( pNode->Body(), nLevel + 1 );
208 m_pSerializer->endElementNS( XML_m, XML_e );
209 m_pSerializer->endElementNS( XML_m, XML_borderBox );
210 break;
211 default:
212 HandleAllSubNodes( pNode, nLevel );
213 break;
217 void SmOoxmlExport::HandleRoot( const SmRootNode* pNode, int nLevel )
219 m_pSerializer->startElementNS( XML_m, XML_rad, FSEND );
220 if( const SmNode* argument = pNode->Argument())
222 m_pSerializer->startElementNS( XML_m, XML_deg, FSEND );
223 HandleNode( argument, nLevel + 1 );
224 m_pSerializer->endElementNS( XML_m, XML_deg );
226 else
228 m_pSerializer->startElementNS( XML_m, XML_radPr, FSEND );
229 m_pSerializer->singleElementNS( XML_m, XML_degHide, FSNS( XML_m, XML_val ), "1", FSEND );
230 m_pSerializer->endElementNS( XML_m, XML_radPr );
231 m_pSerializer->singleElementNS( XML_m, XML_deg, FSEND ); // empty but present
233 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
234 HandleNode( pNode->Body(), nLevel + 1 );
235 m_pSerializer->endElementNS( XML_m, XML_e );
236 m_pSerializer->endElementNS( XML_m, XML_rad );
239 static OString mathSymbolToString( const SmNode* node )
241 assert( node->GetType() == NMATH || node->GetType() == NMATHIDENT );
242 const SmTextNode* txtnode = static_cast< const SmTextNode* >( node );
243 assert( txtnode->GetText().getLength() == 1 );
244 sal_Unicode chr = SmTextNode::ConvertSymbolToUnicode( txtnode->GetText()[0] );
245 return OUStringToOString( OUString( chr ), RTL_TEXTENCODING_UTF8 );
248 void SmOoxmlExport::HandleOperator( const SmOperNode* pNode, int nLevel )
250 SAL_INFO( "starmath.ooxml", "Operator: " << int( pNode->GetToken().eType ));
251 switch( pNode->GetToken().eType )
253 case TINT:
254 case TINTD:
255 case TIINT:
256 case TIIINT:
257 case TLINT:
258 case TLLINT:
259 case TLLLINT:
260 case TPROD:
261 case TCOPROD:
262 case TSUM:
264 const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == NSUBSUP
265 ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr;
266 const SmNode* operation = subsup != nullptr ? subsup->GetBody() : pNode->GetSubNode( 0 );
267 m_pSerializer->startElementNS( XML_m, XML_nary, FSEND );
268 m_pSerializer->startElementNS( XML_m, XML_naryPr, FSEND );
269 m_pSerializer->singleElementNS( XML_m, XML_chr,
270 FSNS( XML_m, XML_val ), mathSymbolToString( operation ).getStr(), FSEND );
271 if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr )
272 m_pSerializer->singleElementNS( XML_m, XML_subHide, FSNS( XML_m, XML_val ), "1", FSEND );
273 if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr )
274 m_pSerializer->singleElementNS( XML_m, XML_supHide, FSNS( XML_m, XML_val ), "1", FSEND );
275 m_pSerializer->endElementNS( XML_m, XML_naryPr );
276 if( subsup == nullptr || subsup->GetSubSup( CSUB ) == nullptr )
277 m_pSerializer->singleElementNS( XML_m, XML_sub, FSEND );
278 else
280 m_pSerializer->startElementNS( XML_m, XML_sub, FSEND );
281 HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 );
282 m_pSerializer->endElementNS( XML_m, XML_sub );
284 if( subsup == nullptr || subsup->GetSubSup( CSUP ) == nullptr )
285 m_pSerializer->singleElementNS( XML_m, XML_sup, FSEND );
286 else
288 m_pSerializer->startElementNS( XML_m, XML_sup, FSEND );
289 HandleNode( subsup->GetSubSup( CSUP ), nLevel + 1 );
290 m_pSerializer->endElementNS( XML_m, XML_sup );
292 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
293 HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body
294 m_pSerializer->endElementNS( XML_m, XML_e );
295 m_pSerializer->endElementNS( XML_m, XML_nary );
296 break;
298 case TLIM:
299 m_pSerializer->startElementNS( XML_m, XML_func, FSEND );
300 m_pSerializer->startElementNS( XML_m, XML_fName, FSEND );
301 m_pSerializer->startElementNS( XML_m, XML_limLow, FSEND );
302 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
303 HandleNode( pNode->GetSymbol(), nLevel + 1 );
304 m_pSerializer->endElementNS( XML_m, XML_e );
305 m_pSerializer->startElementNS( XML_m, XML_lim, FSEND );
306 if( const SmSubSupNode* subsup = pNode->GetSubNode( 0 )->GetType() == NSUBSUP
307 ? static_cast< const SmSubSupNode* >( pNode->GetSubNode( 0 )) : nullptr )
309 if( subsup->GetSubSup( CSUB ) != nullptr )
310 HandleNode( subsup->GetSubSup( CSUB ), nLevel + 1 );
312 m_pSerializer->endElementNS( XML_m, XML_lim );
313 m_pSerializer->endElementNS( XML_m, XML_limLow );
314 m_pSerializer->endElementNS( XML_m, XML_fName );
315 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
316 HandleNode( pNode->GetSubNode( 1 ), nLevel + 1 ); // body
317 m_pSerializer->endElementNS( XML_m, XML_e );
318 m_pSerializer->endElementNS( XML_m, XML_func );
319 break;
320 default:
321 SAL_WARN("starmath.ooxml", "Unhandled operation");
322 HandleAllSubNodes( pNode, nLevel );
323 break;
327 void SmOoxmlExport::HandleSubSupScriptInternal( const SmSubSupNode* pNode, int nLevel, int flags )
329 // docx supports only a certain combination of sub/super scripts, but LO can have any,
330 // so try to merge it using several tags if necessary
331 if( flags == 0 ) // none
332 return;
333 if(( flags & ( 1 << RSUP | 1 << RSUB )) == ( 1 << RSUP | 1 << RSUB ))
334 { // m:sSubSup
335 m_pSerializer->startElementNS( XML_m, XML_sSubSup, FSEND );
336 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
337 flags &= ~( 1 << RSUP | 1 << RSUB );
338 if( flags == 0 )
339 HandleNode( pNode->GetBody(), nLevel + 1 );
340 else
341 HandleSubSupScriptInternal( pNode, nLevel, flags );
342 m_pSerializer->endElementNS( XML_m, XML_e );
343 m_pSerializer->startElementNS( XML_m, XML_sub, FSEND );
344 HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 );
345 m_pSerializer->endElementNS( XML_m, XML_sub );
346 m_pSerializer->startElementNS( XML_m, XML_sup, FSEND );
347 HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 );
348 m_pSerializer->endElementNS( XML_m, XML_sup );
349 m_pSerializer->endElementNS( XML_m, XML_sSubSup );
351 else if(( flags & ( 1 << RSUB )) == 1 << RSUB )
352 { // m:sSub
353 m_pSerializer->startElementNS( XML_m, XML_sSub, FSEND );
354 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
355 flags &= ~( 1 << RSUB );
356 if( flags == 0 )
357 HandleNode( pNode->GetBody(), nLevel + 1 );
358 else
359 HandleSubSupScriptInternal( pNode, nLevel, flags );
360 m_pSerializer->endElementNS( XML_m, XML_e );
361 m_pSerializer->startElementNS( XML_m, XML_sub, FSEND );
362 HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 );
363 m_pSerializer->endElementNS( XML_m, XML_sub );
364 m_pSerializer->endElementNS( XML_m, XML_sSub );
366 else if(( flags & ( 1 << RSUP )) == 1 << RSUP )
367 { // m:sSup
368 m_pSerializer->startElementNS( XML_m, XML_sSup, FSEND );
369 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
370 flags &= ~( 1 << RSUP );
371 if( flags == 0 )
372 HandleNode( pNode->GetBody(), nLevel + 1 );
373 else
374 HandleSubSupScriptInternal( pNode, nLevel, flags );
375 m_pSerializer->endElementNS( XML_m, XML_e );
376 m_pSerializer->startElementNS( XML_m, XML_sup, FSEND );
377 HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 );
378 m_pSerializer->endElementNS( XML_m, XML_sup );
379 m_pSerializer->endElementNS( XML_m, XML_sSup );
381 else if(( flags & ( 1 << LSUP | 1 << LSUB )) == ( 1 << LSUP | 1 << LSUB ))
382 { // m:sPre
383 m_pSerializer->startElementNS( XML_m, XML_sPre, FSEND );
384 m_pSerializer->startElementNS( XML_m, XML_sub, FSEND );
385 HandleNode( pNode->GetSubSup( LSUB ), nLevel + 1 );
386 m_pSerializer->endElementNS( XML_m, XML_sub );
387 m_pSerializer->startElementNS( XML_m, XML_sup, FSEND );
388 HandleNode( pNode->GetSubSup( LSUP ), nLevel + 1 );
389 m_pSerializer->endElementNS( XML_m, XML_sup );
390 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
391 flags &= ~( 1 << LSUP | 1 << LSUB );
392 if( flags == 0 )
393 HandleNode( pNode->GetBody(), nLevel + 1 );
394 else
395 HandleSubSupScriptInternal( pNode, nLevel, flags );
396 m_pSerializer->endElementNS( XML_m, XML_e );
397 m_pSerializer->endElementNS( XML_m, XML_sPre );
399 else if(( flags & ( 1 << CSUB )) == ( 1 << CSUB ))
400 { // m:limLow looks like a good element for central superscript
401 m_pSerializer->startElementNS( XML_m, XML_limLow, FSEND );
402 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
403 flags &= ~( 1 << CSUB );
404 if( flags == 0 )
405 HandleNode( pNode->GetBody(), nLevel + 1 );
406 else
407 HandleSubSupScriptInternal( pNode, nLevel, flags );
408 m_pSerializer->endElementNS( XML_m, XML_e );
409 m_pSerializer->startElementNS( XML_m, XML_lim, FSEND );
410 HandleNode( pNode->GetSubSup( CSUB ), nLevel + 1 );
411 m_pSerializer->endElementNS( XML_m, XML_lim );
412 m_pSerializer->endElementNS( XML_m, XML_limLow );
414 else if(( flags & ( 1 << CSUP )) == ( 1 << CSUP ))
415 { // m:limUpp looks like a good element for central superscript
416 m_pSerializer->startElementNS( XML_m, XML_limUpp, FSEND );
417 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
418 flags &= ~( 1 << CSUP );
419 if( flags == 0 )
420 HandleNode( pNode->GetBody(), nLevel + 1 );
421 else
422 HandleSubSupScriptInternal( pNode, nLevel, flags );
423 m_pSerializer->endElementNS( XML_m, XML_e );
424 m_pSerializer->startElementNS( XML_m, XML_lim, FSEND );
425 HandleNode( pNode->GetSubSup( CSUP ), nLevel + 1 );
426 m_pSerializer->endElementNS( XML_m, XML_lim );
427 m_pSerializer->endElementNS( XML_m, XML_limUpp );
429 else
431 SAL_WARN("starmath.ooxml", "Unhandled sub/sup combination");
432 // TODO do not do anything, this should be probably an assert()
433 // HandleAllSubNodes( pNode, nLevel );
437 void SmOoxmlExport::HandleMatrix( const SmMatrixNode* pNode, int nLevel )
439 m_pSerializer->startElementNS( XML_m, XML_m, FSEND );
440 for( int row = 0; row < pNode->GetNumRows(); ++row )
442 m_pSerializer->startElementNS( XML_m, XML_mr, FSEND );
443 for( int col = 0; col < pNode->GetNumCols(); ++col )
445 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
446 if( const SmNode* node = pNode->GetSubNode( row * pNode->GetNumCols() + col ))
447 HandleNode( node, nLevel + 1 );
448 m_pSerializer->endElementNS( XML_m, XML_e );
450 m_pSerializer->endElementNS( XML_m, XML_mr );
452 m_pSerializer->endElementNS( XML_m, XML_m );
455 void SmOoxmlExport::HandleBrace( const SmBraceNode* pNode, int nLevel )
457 m_pSerializer->startElementNS( XML_m, XML_d, FSEND );
458 m_pSerializer->startElementNS( XML_m, XML_dPr, FSEND );
460 //check if the node has an opening brace
461 if( TNONE == pNode->OpeningBrace()->GetToken().eType )
462 m_pSerializer->singleElementNS( XML_m, XML_begChr,
463 FSNS( XML_m, XML_val ), "", FSEND );
464 else
465 m_pSerializer->singleElementNS( XML_m, XML_begChr,
466 FSNS( XML_m, XML_val ), mathSymbolToString( pNode->OpeningBrace()).getStr(), FSEND );
468 std::vector< const SmNode* > subnodes;
469 if( pNode->Body()->GetType() == NBRACEBODY )
471 const SmBracebodyNode* body = static_cast< const SmBracebodyNode* >( pNode->Body());
472 bool separatorWritten = false; // assume all separators are the same
473 for( int i = 0; i < body->GetNumSubNodes(); ++i )
475 const SmNode* subnode = body->GetSubNode( i );
476 if (subnode->GetType() == NMATH || subnode->GetType() == NMATHIDENT)
477 { // do not write, but write what separator it is
478 const SmMathSymbolNode* math = static_cast< const SmMathSymbolNode* >( subnode );
479 if( !separatorWritten )
481 m_pSerializer->singleElementNS( XML_m, XML_sepChr,
482 FSNS( XML_m, XML_val ), mathSymbolToString( math ).getStr(), FSEND );
483 separatorWritten = true;
486 else
487 subnodes.push_back( subnode );
490 else
491 subnodes.push_back( pNode->Body());
493 if( TNONE == pNode->ClosingBrace()->GetToken().eType )
494 m_pSerializer->singleElementNS( XML_m, XML_endChr,
495 FSNS( XML_m, XML_val ), "", FSEND );
496 else
497 m_pSerializer->singleElementNS( XML_m, XML_endChr,
498 FSNS( XML_m, XML_val ), mathSymbolToString( pNode->ClosingBrace()).getStr(), FSEND );
500 m_pSerializer->endElementNS( XML_m, XML_dPr );
501 for(const SmNode* subnode : subnodes)
503 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
504 HandleNode( subnode, nLevel + 1 );
505 m_pSerializer->endElementNS( XML_m, XML_e );
507 m_pSerializer->endElementNS( XML_m, XML_d );
510 void SmOoxmlExport::HandleVerticalBrace( const SmVerticalBraceNode* pNode, int nLevel )
512 SAL_INFO( "starmath.ooxml", "Vertical: " << int( pNode->GetToken().eType ));
513 switch( pNode->GetToken().eType )
515 case TOVERBRACE:
516 case TUNDERBRACE:
518 bool top = ( pNode->GetToken().eType == TOVERBRACE );
519 m_pSerializer->startElementNS( XML_m, top ? XML_limUpp : XML_limLow, FSEND );
520 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
521 m_pSerializer->startElementNS( XML_m, XML_groupChr, FSEND );
522 m_pSerializer->startElementNS( XML_m, XML_groupChrPr, FSEND );
523 m_pSerializer->singleElementNS( XML_m, XML_chr,
524 FSNS( XML_m, XML_val ), mathSymbolToString( pNode->Brace()).getStr(), FSEND );
525 // TODO not sure if pos and vertJc are correct
526 m_pSerializer->singleElementNS( XML_m, XML_pos,
527 FSNS( XML_m, XML_val ), top ? "top" : "bot", FSEND );
528 m_pSerializer->singleElementNS( XML_m, XML_vertJc, FSNS( XML_m, XML_val ), top ? "bot" : "top", FSEND );
529 m_pSerializer->endElementNS( XML_m, XML_groupChrPr );
530 m_pSerializer->startElementNS( XML_m, XML_e, FSEND );
531 HandleNode( pNode->Body(), nLevel + 1 );
532 m_pSerializer->endElementNS( XML_m, XML_e );
533 m_pSerializer->endElementNS( XML_m, XML_groupChr );
534 m_pSerializer->endElementNS( XML_m, XML_e );
535 m_pSerializer->startElementNS( XML_m, XML_lim, FSEND );
536 HandleNode( pNode->Script(), nLevel + 1 );
537 m_pSerializer->endElementNS( XML_m, XML_lim );
538 m_pSerializer->endElementNS( XML_m, top ? XML_limUpp : XML_limLow );
539 break;
541 default:
542 SAL_WARN("starmath.ooxml", "Unhandled vertical brace");
543 HandleAllSubNodes( pNode, nLevel );
544 break;
548 void SmOoxmlExport::HandleBlank()
550 m_pSerializer->startElementNS( XML_m, XML_r, FSEND );
551 m_pSerializer->startElementNS( XML_m, XML_t, FSNS( XML_xml, XML_space ), "preserve", FSEND );
552 m_pSerializer->write( " " );
553 m_pSerializer->endElementNS( XML_m, XML_t );
554 m_pSerializer->endElementNS( XML_m, XML_r );
557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */