tdf#156866 use mSize instead of mPixelSize for inverted surface
[LibreOffice.git] / hwpfilter / source / formula.cxx
bloba011e48354fd8287a44c5f4e30df5fd2188e5d3c
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "formula.h"
21 #include "grammar.hxx"
23 #include "nodes.h"
24 #include "mapping.h"
25 #include "hwpeq.h"
26 #include <iostream>
28 #ifndef DEBUG
30 #include "hcode.h"
32 #define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(false)
33 #define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(false)
34 #define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
35 #define runistr(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
36 #define reucstr(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)); } while(false)
37 #define padd(x,y,z) mxList->addAttribute(x,y,z)
38 #else
39 static int indent = 0;
40 #define inds indent++; for(int i = 0 ; i < indent ; i++) fprintf(stderr," ")
41 #define inde for(int i = 0 ; i < indent ; i++) fprintf(stderr," "); indent--
42 #define indo indent--;
43 #endif
45 void Formula::makeMathML(Node *res)
47 Node *tmp = res;
48 if( !tmp ) return;
49 #ifdef DEBUG
50 inds;
51 fprintf(stderr,"<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">\n");
52 #else
53 padd("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
54 rstartEl("math:math", mxList);
55 mxList->clear();
56 rstartEl("math:semantics", mxList);
57 #endif
58 if( tmp->child )
59 makeLines( tmp->child );
61 #ifdef DEBUG
62 inds;
63 fprintf(stderr,"<math:semantics/>\n");
64 indo;
65 inde;
66 fprintf(stderr,"</math:math>\n");
67 #else
68 rendEl("math:semantics");
69 rendEl("math:math");
70 #endif
73 void Formula::makeLines(Node *res)
75 Node *tmp = res;
76 if( !tmp ) return;
78 if( tmp->child ){
79 if( tmp->child->id == ID_LINES )
80 makeLines( tmp->child );
81 else
82 makeLine( tmp->child );
84 if( tmp->next )
85 makeLine( tmp->next );
88 void Formula::makeLine(Node *res)
90 if( !res ) return;
91 #ifdef DEBUG
92 inds; fprintf(stderr,"<math:mrow>\n");
93 #else
94 rstartEl("math:mrow", mxList);
95 #endif
96 if( res->child )
97 makeExprList( res->child );
98 #ifdef DEBUG
99 inde; fprintf(stderr,"</math:mrow>\n");
100 #else
101 rendEl("math:mrow");
102 #endif
105 void Formula::makeExprList(Node *res)
107 if( !res ) return;
108 Node *tmp = res->child;
109 if( !tmp ) return ;
111 if( tmp->id == ID_EXPRLIST ){
112 Node *next = tmp->next;
113 makeExprList( tmp ) ;
114 if( next )
115 makeExpr( next );
117 else
118 makeExpr( tmp );
121 void Formula::makeExpr(Node *res)
123 if( !res ) return;
124 Node *tmp = res->child;
125 if( !tmp ) return;
126 switch( tmp->id ) {
127 case ID_PRIMARYEXPR:
128 if( tmp->next ){
129 #ifdef DEBUG
130 inds;
131 fprintf(stderr,"<math:mrow>\n");
132 #else
133 rstartEl("math:mrow", mxList);
134 #endif
137 makePrimary(tmp);
139 if( tmp->next ){
140 #ifdef DEBUG
141 inde; fprintf(stderr,"</math:mrow>\n");
142 #else
143 rendEl("math:mrow");
144 #endif
146 break;
147 case ID_SUBEXPR:
148 case ID_SUPEXPR:
149 case ID_SUBSUPEXPR:
150 makeSubSup(tmp);
151 break;
152 case ID_FRACTIONEXPR:
153 case ID_OVER:
154 makeFraction(tmp);
155 break;
156 case ID_DECORATIONEXPR:
157 makeDecoration(tmp);
158 break;
159 case ID_SQRTEXPR:
160 case ID_ROOTEXPR:
161 makeRoot(tmp);
162 break;
163 case ID_ARROWEXPR:
164 break;
165 case ID_ACCENTEXPR:
166 makeAccent(tmp);
167 break;
168 case ID_PARENTH:
169 case ID_ABS:
170 makeParenth(tmp);
171 break;
172 case ID_FENCE:
173 makeFence(tmp);
174 break;
175 case ID_BLOCK:
176 makeBlock(tmp);
177 break;
178 case ID_BEGIN:
179 case ID_END:
180 break;
184 void Formula::makeIdentifier(Node *res)
186 Node *tmp = res;
187 if( !tmp ) return;
188 if( !tmp->value ) return;
189 switch( tmp->id ){
190 case ID_CHARACTER :
191 #ifdef DEBUG
192 inds;
193 fprintf(stderr,"<math:mi>%s</math:mi>\n",tmp->value.get());
194 indo;
195 #else
196 rstartEl("math:mi", mxList);
197 rchars(OUString::createFromAscii(tmp->value.get()));
198 rendEl("math:mi");
199 #endif
200 break;
201 case ID_STRING :
203 #ifdef DEBUG
204 #else
205 rstartEl("math:mi", mxList);
206 reucstr(tmp->value.get(), strlen(tmp->value.get()));
207 rendEl("math:mi");
208 #endif
210 break;
211 case ID_IDENTIFIER :
212 #ifdef DEBUG
213 inds;
214 fprintf(stderr,"<math:mi>%s</math:mi>\n",
215 getMathMLEntity(tmp->value.get()).c_str());
216 indo;
217 #else
218 rstartEl("math:mi", mxList);
219 runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
220 rendEl("math:mi");
221 #endif
222 break;
223 case ID_NUMBER :
224 #ifdef DEBUG
225 inds;
226 fprintf(stderr,"<math:mn>%s</math:mn>\n",tmp->value.get());
227 indo;
228 #else
229 rstartEl("math:mn", mxList);
230 rchars(OUString::createFromAscii(tmp->value.get()));
231 rendEl("math:mn");
232 #endif
233 break;
234 case ID_OPERATOR :
235 case ID_DELIMITER :
237 #ifdef DEBUG
238 inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value.get()); indo;
239 #else
240 rstartEl("math:mo", mxList);
241 runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
242 rendEl("math:mo");
243 #endif
244 break;
248 void Formula::makePrimary(Node *res)
250 Node *tmp = res;
251 if( !tmp ) return ;
252 if( tmp->child ){
253 if( tmp->child->id == ID_PRIMARYEXPR ){
254 makePrimary(tmp->child);
256 else{
257 makeIdentifier(tmp->child);
260 if( tmp->next ){
261 makeIdentifier(tmp->next);
265 void Formula::makeSubSup(Node *res)
267 Node *tmp = res;
268 if( !tmp ) return;
270 #ifdef DEBUG
271 inds;
272 if( res->id == ID_SUBEXPR )
273 fprintf(stderr,"<math:msub>\n");
274 else if( res->id == ID_SUPEXPR )
275 fprintf(stderr,"<math:msup>\n");
276 else
277 fprintf(stderr,"<math:msubsup>\n");
278 #else
279 if( res->id == ID_SUBEXPR )
280 rstartEl("math:msub", mxList);
281 else if( res->id == ID_SUPEXPR )
282 rstartEl("math:msup", mxList);
283 else
284 rstartEl("math:msubsup", mxList);
285 #endif
287 tmp = tmp->child;
288 if( res->id == ID_SUBSUPEXPR ) {
289 makeExpr(tmp);
290 makeBlock(tmp->next);
291 makeBlock(tmp->next->next);
293 else{
294 makeExpr(tmp);
295 makeExpr(tmp->next);
298 #ifdef DEBUG
299 inde;
300 if( res->id == ID_SUBEXPR )
301 fprintf(stderr,"</math:msub>\n");
302 else if( res->id == ID_SUPEXPR )
303 fprintf(stderr,"</math:msup>\n");
304 else
305 fprintf(stderr,"</math:msubsup>\n");
306 #else
307 if( res->id == ID_SUBEXPR )
308 rendEl("math:msub");
309 else if( res->id == ID_SUPEXPR )
310 rendEl("math:msup");
311 else
312 rendEl("math:msubsup");
313 #endif
316 void Formula::makeFraction(Node *res)
318 Node *tmp = res;
319 if( !tmp ) return;
321 #ifdef DEBUG
322 inds;
323 fprintf(stderr,"<math:mfrac>\n");
324 #else
325 rstartEl("math:mfrac", mxList);
326 #endif
328 tmp = tmp->child;
329 #ifdef DEBUG
330 inds;
331 fprintf(stderr,"<math:mrow>\n");
332 #else
333 rstartEl("math:mrow", mxList);
334 #endif
336 if( res->id == ID_FRACTIONEXPR )
337 makeBlock(tmp);
338 else
339 makeExprList(tmp);
341 #ifdef DEBUG
342 inde;
343 fprintf(stderr,"</math:mrow>\n");
344 inds;
345 fprintf(stderr,"<math:mrow>\n");
346 #else
347 rendEl("math:mrow");
348 rstartEl("math:mrow", mxList);
349 #endif
351 if( res->id == ID_FRACTIONEXPR )
352 makeBlock(tmp->next);
353 else
354 makeExprList(tmp->next);
356 #ifdef DEBUG
357 inde;
358 fprintf(stderr,"</math:mrow>\n");
359 inde;
360 fprintf(stderr,"</math:mfrac>\n");
361 #else
362 rendEl("math:mrow");
363 rendEl("math:mfrac");
364 #endif
367 void Formula::makeDecoration(Node *res)
369 int isover = 1;
370 Node *tmp = res->child;
371 if( !tmp ) return;
372 if( !strncmp(tmp->value.get(),"under", 5) )
373 isover = 0;
374 #ifdef DEBUG
375 inds;
376 if( isover )
377 fprintf(stderr,"<math:mover>\n");
378 else
379 fprintf(stderr,"<math:munder>\n");
380 #else
381 /* FIXME: no idea when 'accent' is true or false. */
382 if( isover ){
383 padd("accent","CDATA","true");
384 rstartEl("math:mover", mxList);
386 else{
387 padd("accentunder","CDATA","true");
388 rstartEl("math:munder", mxList);
390 mxList->clear();
391 #endif
393 makeBlock(tmp->next);
395 #ifdef DEBUG
396 inds;
397 fprintf(stderr,"<math:mo>%s</math:mo>\n",
398 getMathMLEntity(tmp->value.get()).c_str());
399 indo;
400 #else
401 rstartEl("math:mo", mxList);
402 runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
403 rendEl("math:mo");
404 #endif
406 #ifdef DEBUG
407 inde;
408 if( isover )
409 fprintf(stderr,"</math:mover>\n");
410 else
411 fprintf(stderr,"</math:munder>\n");
412 #else
413 if( isover )
414 rendEl("math:mover");
415 else
416 rendEl("math:munder");
417 #endif
420 void Formula::makeRoot(Node *res)
422 Node *tmp = res;
423 if( !tmp ) return;
424 #ifdef DEBUG
425 inds;
426 if( tmp->id == ID_SQRTEXPR )
427 fprintf(stderr,"<math:msqrt>\n");
428 else
429 fprintf(stderr,"<math:mroot>\n");
430 #else
431 if( tmp->id == ID_SQRTEXPR )
432 rstartEl("math:msqrt", mxList);
433 else
434 rstartEl("math:mroot", mxList);
435 #endif
437 if( tmp->id == ID_SQRTEXPR ){
438 makeBlock(tmp->child);
440 else{
441 makeBracket(tmp->child);
442 makeBlock(tmp->child->next);
445 #ifdef DEBUG
446 inde;
447 if( tmp->id == ID_SQRTEXPR )
448 fprintf(stderr,"</math:msqrt>\n");
449 else
450 fprintf(stderr,"</math:mroot>\n");
451 #else
452 if( tmp->id == ID_SQRTEXPR )
453 rendEl("math:msqrt");
454 else
455 rendEl("math:mroot");
456 #endif
458 void Formula::makeAccent(Node *res)
460 makeDecoration( res );
462 void Formula::makeParenth(Node *res)
464 Node *tmp = res;
465 if( !tmp ) return;
466 #ifdef DEBUG
467 inds;
468 fprintf(stderr,"<math:mrow>\n");
469 inds;
470 if( tmp->id == ID_PARENTH ){
471 fprintf(stderr,"<math:mo>(</math:mo>\n");
473 else
474 fprintf(stderr,"<math:mo>|</math:mo>\n");
475 indo; inds;
476 fprintf(stderr,"<math:mrow>\n");
477 #else
478 rstartEl("math:mrow", mxList);
479 rstartEl("math:mo", mxList);
480 if( tmp->id == ID_PARENTH )
481 rchars("(");
482 else
483 rchars("|");
484 rendEl("math:mo");
485 rstartEl("math:mrow", mxList);
486 #endif
488 if( tmp->child )
489 makeExprList(tmp->child);
491 #ifdef DEBUG
492 inde;
493 fprintf(stderr,"</math:mrow>\n");
494 inds;
495 if( tmp->id == ID_PARENTH )
496 fprintf(stderr,"<math:mo>)</math:mo>\n");
497 else
498 fprintf(stderr,"<math:mo>|</math:mo>\n");
499 indo;
500 inde;
501 fprintf(stderr,"</math:mrow>\n");
502 #else
503 rendEl("math:mrow");
504 rstartEl("math:mo", mxList);
505 if( tmp->id == ID_PARENTH )
506 rchars(")");
507 else
508 rchars("|");
509 rendEl("math:mo");
510 rendEl("math:mrow");
511 #endif
514 void Formula::makeFence(Node *res)
516 Node *tmp = res->child;
517 #ifdef DEBUG
518 inds;
519 fprintf(stderr,"<math:mfenced open=\"%s\" close=\"%s\">\n",
520 getMathMLEntity(tmp->value.get()).c_str(),
521 getMathMLEntity(tmp->next->next->value.get()).c_str());
522 #else
523 padd("open", "CDATA",
524 OUString(reinterpret_cast<sal_Unicode const *>(getMathMLEntity(tmp->value.get()).c_str())));
525 padd("close", "CDATA",
526 OUString(reinterpret_cast<sal_Unicode const *>(getMathMLEntity(tmp->next->next->value.get()).c_str())));
527 rstartEl("math:mfenced", mxList);
528 mxList->clear();
529 #endif
531 makeExprList(tmp->next);
533 #ifdef DEBUG
534 inde;
535 fprintf(stderr,"</math:mfenced>\n");
536 #else
537 rendEl("math:mfenced");
538 #endif
541 void Formula::makeBracket(Node *res)
543 makeBlock(res);
546 void Formula::makeBlock(Node *res)
548 #ifdef DEBUG
549 inds;
550 fprintf(stderr,"<math:mrow>\n");
551 #else
552 rstartEl("math:mrow", mxList);
553 #endif
555 if( res->child )
556 makeExprList(res->child);
558 #ifdef DEBUG
559 inde;
560 fprintf(stderr,"</math:mrow>\n");
561 #else
562 rendEl("math:mrow");
563 #endif
566 void Formula::parse()
568 Node *res = nullptr;
569 if( !eq ) return;
571 OString a;
572 // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
573 eq2latex(a,eq);
575 int idx=a.indexOf('\xff');
576 while(idx >= 0){
577 //printf("idx = [%d]\n",idx);
578 a = a.replaceAt(idx, 1, "\x20");
579 idx = a.indexOf('\xff', idx + 1);
582 char *buf = static_cast<char *>(malloc(a.getLength()+1));
583 bool bStart = false;
584 int i, j;
585 for( i = 0, j=0 ; i < a.getLength() ; i++){ // rtrim and ltrim 32 10 13
586 if( bStart ){
587 buf[j++] = a[i];
589 else{
590 if( a[i] != 32 && a[i] != 10 && a[i] != 13){
591 bStart = true;
592 buf[j++] = a[i];
596 buf[j] = 0;
597 for( i = j-1 ; i >= 0 ; i++ ){
598 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
599 buf[i] = 0;
601 else
602 break;
604 // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
605 if( buf[0] != '\0' )
606 res = mainParse( a.getStr() );
607 else
608 res = nullptr;
609 free(buf);
611 if( res ){
612 makeMathML( res );
614 nodelist.clear();
617 void Formula::trim()
619 int len = strlen(eq);
620 char *buf = static_cast<char *>(malloc(len+1));
621 bool bStart = false;
622 int i, j;
623 for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
624 if( bStart ){
625 buf[j++] = eq[i];
627 else{
628 if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
629 bStart = true;
630 buf[j++] = eq[i];
634 buf[j] = 0;
635 for( i = j-1 ; i >= 0 ; i++ ){
636 if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
637 buf[i] = 0;
639 else
640 break;
642 if( buf[0] != '\0' )
643 strcpy(eq, buf);
644 else
645 eq = nullptr;
646 free(buf);
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */