00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qfont.h>
00022 #include <qfontmetrics.h>
00023 #include <qpainter.h>
00024
00025 #include <kdebug.h>
00026
00027 #include "basicelement.h"
00028 #include "contextstyle.h"
00029 #include "elementtype.h"
00030 #include "sequenceelement.h"
00031 #include "sequenceparser.h"
00032 #include "textelement.h"
00033
00034
00035 KFORMULA_NAMESPACE_BEGIN
00036
00037 int ElementType::evilDestructionCount = 0;
00038
00039
00040
00041
00042
00043 QString format2variant( CharStyle style, CharFamily family )
00044 {
00045 QString result;
00046
00047 switch( family ) {
00048 case normalFamily:
00049 case anyFamily:
00050 switch( style ) {
00051 case normalChar:
00052 result = "normal"; break;
00053 case boldChar:
00054 result = "bold"; break;
00055 case italicChar:
00056 result = "italic"; break;
00057 case boldItalicChar:
00058 result = "bold-italic"; break;
00059 case anyChar:
00060 break;
00061 }
00062 break;
00063 case scriptFamily:
00064 result = "script";
00065 if ( style == boldChar || style == boldItalicChar )
00066 result = "bold-" + result;
00067 break;
00068 case frakturFamily:
00069 result = "fraktur";
00070 if ( style == boldChar || style == boldItalicChar )
00071 result = "bold-" + result;
00072 break;
00073 case doubleStruckFamily:
00074 result = "double-struck"; break;
00075 }
00076
00077 return result;
00078 }
00079
00080 ElementType::ElementType( SequenceParser* parser )
00081 : from( parser->getStart() ), to( parser->getEnd() ), prev( 0 )
00082 {
00083 evilDestructionCount++;
00084 }
00085
00086 ElementType::~ElementType()
00087 {
00088 delete prev;
00089 evilDestructionCount--;
00090 }
00091
00092
00093 QString ElementType::text( SequenceElement* seq ) const
00094 {
00095 QString str;
00096 for ( uint i=start(); i<end(); ++i ) {
00097 str.append( seq->getChild( i )->getCharacter() );
00098 }
00099 return str;
00100 }
00101
00102
00103 luPt ElementType::getSpaceBefore( const ContextStyle&,
00104 ContextStyle::TextStyle )
00105 {
00106 return 0;
00107 }
00108
00109 luPt ElementType::getSpaceAfter( MultiElementType*,
00110 const ContextStyle&,
00111 ContextStyle::TextStyle )
00112 {
00113 return 0;
00114 }
00115
00116 luPt ElementType::getSpaceAfter( OperatorType*,
00117 const ContextStyle&,
00118 ContextStyle::TextStyle )
00119 {
00120 return 0;
00121 }
00122
00123 luPt ElementType::getSpaceAfter( RelationType*,
00124 const ContextStyle&,
00125 ContextStyle::TextStyle )
00126 {
00127 return 0;
00128 }
00129
00130 luPt ElementType::getSpaceAfter( PunctuationType*,
00131 const ContextStyle&,
00132 ContextStyle::TextStyle )
00133 {
00134 return 0;
00135 }
00136
00137 luPt ElementType::getSpaceAfter( BracketType*,
00138 const ContextStyle&,
00139 ContextStyle::TextStyle )
00140 {
00141 return 0;
00142 }
00143
00144 luPt ElementType::getSpaceAfter( ComplexElementType*,
00145 const ContextStyle&,
00146 ContextStyle::TextStyle )
00147 {
00148 return 0;
00149 }
00150
00151 luPt ElementType::getSpaceAfter( InnerElementType*,
00152 const ContextStyle&,
00153 ContextStyle::TextStyle )
00154 {
00155 return 0;
00156 }
00157
00158 luPt ElementType::thinSpaceIfNotScript( const ContextStyle& context,
00159 ContextStyle::TextStyle tstyle )
00160 {
00161 if ( !context.isScript( tstyle ) ) {
00162 return context.getThinSpace( tstyle );
00163 }
00164 return 0;
00165 }
00166
00167 luPt ElementType::mediumSpaceIfNotScript( const ContextStyle& context,
00168 ContextStyle::TextStyle tstyle )
00169 {
00170 if ( !context.isScript( tstyle ) ) {
00171 return context.getMediumSpace( tstyle );
00172 }
00173 return 0;
00174 }
00175
00176 luPt ElementType::thickSpaceIfNotScript( const ContextStyle& context,
00177 ContextStyle::TextStyle tstyle )
00178 {
00179 if ( !context.isScript( tstyle ) ) {
00180 return context.getThickSpace( tstyle );
00181 }
00182 return 0;
00183 }
00184
00185
00186 QFont ElementType::getFont(const ContextStyle& context)
00187 {
00188 return context.getDefaultFont();
00189 }
00190
00191 void ElementType::setUpPainter(const ContextStyle& context, QPainter& painter)
00192 {
00193 painter.setPen(context.getDefaultColor());
00194 }
00195
00196 void ElementType::append( ElementType* element )
00197 {
00198 element->prev = this;
00199 }
00200
00201 void ElementType::output()
00202 {
00203 kdDebug( DEBUGID ) << start() << " - " << end() << endl;
00204 }
00205
00206 void ElementType::saveMathML( SequenceElement* se, QDomDocument& doc, QDomElement de, bool oasisFormat )
00207 {
00208 for ( uint i = from; i < to; ++i ) {
00209 se->getChild( i )->writeMathML( doc, de, oasisFormat );
00210 }
00211 }
00212
00213
00214 SequenceType::SequenceType( SequenceParser* parser )
00215 : ElementType( parser ), last( 0 )
00216 {
00217 while ( true ) {
00218 parser->nextToken();
00219
00220
00221 if ( parser->getTokenType() == END ) {
00222 break;
00223 }
00224 ElementType* nextType = parser->getPrimitive();
00225 if ( nextType == 0 ) {
00226 break;
00227 }
00228 if ( last != 0 ) {
00229 last->append( nextType );
00230 }
00231 last = nextType;
00232 }
00233 }
00234
00235 SequenceType::~SequenceType()
00236 {
00237 delete last;
00238 }
00239
00240
00241 void SequenceType::output()
00242 {
00243 }
00244
00245
00246 MultiElementType::MultiElementType( SequenceParser* parser )
00247 : ElementType( parser )
00248 {
00249 for ( uint i = start(); i < end(); i++ ) {
00250 parser->setElementType( i, this );
00251 }
00252 m_text = parser->text();
00253 }
00254
00255
00256 luPt MultiElementType::getSpaceBefore( const ContextStyle& context,
00257 ContextStyle::TextStyle tstyle )
00258 {
00259 if ( getPrev() != 0 ) {
00260 return getPrev()->getSpaceAfter( this, context, tstyle );
00261 }
00262 return 0;
00263 }
00264
00265 luPt MultiElementType::getSpaceAfter( OperatorType*,
00266 const ContextStyle& context,
00267 ContextStyle::TextStyle tstyle )
00268 {
00269 return mediumSpaceIfNotScript( context, tstyle );
00270 }
00271
00272 luPt MultiElementType::getSpaceAfter( RelationType*,
00273 const ContextStyle& context,
00274 ContextStyle::TextStyle tstyle )
00275 {
00276 return thickSpaceIfNotScript( context, tstyle );
00277 }
00278
00279 luPt MultiElementType::getSpaceAfter( InnerElementType*,
00280 const ContextStyle& context,
00281 ContextStyle::TextStyle tstyle )
00282 {
00283 return thinSpaceIfNotScript( context, tstyle );
00284 }
00285
00286
00287 TextType::TextType( SequenceParser* parser )
00288 : MultiElementType( parser )
00289 {
00290 }
00291
00292 void TextType::saveMathML( SequenceElement* se, QDomDocument& doc, QDomElement de, bool oasisFormat )
00293 {
00294 for ( uint i = start(); i < end(); ++i ) {
00295 QDomElement text = doc.createElement( oasisFormat ? "math:mi" : "mi" );
00296 BasicElement* be = se->getChild( i );
00297 TextElement* te = static_cast<TextElement*>( be );
00298 QString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily());
00299 if ( !mathvariant.isNull() )
00300 text.setAttribute( "mathvariant", mathvariant );
00301
00302 text.appendChild( doc.createTextNode( be->getCharacter() ) );
00303
00304 de.appendChild( text );
00305 if ( i != end() - 1 ) {
00306 QDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
00307 op.appendChild( doc.createEntityReference( "InvisibleTimes" ) );
00308 de.appendChild( op );
00309 }
00310 }
00311 }
00312
00313
00314 NameType::NameType( SequenceParser* parser )
00315 : MultiElementType( parser )
00316 {
00317 }
00318
00319 void NameType::saveMathML( SequenceElement* se, QDomDocument& doc, QDomElement de, bool oasisFormat )
00320 {
00321 se->getChild( start() )->writeMathML( doc, de, oasisFormat );
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 }
00334
00335
00336 QFont NameType::getFont(const ContextStyle& context)
00337 {
00338 return context.getNameFont();
00339 }
00340
00341 NumberType::NumberType( SequenceParser* parser )
00342 : MultiElementType( parser )
00343 {
00344 }
00345
00346 QFont NumberType::getFont(const ContextStyle& context)
00347 {
00348 return context.getNumberFont();
00349 }
00350
00351 void NumberType::setUpPainter(const ContextStyle& context, QPainter& painter)
00352 {
00353 painter.setPen(context.getNumberColor());
00354 }
00355
00356 void NumberType::saveMathML( SequenceElement* se, QDomDocument& doc, QDomElement de, bool oasisFormat )
00357 {
00358 QDomElement name = doc.createElement( oasisFormat ? "math:mn" : "mn" );
00359 QString value;
00360 for ( uint i = start(); i < end(); ++i ) {
00361 BasicElement* be = se->getChild( i );
00362 value += be->getCharacter();
00363 }
00364 TextElement* te = static_cast<TextElement*>( se->getChild( start() ) );
00365 QString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
00366 if ( !mathvariant.isNull() )
00367 name.setAttribute( "mathvariant", mathvariant );
00368
00369 name.appendChild( doc.createTextNode( value ) );
00370 de.appendChild( name );
00371 }
00372
00373
00374 SingleElementType::SingleElementType( SequenceParser* parser )
00375 : ElementType( parser )
00376 {
00377 parser->setElementType( start(), this );
00378 }
00379
00380 AbstractOperatorType::AbstractOperatorType( SequenceParser* parser )
00381 : SingleElementType( parser )
00382 {
00383 }
00384
00385 void AbstractOperatorType::saveMathML( SequenceElement* se, QDomDocument& doc, QDomElement de, bool oasisFormat )
00386 {
00387 QDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
00388 BasicElement* be = se->getChild( start() );
00389 if ( be->getCharacter().latin1() != 0 ) {
00390
00391 op.appendChild( doc.createTextNode( be->getCharacter() ) );
00392 }
00393 else {
00394
00395 QString s;
00396 op.appendChild( doc.createEntityReference( s.sprintf( "#x%05X", be->getCharacter().unicode() ) ) );
00397 }
00398 TextElement* te = static_cast<TextElement*>( be );
00399 QString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
00400 if ( !mathvariant.isNull() )
00401 op.setAttribute( "mathvariant", mathvariant );
00402
00403 de.appendChild( op );
00404 }
00405
00406 OperatorType::OperatorType( SequenceParser* parser )
00407 : AbstractOperatorType( parser )
00408 {
00409 }
00410
00411 luPt OperatorType::getSpaceBefore( const ContextStyle& context,
00412 ContextStyle::TextStyle tstyle )
00413 {
00414 if ( getPrev() != 0 ) {
00415 return getPrev()->getSpaceAfter( this, context, tstyle );
00416 }
00417 return 0;
00418 }
00419
00420 luPt OperatorType::getSpaceAfter( MultiElementType*,
00421 const ContextStyle& context,
00422 ContextStyle::TextStyle tstyle )
00423 {
00424 return mediumSpaceIfNotScript( context, tstyle );
00425 }
00426
00427 luPt OperatorType::getSpaceAfter( BracketType*,
00428 const ContextStyle& context,
00429 ContextStyle::TextStyle tstyle )
00430 {
00431 return mediumSpaceIfNotScript( context, tstyle );
00432 }
00433
00434 luPt OperatorType::getSpaceAfter( ComplexElementType*,
00435 const ContextStyle& context,
00436 ContextStyle::TextStyle tstyle )
00437 {
00438 return mediumSpaceIfNotScript( context, tstyle );
00439 }
00440
00441 luPt OperatorType::getSpaceAfter( InnerElementType*,
00442 const ContextStyle& context,
00443 ContextStyle::TextStyle tstyle )
00444 {
00445 return mediumSpaceIfNotScript( context, tstyle );
00446 }
00447
00448
00449 QFont OperatorType::getFont(const ContextStyle& context)
00450 {
00451 return context.getOperatorFont();
00452 }
00453
00454 void OperatorType::setUpPainter(const ContextStyle& context, QPainter& painter)
00455 {
00456 painter.setPen(context.getOperatorColor());
00457 }
00458
00459
00460 RelationType::RelationType( SequenceParser* parser )
00461 : AbstractOperatorType( parser )
00462 {
00463 }
00464
00465 luPt RelationType::getSpaceBefore( const ContextStyle& context,
00466 ContextStyle::TextStyle tstyle )
00467 {
00468 if ( getPrev() != 0 ) {
00469 return getPrev()->getSpaceAfter( this, context, tstyle );
00470 }
00471 return 0;
00472 }
00473
00474 luPt RelationType::getSpaceAfter( MultiElementType*,
00475 const ContextStyle& context,
00476 ContextStyle::TextStyle tstyle )
00477 {
00478 return thickSpaceIfNotScript( context, tstyle );
00479 }
00480
00481 luPt RelationType::getSpaceAfter( BracketType*,
00482 const ContextStyle& context,
00483 ContextStyle::TextStyle tstyle )
00484 {
00485 return thickSpaceIfNotScript( context, tstyle );
00486 }
00487
00488 luPt RelationType::getSpaceAfter( ComplexElementType*,
00489 const ContextStyle& context,
00490 ContextStyle::TextStyle tstyle )
00491 {
00492 return thickSpaceIfNotScript( context, tstyle );
00493 }
00494
00495 luPt RelationType::getSpaceAfter( InnerElementType*,
00496 const ContextStyle& context,
00497 ContextStyle::TextStyle tstyle )
00498 {
00499 return thickSpaceIfNotScript( context, tstyle );
00500 }
00501
00502 QFont RelationType::getFont( const ContextStyle& context )
00503 {
00504 return context.getOperatorFont();
00505 }
00506
00507 void RelationType::setUpPainter( const ContextStyle& context, QPainter& painter )
00508 {
00509 painter.setPen(context.getOperatorColor());
00510 }
00511
00512
00513
00514 PunctuationType::PunctuationType( SequenceParser* parser )
00515 : AbstractOperatorType( parser )
00516 {
00517 }
00518
00519 luPt PunctuationType::getSpaceBefore( const ContextStyle& context,
00520 ContextStyle::TextStyle tstyle )
00521 {
00522 if ( getPrev() != 0 ) {
00523 return getPrev()->getSpaceAfter( this, context, tstyle );
00524 }
00525 return 0;
00526 }
00527
00528 luPt PunctuationType::getSpaceAfter( MultiElementType*,
00529 const ContextStyle& context,
00530 ContextStyle::TextStyle tstyle )
00531 {
00532 return thinSpaceIfNotScript( context, tstyle );
00533 }
00534
00535 luPt PunctuationType::getSpaceAfter( RelationType*,
00536 const ContextStyle& context,
00537 ContextStyle::TextStyle tstyle )
00538 {
00539 return thickSpaceIfNotScript( context, tstyle );
00540 }
00541
00542 luPt PunctuationType::getSpaceAfter( PunctuationType*,
00543 const ContextStyle& context,
00544 ContextStyle::TextStyle tstyle )
00545 {
00546 return thinSpaceIfNotScript( context, tstyle );
00547 }
00548
00549 luPt PunctuationType::getSpaceAfter( BracketType*,
00550 const ContextStyle& context,
00551 ContextStyle::TextStyle tstyle )
00552 {
00553 return thinSpaceIfNotScript( context, tstyle );
00554 }
00555
00556 luPt PunctuationType::getSpaceAfter( ComplexElementType*,
00557 const ContextStyle& context,
00558 ContextStyle::TextStyle tstyle )
00559 {
00560 return thinSpaceIfNotScript( context, tstyle );
00561 }
00562
00563 luPt PunctuationType::getSpaceAfter( InnerElementType*,
00564 const ContextStyle& context,
00565 ContextStyle::TextStyle tstyle )
00566 {
00567 return thinSpaceIfNotScript( context, tstyle );
00568 }
00569
00570 QFont PunctuationType::getFont( const ContextStyle& context )
00571 {
00572 return context.getOperatorFont();
00573 }
00574
00575 void PunctuationType::setUpPainter( const ContextStyle& context, QPainter& painter )
00576 {
00577 painter.setPen( context.getDefaultColor() );
00578 }
00579
00580
00581 BracketType::BracketType( SequenceParser* parser )
00582 : SingleElementType( parser )
00583 {
00584 }
00585
00586 luPt BracketType::getSpaceBefore( const ContextStyle& context,
00587 ContextStyle::TextStyle tstyle )
00588 {
00589 if ( getPrev() != 0 ) {
00590 return getPrev()->getSpaceAfter( this, context, tstyle );
00591 }
00592 return 0;
00593 }
00594
00595 luPt BracketType::getSpaceAfter( OperatorType*,
00596 const ContextStyle& context,
00597 ContextStyle::TextStyle tstyle )
00598 {
00599 return mediumSpaceIfNotScript( context, tstyle );
00600 }
00601
00602 luPt BracketType::getSpaceAfter( RelationType*,
00603 const ContextStyle& context,
00604 ContextStyle::TextStyle tstyle )
00605 {
00606 return thickSpaceIfNotScript( context, tstyle );
00607 }
00608
00609 luPt BracketType::getSpaceAfter( InnerElementType*,
00610 const ContextStyle& context,
00611 ContextStyle::TextStyle tstyle )
00612 {
00613 return thinSpaceIfNotScript( context, tstyle );
00614 }
00615
00616
00617 ComplexElementType::ComplexElementType( SequenceParser* parser )
00618 : SingleElementType( parser )
00619 {
00620 }
00621
00622 luPt ComplexElementType::getSpaceBefore( const ContextStyle& context,
00623 ContextStyle::TextStyle tstyle )
00624 {
00625 if ( getPrev() != 0 ) {
00626 return getPrev()->getSpaceAfter( this, context, tstyle );
00627 }
00628 return 0;
00629 }
00630
00631 luPt ComplexElementType::getSpaceAfter( OperatorType*,
00632 const ContextStyle& context,
00633 ContextStyle::TextStyle tstyle )
00634 {
00635 return mediumSpaceIfNotScript( context, tstyle );
00636 }
00637
00638 luPt ComplexElementType::getSpaceAfter( RelationType*,
00639 const ContextStyle& context,
00640 ContextStyle::TextStyle tstyle )
00641 {
00642 return thickSpaceIfNotScript( context, tstyle );
00643 }
00644
00645 luPt ComplexElementType::getSpaceAfter( InnerElementType*,
00646 const ContextStyle& context,
00647 ContextStyle::TextStyle tstyle )
00648 {
00649 return thinSpaceIfNotScript( context, tstyle );
00650 }
00651
00652
00653 InnerElementType::InnerElementType( SequenceParser* parser )
00654 : SingleElementType( parser )
00655 {
00656 }
00657
00658 luPt InnerElementType::getSpaceBefore( const ContextStyle& context,
00659 ContextStyle::TextStyle tstyle )
00660 {
00661 if ( getPrev() != 0 ) {
00662 return getPrev()->getSpaceAfter( this, context, tstyle );
00663 }
00664 return 0;
00665 }
00666
00667 luPt InnerElementType::getSpaceAfter( MultiElementType*,
00668 const ContextStyle& context,
00669 ContextStyle::TextStyle tstyle )
00670 {
00671 return thinSpaceIfNotScript( context, tstyle );
00672 }
00673
00674 luPt InnerElementType::getSpaceAfter( OperatorType*,
00675 const ContextStyle& context,
00676 ContextStyle::TextStyle tstyle )
00677 {
00678 return mediumSpaceIfNotScript( context, tstyle );
00679 }
00680
00681 luPt InnerElementType::getSpaceAfter( RelationType*,
00682 const ContextStyle& context,
00683 ContextStyle::TextStyle tstyle )
00684 {
00685 return thickSpaceIfNotScript( context, tstyle );
00686 }
00687
00688 luPt InnerElementType::getSpaceAfter( PunctuationType*,
00689 const ContextStyle& context,
00690 ContextStyle::TextStyle tstyle )
00691 {
00692 return thinSpaceIfNotScript( context, tstyle );
00693 }
00694
00695 luPt InnerElementType::getSpaceAfter( BracketType*,
00696 const ContextStyle& context,
00697 ContextStyle::TextStyle tstyle )
00698 {
00699 return thinSpaceIfNotScript( context, tstyle );
00700 }
00701
00702 luPt InnerElementType::getSpaceAfter( ComplexElementType*,
00703 const ContextStyle& context,
00704 ContextStyle::TextStyle tstyle )
00705 {
00706 return thinSpaceIfNotScript( context, tstyle );
00707 }
00708
00709 luPt InnerElementType::getSpaceAfter( InnerElementType*,
00710 const ContextStyle& context,
00711 ContextStyle::TextStyle tstyle )
00712 {
00713 return thinSpaceIfNotScript( context, tstyle );
00714 }
00715
00716
00717 KFORMULA_NAMESPACE_END