23#include <tqfontmetrics.h>
26#include <tdemessagebox.h>
30#include "kformulamathmlread.h"
31#include "symboltable.h"
33KFORMULA_NAMESPACE_BEGIN
36class MathML2KFormulaPrivate
43 const TQDomDocument& formuladoc );
44 ~MathML2KFormulaPrivate();
46 void math( TQDomElement element );
49 void mi( TQDomElement element, TQDomNode docnode );
50 void mn( TQDomElement element, TQDomNode docnode );
51 void mo( TQDomElement element, TQDomNode docnode );
52 void mtext( TQDomElement element, TQDomNode docnode );
53 void mspace( TQDomElement element, TQDomNode docnode );
54 void ms( TQDomElement element, TQDomNode docnode );
58 void mrow( TQDomElement element, TQDomNode docnode );
59 void mfrac( TQDomElement element, TQDomNode docnode );
60 void msqrt( TQDomElement element, TQDomNode docnode );
61 void mroot( TQDomElement element, TQDomNode docnode );
62 void mstyle( TQDomElement element, TQDomNode docnode );
66 void mfenced( TQDomElement element, TQDomNode docnode );
70 void msub_msup( TQDomElement element, TQDomNode docnode );
71 void msubsup( TQDomElement element, TQDomNode docnode );
72 void munder( TQDomElement element, TQDomNode docnode,
bool oasisFormat );
73 void mover( TQDomElement element, TQDomNode docnode,
bool oasisFormat );
74 void munderover( TQDomElement element, TQDomNode docnode,
bool oasisFormat );
78 void mtable( TQDomElement element, TQDomNode docnode );
85 void createTextElements( TQString text, TQDomNode docnode );
86 void createNameSequence( TQString text, TQDomNode docnode );
87 double convertToPoint( TQString value,
bool* ok );
88 bool isEmbellishedOperator( TQDomNode node, TQDomElement* mo,
bool oasisFormat );
89 bool isSpaceLike( TQDomNode node,
bool oasisFormat );
104 sans_serif_bold_italic,
110 : scriptsizemultiplier( 0.71 ),
112 veryverythinmathspace( 1.0/18.0 ),
113 verythinmathspace( 2.0/18.0 ),
114 thinmathspace( 3.0/18.0 ),
115 mediummathspace( 4.0/18.0 ),
116 thickmathspace( 5.0/18.0 ),
117 verythickmathspace( 6.0/18.0 ),
118 veryverythickmathspace( 7.0/18.0 ),
126 kdDebug( DEBUGID ) <<
"Style Change:"
127 <<
"\n scriptlevel = " << scriptlevel
128 <<
"\n displaystyle = " << displaystyle
129 <<
"\n scriptsizemultiplier = "
130 << scriptsizemultiplier
131 <<
"\n scriptminsize = " << scriptminsize
135 void setStyles( TQDomElement element )
140 switch ( mathvariant )
143 element.setAttribute(
"STYLE",
"normal" );
146 element.setAttribute(
"STYLE",
"bold" );
150 element.setAttribute(
"STYLE",
"bolditalic" );
153 element.setAttribute(
"STYLE",
"italic" );
157 element.setAttribute(
"FAMILY",
"doublestruck" );
161 element.setAttribute(
"STYLE",
"bold" );
163 element.setAttribute(
"FAMILY",
"fraktur" );
167 element.setAttribute(
"STYLE",
"bold" );
169 element.setAttribute(
"FAMILY",
"script" );
172 case bold_sans_serif:
173 element.setAttribute(
"STYLE",
"bold" );
175 element.setAttribute(
"FAMILY",
"normal" );
177 case sans_serif_bold_italic:
178 element.setAttribute(
"STYLE",
"bolditalic" );
179 element.setAttribute(
"FAMILY",
"normal" );
181 case sans_serif_italic:
182 element.setAttribute(
"STYLE",
"italic" );
183 element.setAttribute(
"FAMILY",
"normal" );
192 void readStyles( TQDomElement mmlElement )
194 if ( mmlElement.hasAttribute(
"mathvariant" ) )
198 if ( mmlElement.attribute(
"mathvariant" ) ==
"normal" )
199 mathvariant = normal;
200 else if ( mmlElement.attribute(
"mathvariant" ) ==
"bold" )
202 else if ( mmlElement.attribute(
"mathvariant" ) ==
"italic" )
203 mathvariant = italic;
204 else if ( mmlElement.attribute(
"mathvariant" ) ==
"bold-italic" )
205 mathvariant = bold_italic;
206 else if ( mmlElement.attribute(
"mathvariant" ) ==
"double-struck" )
207 mathvariant = double_struck;
208 else if ( mmlElement.attribute(
"mathvariant" ) ==
"bold-fraktur" )
209 mathvariant = bold_fraktur;
210 else if ( mmlElement.attribute(
"mathvariant" ) ==
"script" )
211 mathvariant = script;
212 else if ( mmlElement.attribute(
"mathvariant" ) ==
"bold-script" )
213 mathvariant = bold_script;
214 else if ( mmlElement.attribute(
"mathvariant" ) ==
"fraktur" )
215 mathvariant = fraktur;
216 else if ( mmlElement.attribute(
"mathvariant" ) ==
"sans-serif" )
217 mathvariant = sans_serif;
218 else if ( mmlElement.attribute(
"mathvariant" ) ==
"bold-sans-serif" )
219 mathvariant = bold_sans_serif;
220 else if ( mmlElement.attribute(
"mathvariant" ) ==
"sans-serif-italic" )
221 mathvariant = sans_serif_italic;
222 else if ( mmlElement.attribute(
"mathvariant" ) ==
"sans-serif-bold-italic" )
223 mathvariant = sans_serif_bold_italic;
224 else if ( mmlElement.attribute(
"mathvariant" ) ==
"monospace" )
225 mathvariant = monospace;
233 double scriptsizemultiplier;
234 double scriptminsize;
237 double veryverythinmathspace;
238 double verythinmathspace;
239 double thinmathspace;
240 double mediummathspace;
241 double thickmathspace;
242 double verythickmathspace;
243 double veryverythickmathspace;
247 MathVariant mathvariant;
260MathML2KFormulaPrivate::MathML2KFormulaPrivate(
MathML2KFormula* mml_filter,
const ContextStyle& cs,
const TQDomDocument& formuladoc )
261 : doc( formuladoc ), context( cs ), filter( mml_filter )
265MathML2KFormulaPrivate::~MathML2KFormulaPrivate()
269void MathML2KFormulaPrivate::math( TQDomElement element )
271 TQDomElement formula = doc.createElement(
"FORMULA" );
272 TQDomNode n = element.firstChild();
274 TQString display = element.attribute(
"display" );
276 if ( display ==
"block" ) {
277 style.displaystyle =
true;
281 style.displaystyle =
false;
284 style.scriptlevel = 0;
290 while ( !n.isNull() ) {
291 filter->processElement( n, doc, formula );
295 doc.appendChild( formula );
298void MathML2KFormulaPrivate::mi( TQDomElement element, TQDomNode docnode )
300 MathStyle previousStyle( style );
301 TQString text = element.text().stripWhiteSpace();
302 if ( text.length() == 1 ) {
303 style.mathvariant = italic;
304 style.useVariant =
true;
305 style.readStyles( element );
306 createTextElements( text, docnode );
308 style.readStyles( element );
309 createNameSequence( text, docnode );
311 style = previousStyle;
314void MathML2KFormulaPrivate::mo( TQDomElement element, TQDomNode docnode )
316 MathStyle previousStyle( style );
317 style.readStyles( element );
319 TQString text = element.text().stripWhiteSpace();
320 createTextElements( text, docnode );
322 style = previousStyle;
325void MathML2KFormulaPrivate::mn( TQDomElement element, TQDomNode docnode )
327 MathStyle previousStyle( style );
328 style.readStyles( element );
330 TQString text = element.text().stripWhiteSpace();
331 createTextElements( text, docnode );
333 style = previousStyle;
336void MathML2KFormulaPrivate::mtext( TQDomElement element, TQDomNode docnode )
338 MathStyle previousStyle( style );
339 style.readStyles( element );
341 TQDomNode n = element.firstChild();
343 while ( !n.isNull() ) {
345 TQString text = n.toText().data().stripWhiteSpace();
346 createTextElements( text, docnode );
348 else if ( n.isElement() ) {
349 filter->processElement( n, doc, docnode );
352 kdDebug( DEBUGID ) <<
"<mtext> child: " << n.nodeName() << endl;
358 style = previousStyle;
361void MathML2KFormulaPrivate::ms( TQDomElement element, TQDomNode docnode )
363 TQString lquote = element.attribute(
"lquote",
"\"" );
364 TQString rquote = element.attribute(
"rquote",
"\"" );
368 text += element.text().stripWhiteSpace();
371 createTextElements( text, docnode );
374void MathML2KFormulaPrivate::mspace( TQDomElement element, TQDomNode docnode )
377 TQString width = element.attribute(
"width" );
379 TQDomElement spaceelement = doc.createElement(
"SPACE" );
382 if ( width ==
"veryverythinmathspace" ) {
383 spaceelement.setAttribute(
"WIDTH",
"thin" );
385 else if ( width ==
"verythinmathspace" ) {
386 spaceelement.setAttribute(
"WIDTH",
"thin" );
388 else if ( width ==
"thinmathspace" ) {
389 spaceelement.setAttribute(
"WIDTH",
"thin" );
391 else if ( width ==
"mediummathspace" ) {
392 spaceelement.setAttribute(
"WIDTH",
"medium" );
394 else if ( width ==
"thickmathspace" ) {
395 spaceelement.setAttribute(
"WIDTH",
"thick" );
397 else if ( width ==
"verythickmathspace" ) {
398 spaceelement.setAttribute(
"WIDTH",
"thick" );
400 else if ( width ==
"veryverythickmathspace" ) {
401 spaceelement.setAttribute(
"WIDTH",
"quad" );
410 if ( width.endsWith(
"em" ) ) {
412 w = context.getDefaultFont().pointSize();
414 TQFontMetrics fm( context.getDefaultFont() );
417 w = w * width.remove( width.length() - 2, 2 ).toDouble( &ok );
420 else if ( width.endsWith(
"px" ) ) {
421 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
424 else if ( width.endsWith(
"in" ) ) {
425 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
428 else if ( width.endsWith(
"cm" ) ) {
429 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
432 else if ( width.endsWith(
"mm" ) ) {
433 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
436 else if ( width.endsWith(
"pt" ) ) {
437 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
440 else if ( width.endsWith(
"pc" ) ) {
441 w = width.remove( width.length() - 2, 2 ).toDouble( &ok );
445 w = width.toDouble( &ok );
452 spaceelement.setAttribute(
"WIDTH",
"thin" );
454 spaceelement.setAttribute(
"WIDTH",
"medium" );
456 spaceelement.setAttribute(
"WIDTH",
"thick" );
458 spaceelement.setAttribute(
"WIDTH",
"quad" );
461 docnode.appendChild( spaceelement );
464void MathML2KFormulaPrivate::mrow( TQDomElement element, TQDomNode docnode )
466 TQDomNode n = element.firstChild();
467 while ( !n.isNull() ) {
468 if ( n.isElement () ) {
469 TQDomElement e = n.toElement();
471 filter->processElement( e, doc, docnode );
474 kdDebug( DEBUGID ) <<
"<mrow> child: " << n.nodeName() << endl;
480void MathML2KFormulaPrivate::mfrac( TQDomElement element, TQDomNode docnode )
482 TQDomNode n = element.firstChild();
483 TQDomElement fraction = doc.createElement(
"FRACTION" );
485 MathStyle previousStyle( style );
486 style.displaystyle ? style.displaystyle = false : style.scriptlevel += 1;
490 while ( !n.isNull() && i < 2 ) {
491 if ( n.isElement() ) {
494 TQDomElement numerator =
495 doc.createElement(
"NUMERATOR" );
496 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
497 numerator.appendChild( sequence );
498 TQDomElement e = n.toElement();
499 filter->processElement( e, doc, sequence );
500 fraction.appendChild( numerator );
504 TQDomElement denominator =
505 doc.createElement(
"DENOMINATOR" );
506 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
507 denominator.appendChild( sequence );
508 TQDomElement e = n.toElement();
509 filter->processElement( e, doc, sequence );
510 fraction.appendChild( denominator );
515 kdDebug( DEBUGID ) <<
"<mfrac> child: " << n.nodeName() << endl;
520 style = previousStyle;
521 docnode.appendChild( fraction );
524void MathML2KFormulaPrivate::mroot( TQDomElement element, TQDomNode docnode )
526 TQDomNode n = element.firstChild();
528 TQDomElement root = doc.createElement(
"ROOT" );
530 while ( !n.isNull() && i < 2 ) {
531 if ( n.isElement() ) {
534 TQDomElement content = doc.createElement(
"CONTENT" );
535 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
536 content.appendChild( sequence );
537 TQDomElement e = n.toElement();
538 filter->processElement( e, doc, sequence );
540 root.appendChild(content);
543 MathStyle previousStyle( style );
544 style.scriptlevel += 2;
545 style.displaystyle =
false;
548 TQDomElement index = doc.createElement(
"INDEX" );
549 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
550 index.appendChild( sequence );
551 TQDomElement e = n.toElement();
552 filter->processElement( e, doc, sequence );
553 root.appendChild( index );
555 style = previousStyle;
559 kdDebug( DEBUGID ) <<
"<mroot> child: " << n.nodeName() << endl;
563 docnode.appendChild( root );
566void MathML2KFormulaPrivate::msqrt( TQDomElement element, TQDomNode docnode )
568 TQDomNode n = element.firstChild();
569 TQDomElement root = doc.createElement(
"ROOT" );
571 TQDomElement content = doc.createElement(
"CONTENT" );
572 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
573 content.appendChild( sequence );
574 root.appendChild( content );
576 while ( !n.isNull() ) {
577 if ( n.isElement() ) {
578 filter->processElement( n.toElement(), doc, sequence );
581 kdDebug( DEBUGID ) <<
"<msqrt> child: " << n.nodeName() << endl;
586 docnode.appendChild( root );
589void MathML2KFormulaPrivate::mstyle( TQDomElement element, TQDomNode docnode )
593 MathStyle previousStyle( style );
594 style.readStyles( element );
596 if ( element.hasAttribute(
"scriptlevel" ) ) {
597 TQString scriptlevel = element.attribute(
"scriptlevel" );
598 if ( scriptlevel.startsWith(
"+" ) || scriptlevel.startsWith(
"-" ) )
599 style.scriptlevel += scriptlevel.toInt( &ok );
601 style.scriptlevel = scriptlevel.toInt( &ok );
603 style.scriptlevel = previousStyle.scriptlevel;
605 if ( element.hasAttribute(
"displaystyle" ) ) {
606 TQString displaystyle = element.attribute(
"displaystyle" );
607 if ( displaystyle ==
"true" )
608 style.displaystyle =
true;
609 else if ( displaystyle ==
"false" )
610 style.displaystyle =
false;
612 if ( element.hasAttribute(
"scriptsizemultiplier" ) ) {
613 style.scriptsizemultiplier =
614 element.attribute(
"scriptsizemultiplier" ).toDouble( &ok );
616 style.scriptsizemultiplier = previousStyle.scriptsizemultiplier;
618 if ( element.hasAttribute(
"scriptminsize" ) ) {
619 TQString scriptminsize = element.attribute(
"scriptminsize" );
620 style.scriptminsize = convertToPoint( scriptminsize, &ok );
622 style.scriptminsize = previousStyle.scriptminsize;
625 if ( element.hasAttribute(
"veryverythinmathspace" ) ) {
626 TQString vvthinmspace = element.attribute(
"veryverythinmathspace" );
627 style.veryverythinmathspace = convertToPoint( vvthinmspace, &ok );
629 style.veryverythinmathspace = previousStyle.veryverythinmathspace;
631 if ( element.hasAttribute(
"verythinmathspace" ) ) {
632 TQString vthinmspace = element.attribute(
"verythinmathspace" );
633 style.verythinmathspace = convertToPoint( vthinmspace, &ok );
635 style.verythinmathspace = previousStyle.verythinmathspace;
637 if ( element.hasAttribute(
"thinmathspace" ) ) {
638 TQString thinmathspace = element.attribute(
"thinmathspace" );
639 style.thinmathspace = convertToPoint( thinmathspace, &ok );
641 style.thinmathspace = previousStyle.thinmathspace;
643 if ( element.hasAttribute(
"mediummathspace" ) ) {
644 TQString mediummathspace = element.attribute(
"mediummathspace" );
645 style.mediummathspace = convertToPoint( mediummathspace, &ok );
647 style.mediummathspace = previousStyle.mediummathspace;
649 if ( element.hasAttribute(
"thickmathspace" ) ) {
650 TQString thickmathspace = element.attribute(
"thickmathspace" );
651 style.thickmathspace = convertToPoint( thickmathspace, &ok );
653 style.thickmathspace = previousStyle.thickmathspace;
655 if ( element.hasAttribute(
"verythickmathspace" ) ) {
656 TQString vthickmspace = element.attribute(
"verythickmathspace" );
657 style.verythickmathspace = convertToPoint( vthickmspace, &ok );
659 style.verythickmathspace = previousStyle.verythickmathspace;
661 if ( element.hasAttribute(
"veryverythickmathspace" ) ) {
662 TQString vvthickmspace = element.attribute(
"veryverythickmathspace" );
663 style.veryverythickmathspace = convertToPoint( vvthickmspace, &ok );
665 style.veryverythickmathspace =
666 previousStyle.veryverythickmathspace;
671 TQDomNode n = element.firstChild();
672 while ( !n.isNull() ) {
673 filter->processElement( n, doc, docnode );
677 style = previousStyle;
680void MathML2KFormulaPrivate::mfenced( TQDomElement element, TQDomNode docnode )
682 TQDomElement bracket = doc.createElement(
"BRACKET" );
683 TQString value = element.attribute(
"open",
"(" );
684 bracket.setAttribute(
"LEFT", TQString::number( value.at( 0 ).latin1() ) );
685 value = element.attribute(
"close",
")" );
686 bracket.setAttribute(
"RIGHT", TQString::number( value.at( 0 ).latin1() ) );
688 TQDomElement content = doc.createElement(
"CONTENT" );
689 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
690 content.appendChild( sequence );
692 TQString separators = element.attribute(
"separators",
"," );
694 TQDomNode n = element.firstChild();
696 while ( !n.isNull() ) {
697 if ( n.isElement() ) {
698 if ( i != 0 && !separators.isEmpty() ) {
699 TQDomElement textelement = doc.createElement(
"TEXT" );
700 if ( i > separators.length() )
701 i = separators.length();
702 textelement.setAttribute(
"CHAR", TQString( separators.at( i - 1 ) ) );
704 sequence.appendChild( textelement );
707 TQDomElement e = n.toElement();
708 filter->processElement( e, doc, sequence );
711 kdDebug( DEBUGID ) <<
"<mfenced> child: " << n.nodeName() << endl;
715 bracket.appendChild( content );
716 docnode.appendChild( bracket );
719void MathML2KFormulaPrivate::mtable( TQDomElement element, TQDomNode docnode )
721 MathStyle previousStyle( style );
722 TQString displaystyle = element.attribute(
"displaystyle",
"false" );
723 if ( displaystyle ==
"true" ) {
724 style.displaystyle =
true;
728 style.displaystyle =
false;
733 int rows = 0;
int cols = 0;
734 TQDomNode n = element.firstChild();
736 while ( !n.isNull() ) {
737 if ( n.isElement() ) {
738 TQDomElement e = n.toElement();
739 subtag = e.tagName();
746 TQDomNode cellnode = e.firstChild();
749 while ( !cellnode.isNull() ) {
750 if ( cellnode.isElement() )
752 cellnode = cellnode.nextSibling();
761 kdDebug( DEBUGID ) <<
"<mtable> child: " << n.nodeName() << endl;
769 n = element.firstChild();
770 TQDomElement matrix = doc.createElement(
"MATRIX" );
771 matrix.setAttribute(
"COLUMNS", cols );
772 matrix.setAttribute(
"ROWS", rows );
774 while ( !n.isNull() ) {
775 if ( n.isElement() ) {
776 TQDomElement e = n.toElement();
777 subtag = e.tagName();
778 if ( subtag ==
"mtr" ) {
779 TQDomNode cellnode = e.firstChild();
781 while ( !cellnode.isNull() ) {
782 if ( cellnode.isElement() ) {
784 TQDomElement cell = doc.createElement(
"SEQUENCE" );
785 TQDomElement cellelement = cellnode.toElement();
786 filter->processElement( cellelement, doc, cell );
787 matrix.appendChild( cell );
789 cellnode = cellnode.nextSibling();
793 for(; cc < cols; cc++ ) {
794 TQDomElement cell = doc.createElement(
"SEQUENCE" );
795 matrix.appendChild( cell );
802 style = previousStyle;
803 docnode.appendChild(matrix);
806void MathML2KFormulaPrivate::msub_msup( TQDomElement element, TQDomNode docnode )
808 TQDomNode n = element.firstChild();
810 TQDomElement root = doc.createElement(
"INDEX" );
812 while ( !n.isNull() && i < 2 ) {
813 if ( n.isElement() ) {
816 TQDomElement content = doc.createElement(
"CONTENT" );
817 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
818 content.appendChild( sequence );
819 TQDomElement e = n.toElement();
820 filter->processElement( e, doc, sequence );
822 root.appendChild( content );
826 if ( element.tagName() ==
"msup" )
827 index = doc.createElement(
"UPPERRIGHT" );
829 index = doc.createElement(
"LOWERRIGHT" );
831 MathStyle previousStyle( style );
832 style.scriptlevel += 1;
833 style.displaystyle =
false;
836 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
837 index.appendChild( sequence );
838 TQDomElement e = n.toElement();
839 filter->processElement( e, doc, sequence );
840 root.appendChild( index );
842 style = previousStyle;
846 kdDebug( DEBUGID ) <<
"<" << element.tagName() <<
"> child: "
847 << n.nodeName() << endl;
851 docnode.appendChild( root );
854void MathML2KFormulaPrivate::munder( TQDomElement element, TQDomNode docnode,
bool oasisFormat )
858 TQString au = element.attribute(
"accentunder" );
861 else if ( au ==
"false" )
868 if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) {
869 if ( mo.attribute(
"accent" ) ==
"true" )
878 TQDomNode n = element.firstChild();
880 TQDomElement root = doc.createElement(
"INDEX" );
882 while ( !n.isNull() && i < 2 ) {
883 if ( n.isElement() ) {
886 TQDomElement content = doc.createElement(
"CONTENT" );
887 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
888 content.appendChild( sequence );
889 TQDomElement e = n.toElement();
890 filter->processElement( e, doc, sequence );
892 root.appendChild( content );
895 MathStyle previousStyle( style );
896 style.displaystyle =
false;
897 if ( !accentunder ) {
898 style.scriptlevel += 1;
902 TQDomElement mo; TQDomElement index;
903 if ( isEmbellishedOperator( n.previousSibling(), &mo, oasisFormat ) &&
904 !previousStyle.displaystyle &&
905 mo.attribute(
"movablelimits" ) ==
"true" )
907 index = doc.createElement(
"LOWERRIGHT" );
910 index = doc.createElement(
"LOWERMIDDLE" );
913 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
914 index.appendChild( sequence );
915 TQDomElement e = n.toElement();
916 filter->processElement( e, doc, sequence );
917 root.appendChild( index );
919 style = previousStyle;
923 kdDebug( DEBUGID ) <<
"<" << element.tagName() <<
"> child: "
924 << n.nodeName() << endl;
929 docnode.appendChild( root );
932void MathML2KFormulaPrivate::mover( TQDomElement element, TQDomNode docnode,
bool oasisFormat )
936 TQString ac = element.attribute(
"accent" );
939 else if ( ac ==
"false" )
946 if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) {
947 if ( mo.attribute(
"accent" ) ==
"true" )
956 TQDomNode n = element.firstChild();
958 TQDomElement root = doc.createElement(
"INDEX" );
960 while ( !n.isNull() && i < 2 ) {
961 if ( n.isElement() ) {
964 TQDomElement content = doc.createElement(
"CONTENT" );
965 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
966 content.appendChild( sequence );
967 TQDomElement e = n.toElement();
968 filter->processElement( e, doc, sequence );
970 root.appendChild( content );
973 MathStyle previousStyle( style );
974 style.displaystyle =
false;
976 style.scriptlevel += 1;
980 TQDomElement mo; TQDomElement index;
981 if ( isEmbellishedOperator( n.previousSibling(), &mo, oasisFormat ) &&
982 !previousStyle.displaystyle &&
983 mo.attribute(
"movablelimits" ) ==
"true" )
985 index = doc.createElement(
"UPPERRIGHT" );
988 index = doc.createElement(
"UPPERMIDDLE" );
991 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
992 index.appendChild( sequence );
993 TQDomElement e = n.toElement();
994 filter->processElement( e, doc, sequence );
995 root.appendChild( index );
997 style = previousStyle;
1001 kdDebug( DEBUGID ) <<
"<" << element.tagName() <<
"> child: "
1002 << n.nodeName() << endl;
1004 n = n.nextSibling();
1007 docnode.appendChild( root );
1010void MathML2KFormulaPrivate::munderover( TQDomElement element, TQDomNode docnode,
bool oasisFormat )
1015 TQString value = element.attribute(
"accentunder" );
1016 if ( value ==
"true" )
1018 else if ( value ==
"false" )
1019 accentunder =
false;
1025 if ( isEmbellishedOperator( element.childNodes().item( 1 ), &mo, oasisFormat ) ) {
1026 if ( mo.attribute(
"accent" ) ==
"true" )
1029 accentunder =
false;
1032 accentunder =
false;
1034 value = element.attribute(
"accent" );
1035 if ( value ==
"true" )
1037 else if ( value ==
"false" )
1044 if ( isEmbellishedOperator( element.childNodes().item( 2 ), &mo,oasisFormat ) ) {
1045 kdDebug( DEBUGID ) <<
"embellished operator" << endl;
1046 if ( mo.attribute(
"accent" ) ==
"true" )
1054 kdDebug( DEBUGID ) <<
"munderover:\n accentunder = " << accentunder
1055 <<
"\n accent = " << accent << endl;
1057 TQDomNode n = element.firstChild();
1059 TQDomElement root = doc.createElement(
"INDEX" );
1061 while ( !n.isNull() && i < 3 ) {
1062 if ( n.isElement() ) {
1065 TQDomElement content = doc.createElement(
"CONTENT" );
1066 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1067 content.appendChild( sequence );
1068 TQDomElement e = n.toElement();
1069 filter->processElement( e, doc, sequence );
1071 root.appendChild( content );
1073 else if ( i == 2 ) {
1074 MathStyle previousStyle( style );
1075 style.displaystyle =
false;
1076 if ( !accentunder ) {
1077 style.scriptlevel += 1;
1078 style.styleChange();
1081 TQDomElement mo; TQDomElement index;
1083 if ( isEmbellishedOperator( element.firstChild(), &mo, oasisFormat ) &&
1084 !previousStyle.displaystyle &&
1085 mo.attribute(
"movablelimits" ) ==
"true" )
1087 index = doc.createElement(
"LOWERRIGHT" );
1090 index = doc.createElement(
"LOWERMIDDLE" );
1093 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1094 index.appendChild( sequence );
1095 TQDomElement e = n.toElement();
1096 filter->processElement( e, doc, sequence );
1097 root.appendChild( index );
1099 style = previousStyle;
1102 MathStyle previousStyle( style );
1103 style.displaystyle =
false;
1105 style.scriptlevel += 1;
1106 style.styleChange();
1109 TQDomElement mo; TQDomElement index;
1110 if ( isEmbellishedOperator( element.firstChild(), &mo, oasisFormat ) &&
1111 !previousStyle.displaystyle &&
1112 mo.attribute(
"movablelimits" ) ==
"true" )
1114 index = doc.createElement(
"UPPERRIGHT" );
1117 index = doc.createElement(
"UPPERMIDDLE" );
1120 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1121 index.appendChild( sequence );
1122 TQDomElement e = n.toElement();
1123 filter->processElement( e, doc, sequence );
1124 root.appendChild( index );
1126 style = previousStyle;
1130 kdDebug( DEBUGID ) <<
"<" << element.tagName() <<
"> child: "
1131 << n.nodeName() << endl;
1133 n = n.nextSibling();
1136 docnode.appendChild( root );
1139void MathML2KFormulaPrivate::msubsup( TQDomElement element, TQDomNode docnode )
1141 TQDomNode n = element.firstChild();
1143 TQDomElement root = doc.createElement(
"INDEX");
1144 MathStyle previousStyle( style );
1146 while ( !n.isNull() && i < 2 ) {
1147 if ( n.isElement() ) {
1150 TQDomElement content = doc.createElement(
"CONTENT" );
1151 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1152 content.appendChild( sequence );
1153 TQDomElement e = n.toElement();
1154 filter->processElement( e, doc, sequence );
1156 root.appendChild( content );
1158 else if ( i == 2 ) {
1159 style.scriptlevel += 1;
1160 style.displaystyle =
false;
1161 style.styleChange();
1164 index = doc.createElement(
"LOWERRIGHT" );
1166 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1167 index.appendChild( sequence );
1168 TQDomElement e = n.toElement();
1169 filter->processElement( e, doc, sequence );
1170 root.appendChild( index );
1174 index = doc.createElement(
"UPPERRIGHT" );
1176 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1177 index.appendChild( sequence );
1178 TQDomElement e = n.toElement();
1179 filter->processElement( e, doc, sequence );
1180 root.appendChild( index );
1182 style = previousStyle;
1187 kdDebug( DEBUGID ) <<
"<msubsup> child: " << n.nodeName() << endl;
1189 n = n.nextSibling();
1191 docnode.appendChild( root );
1194void MathML2KFormulaPrivate::createTextElements( TQString text, TQDomNode docnode )
1196 for ( uint i = 0; i < text.length(); ++i ) {
1197 TQDomElement textelement = doc.createElement(
"TEXT" );
1198 textelement.setAttribute(
"CHAR", TQString( text.at( i ) ) );
1199 style.setStyles( textelement );
1200 if ( context.symbolTable().inTable( text.at( i ) ) ) {
1202 textelement.setAttribute(
"SYMBOL",
"3" );
1204 docnode.appendChild( textelement );
1208void MathML2KFormulaPrivate::createNameSequence( TQString text, TQDomNode docnode )
1210 TQDomElement namesequence = doc.createElement(
"NAMESEQUENCE" );
1211 for ( uint i = 0; i < text.length(); ++i ) {
1212 TQDomElement textelement = doc.createElement(
"TEXT" );
1213 textelement.setAttribute(
"CHAR", TQString( text.at( i ) ) );
1214 style.setStyles( textelement );
1215 if ( context.symbolTable().inTable( text.at( i ) ) ) {
1217 textelement.setAttribute(
"SYMBOL",
"3" );
1219 namesequence.appendChild( textelement );
1221 docnode.appendChild( namesequence );
1224double MathML2KFormulaPrivate::convertToPoint( TQString value,
bool* ok )
1228 if ( value.endsWith(
"em" ) ) {
1230 pt = context.getDefaultFont().pointSize();
1232 TQFontMetrics fm( context.getDefaultFont() );
1233 pt = fm.width(
'M' );
1236 pt = pt * value.remove( value.length() - 2, 2 ).toDouble( ok );
1238 else if ( value.endsWith(
"ex" ) ) {
1239 TQFontMetrics fm( context.getDefaultFont() );
1243 else if ( value.endsWith(
"px" ) ) {
1244 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
1247 else if ( value.endsWith(
"in" ) ) {
1248 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
1251 else if ( value.endsWith(
"cm" ) ) {
1252 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
1255 else if ( value.endsWith(
"mm" ) ) {
1256 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
1259 else if ( value.endsWith(
"pt" ) ) {
1260 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
1262 else if ( value.endsWith(
"pc" ) ) {
1263 pt = value.remove( value.length() - 2, 2 ).toDouble( ok );
1267 pt = value.toDouble( ok );
1273bool MathML2KFormulaPrivate::isEmbellishedOperator( TQDomNode node,
1274 TQDomElement* mo,
bool oasisFormat )
1278 if ( !node.isElement() )
1281 TQDomElement element = node.toElement();
1282 TQString tag = element.tagName();
1289 if ( tag ==
"msub" || tag ==
"msup" || tag ==
"msubsup" ||
1290 tag ==
"munder" || tag ==
"mover" || tag ==
"munderover" ||
1291 tag ==
"mmultiscripts" || tag ==
"mfrac" || tag ==
"semantics" )
1293 return isEmbellishedOperator( element.firstChild(), mo,oasisFormat );
1295 if ( tag ==
"maction" )
1299 if ( tag ==
"mrow" || tag ==
"mstyle" || tag ==
"mphantom" || tag ==
"mpadded" ) {
1300 TQDomNode n = element.firstChild();
1303 while ( !n.isNull() ) {
1304 if ( isEmbellishedOperator( n, mo,oasisFormat ) ) {
1308 else if ( !isSpaceLike( n, oasisFormat ) ) {
1311 n = n.nextSibling();
1318bool MathML2KFormulaPrivate::isSpaceLike( TQDomNode node,
bool oasisFormat )
1322 if ( !node.isElement() )
1325 TQDomElement element = node.toElement();
1326 TQString tag = element.tagName();
1328 if ( tag ==
"mtext" || tag ==
"mspace" ||
1329 tag ==
"maligngroup" || tag ==
"malignmark" ) {
1332 if ( tag ==
"mstyle" || tag ==
"mphantom" || tag ==
"mpadded" || tag ==
"mrow" ) {
1333 TQDomNode n = element.firstChild();
1334 while ( !n.isNull() ) {
1335 if ( isSpaceLike( n,oasisFormat ) )
1336 n = n.nextSibling();
1342 if ( tag ==
"maction" ) {
1351 : m_error( false ), oasisFormat( _oasisFormat ), context( contextStyle )
1353 orig_element = mmldoc.documentElement();
1358 : m_error( false ), orig_element( mmlelm ), oasisFormat( _oasisFormat ), context( contextStyle )
1363TQDomDocument MathML2KFormula::getKFormulaDom()
1370void MathML2KFormula::startConversion()
1375 formuladoc = TQDomDocument(
"KFORMULA" );
1376 impl =
new MathML2KFormulaPrivate(
this, context, formuladoc );
1377 if ( orig_element.tagName() ==
"math" ) {
1378 impl->math( orig_element );
1382 kdError() <<
"Not a MathML document!" << endl;
1383 KMessageBox::error( 0, i18n(
"The document does not seem to be MathML." ), i18n(
"MathML Import Error" ) );
1389bool MathML2KFormula::processElement( TQDomNode node, TQDomDocument& doc, TQDomNode docnode )
1393 Type type = UNKNOWN;
1395 if ( node.isElement() ) {
1396 TQDomElement element = node.toElement();
1397 TQString tag = element.tagName();
1399 if ( tag ==
"mi" ) {
1401 impl->mi( element, docnode );
1403 else if ( tag ==
"mo" ) {
1405 impl->mo( element, docnode );
1407 else if ( tag ==
"mn" ) {
1409 impl->mn( element, docnode );
1411 else if ( tag ==
"mtext" ) {
1413 impl->mtext( element, docnode );
1415 else if ( tag ==
"ms" ) {
1417 impl->ms( element, docnode );
1419 else if ( tag ==
"mspace" ) {
1421 impl->mspace( element, docnode );
1423 else if ( tag ==
"mrow" ) {
1425 impl->mrow( element, docnode );
1427 else if ( tag ==
"mfrac" ) {
1429 impl->mfrac( element, docnode );
1431 else if ( tag ==
"mroot" ) {
1433 impl->mroot( element, docnode );
1435 else if ( tag ==
"msqrt" ) {
1437 impl->msqrt( element, docnode );
1439 else if ( tag ==
"mstyle" ) {
1441 impl->mstyle( element, docnode );
1443 else if ( tag ==
"mfenced" ) {
1445 impl->mfenced( element, docnode );
1447 else if ( tag ==
"mtable" ) {
1449 impl->mtable( element, docnode );
1451 else if ( tag ==
"msub" || tag ==
"msup" ) {
1453 impl->msub_msup( element, docnode );
1455 else if ( tag ==
"munder" ) {
1457 impl->munder( element, docnode,oasisFormat );
1459 else if ( tag ==
"mover" ) {
1461 impl->mover( element, docnode,oasisFormat );
1463 else if ( tag ==
"munderover" ) {
1465 impl->munderover( element, docnode, oasisFormat );
1467 else if ( tag ==
"msubsup" ) {
1469 impl->msubsup( element, docnode );
1473 else if ( tag ==
"apply" ) {
1475 TQDomNode n = element.firstChild();
1476 TQDomElement op = n.toElement();
1477 uint count = element.childNodes().count();
1479 TQDomElement brackets = doc.createElement(
"BRACKET");
1480 brackets.setAttribute(
"RIGHT",
"41");
1481 brackets.setAttribute(
"LEFT",
"40");
1482 TQDomElement content = doc.createElement(
"CONTENT");
1483 brackets.appendChild(content);
1484 TQDomElement base = doc.createElement(
"SEQUENCE");
1485 content.appendChild(base);
1486 docnode.appendChild(brackets);
1516 if ( op.tagName() ==
"plus" || op.tagName() ==
"times" ||
1517 op.tagName() ==
"and" || op.tagName() ==
"or" ||
1518 op.tagName() ==
"xor" ) {
1520 n = n.nextSibling();
1523 while ( !n.isNull() ) {
1524 if ( n.isElement() ) {
1526 TQDomElement text = doc.createElement(
"TEXT" );
1529 if ( op.tagName() ==
"plus" )
1531 else if ( op.tagName() ==
"times" )
1533 else if ( op.tagName() ==
"and" )
1535 else if ( op.tagName() ==
"or" )
1537 else if ( op.tagName() ==
"xor" )
1540 text.setAttribute(
"CHAR", value );
1541 base.appendChild( text );
1544 TQDomElement e = n.toElement();
1545 processElement( e, doc, base );
1547 n = n.nextSibling();
1551 else if ( op.tagName() ==
"factorial" ) {
1552 TQDomElement e = n.nextSibling().toElement();
1553 processElement( e, doc, docnode );
1554 impl->createTextElements(
"!", base );
1556 else if ( op.tagName() ==
"minus" ) {
1557 n = n.nextSibling();
1559 impl->createTextElements(
"-", base );
1560 TQDomElement e = n.toElement();
1561 processElement( e, doc, base );
1563 else if ( count == 3 ) {
1564 TQDomElement e = n.toElement();
1565 processElement( e, doc, base );
1566 impl->createTextElements(
"-", base );
1567 n = n.nextSibling();
1569 processElement( e, doc, base );
1573 else if ( op.tagName() ==
"divide" && count == 3 ) {
1574 n = n.nextSibling();
1575 TQDomElement e = n.toElement();
1576 processElement( e, doc, base );
1577 impl->createTextElements(
"/", base);
1578 n = n.nextSibling();
1580 processElement( e, doc, base );
1582 else if ( op.tagName() ==
"power" && count == 3 ) {
1584 n = n.nextSibling();
1585 TQDomElement e = n.toElement();
1586 TQDomElement index = doc.createElement(
"INDEX");
1587 base.appendChild(index);
1588 TQDomElement content = doc.createElement(
"CONTENT");
1589 index.appendChild(content);
1590 TQDomElement sequence = doc.createElement(
"SEQUENCE");
1591 content.appendChild(sequence);
1592 processElement(e, doc, sequence);
1593 TQDomElement upper = doc.createElement(
"UPPERRIGHT");
1594 index.appendChild(upper);
1595 sequence = doc.createElement(
"SEQUENCE");
1596 upper.appendChild(sequence);
1597 n = n.nextSibling();
1599 processElement(e, doc, sequence);
1601 else if ( op.tagName() ==
"abs" && count == 2) {
1602 n = n.nextSibling();
1603 TQDomElement e = n.toElement();
1604 TQDomElement bracket = doc.createElement(
"BRACKET");
1605 bracket.setAttribute(
"RIGHT",
"257");
1606 bracket.setAttribute(
"LEFT",
"256");
1607 base.appendChild(bracket);
1608 TQDomElement content = doc.createElement(
"CONTENT");
1609 bracket.appendChild(content);
1610 TQDomElement sequence = doc.createElement(
"SEQUENCE");
1611 content.appendChild(sequence);
1612 processElement(e, doc, sequence);
1614 else if ( op.tagName() ==
"not" && count == 2) {
1615 n = n.nextSibling();
1616 TQDomElement e = n.toElement();
1617 impl->createTextElements(TQString(TQChar(0xAC)), base);
1618 processElement(e, doc, base);
1620 else if ( op.tagName() ==
"implies" && count == 3 ) {
1621 n = n.nextSibling();
1622 TQDomElement e = n.toElement();
1623 processElement( e, doc, base );
1624 impl->createTextElements(TQString(TQChar(0x21D2)), base);
1625 n = n.nextSibling();
1627 processElement( e, doc, base );
1633 else if ( tag ==
"cn" ) {
1635 TQString type = element.attribute(
"type",
"real" );
1637 if ( type ==
"real" || type ==
"constant" ) {
1638 impl->createTextElements( element.text().stripWhiteSpace(),
1641 else if ( type ==
"integer" ) {
1642 TQString base = element.attribute(
"base" );
1644 impl->createTextElements( element.text().stripWhiteSpace(),
1648 TQDomElement index = doc.createElement(
"INDEX" );
1649 TQDomElement content = doc.createElement(
"CONTENT" );
1650 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1651 impl->createTextElements( element.text().stripWhiteSpace(),
1653 content.appendChild( sequence );
1654 index.appendChild( content );
1656 TQDomElement lowerright = doc.createElement(
"LOWERRIGHT" );
1657 sequence = doc.createElement(
"SEQUENCE" );
1659 impl->createTextElements( base, sequence );
1661 lowerright.appendChild( sequence );
1662 index.appendChild( lowerright );
1664 docnode.appendChild( index );
1667 else if ( type ==
"rational" ) {
1668 TQDomNode n = element.firstChild();
1669 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1672 n = n.nextSibling();
1673 impl->createTextElements(
"/", docnode );
1675 n = n.nextSibling();
1676 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1679 else if ( type ==
"complex-cartesian" ) {
1680 TQDomNode n = element.firstChild();
1681 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1684 n = n.nextSibling();
1685 impl->createTextElements(
"+", docnode );
1687 n = n.nextSibling();
1688 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1691 impl->createTextElements(
"i", docnode );
1694 else if ( type ==
"complex-polar" ) {
1695 TQDomNode n = element.firstChild();
1696 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1699 n = n.nextSibling();
1700 TQDomElement index = doc.createElement(
"INDEX" );
1701 TQDomElement content = doc.createElement(
"CONTENT" );
1702 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1703 TQDomElement textelement = doc.createElement(
"TEXT" );
1704 textelement.setAttribute(
"CHAR",
"e" );
1705 sequence.appendChild( textelement );
1706 content.appendChild( sequence );
1707 index.appendChild( content );
1709 TQDomElement upperright = doc.createElement(
"UPPERRIGHT" );
1710 sequence = doc.createElement(
"SEQUENCE" );
1711 textelement = doc.createElement(
"TEXT" );
1712 textelement.setAttribute(
"CHAR",
"i" );
1713 sequence.appendChild( textelement );
1715 n = n.nextSibling();
1716 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1719 upperright.appendChild( sequence );
1720 index.appendChild( upperright );
1722 docnode.appendChild( index );
1726 else if ( tag ==
"ci" ) {
1728 TQDomNode n = element.firstChild();
1731 impl->createTextElements( n.toText().data().stripWhiteSpace(),
1734 else if ( n.isElement() ) {
1735 TQDomElement e = n.toElement();
1736 processElement( e, doc, docnode );
1738 else if ( n.isEntityReference() ) {
1739 kdDebug( DEBUGID ) <<
"isEntityReference: "
1740 << n.toEntityReference().nodeName().latin1()
1744 kdDebug( DEBUGID ) <<
"ci: " << n.nodeName().latin1() << endl;
1747 else if ( tag ==
"list" ) {
1749 TQDomNode n = element.firstChild();
1751 TQDomElement bracket = doc.createElement(
"BRACKET" );
1752 bracket.setAttribute(
"LEFT", 91 );
1753 bracket.setAttribute(
"RIGHT", 93 );
1754 TQDomElement content = doc.createElement(
"CONTENT" );
1755 TQDomElement sequence = doc.createElement(
"SEQUENCE" );
1759 while ( !n.isNull() ) {
1760 if ( n.isElement() ) {
1762 TQDomElement textelement = doc.createElement(
"TEXT" );
1763 textelement.setAttribute(
"CHAR",
"," );
1764 sequence.appendChild( textelement );
1767 TQDomElement e = n.toElement();
1768 processElement( e, doc, sequence );
1770 n = n.nextSibling();
1773 content.appendChild( sequence );
1774 bracket.appendChild( content );
1775 docnode.appendChild( bracket );
1779 if ( type == UNKNOWN && node.nodeType() != TQDomNode::AttributeNode ) {
1780 kdDebug() <<
"Not an element: " << node.nodeName() << endl;
1781 TQDomNode n = node.firstChild();
1782 while ( !n.isNull() ) {
1783 processElement( n, doc, docnode );
1784 n = n.nextSibling();
1791KFORMULA_NAMESPACE_END
1793using namespace KFormula;
1794#include "kformulamathmlread.moc"
Contains all the style information for the formela.
static void error(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, int options=Notify)