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