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 )
00207 {
00208 for ( uint i = from; i < to; ++i ) {
00209 se->getChild( i )->writeMathML( doc, de );
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 )
00293 {
00294 for ( uint i = start(); i < end(); ++i ) {
00295 QDomElement text = doc.createElement( "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 if ( be->getCharacter().latin1() != 0 ) {
00302
00303 text.appendChild( doc.createTextNode( be->getCharacter() ) );
00304 }
00305 else {
00306
00307 QString s;
00308 text.appendChild( doc.createEntityReference( s.sprintf( "#x%05X", be->getCharacter().unicode() ) ) );
00309 }
00310
00311 de.appendChild( text );
00312 if ( i != end() - 1 ) {
00313 QDomElement op = doc.createElement( "mo" );
00314 op.appendChild( doc.createEntityReference( "InvisibleTimes" ) );
00315 de.appendChild( op );
00316 }
00317 }
00318 }
00319
00320
00321 NameType::NameType( SequenceParser* parser )
00322 : MultiElementType( parser )
00323 {
00324 }
00325
00326 void NameType::saveMathML( SequenceElement* se, QDomDocument doc, QDomElement de )
00327 {
00328 se->getChild( start() )->writeMathML( doc, de );
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 }
00341
00342
00343 QFont NameType::getFont(const ContextStyle& context)
00344 {
00345 return context.getNameFont();
00346 }
00347
00348 NumberType::NumberType( SequenceParser* parser )
00349 : MultiElementType( parser )
00350 {
00351 }
00352
00353 QFont NumberType::getFont(const ContextStyle& context)
00354 {
00355 return context.getNumberFont();
00356 }
00357
00358 void NumberType::setUpPainter(const ContextStyle& context, QPainter& painter)
00359 {
00360 painter.setPen(context.getNumberColor());
00361 }
00362
00363 void NumberType::saveMathML( SequenceElement* se, QDomDocument doc, QDomElement de )
00364 {
00365 QDomElement name = doc.createElement( "mn" );
00366 QString value;
00367 for ( uint i = start(); i < end(); ++i ) {
00368 BasicElement* be = se->getChild( i );
00369 value += be->getCharacter();
00370 }
00371 TextElement* te = static_cast<TextElement*>( se->getChild( start() ) );
00372 QString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
00373 if ( !mathvariant.isNull() )
00374 name.setAttribute( "mathvariant", mathvariant );
00375
00376 name.appendChild( doc.createTextNode( value ) );
00377 de.appendChild( name );
00378 }
00379
00380
00381 SingleElementType::SingleElementType( SequenceParser* parser )
00382 : ElementType( parser )
00383 {
00384 parser->setElementType( start(), this );
00385 }
00386
00387 AbstractOperatorType::AbstractOperatorType( SequenceParser* parser )
00388 : SingleElementType( parser )
00389 {
00390 }
00391
00392 void AbstractOperatorType::saveMathML( SequenceElement* se, QDomDocument doc, QDomElement de )
00393 {
00394 QDomElement op = doc.createElement( "mo" );
00395 BasicElement* be = se->getChild( start() );
00396 if ( be->getCharacter().latin1() != 0 ) {
00397
00398 op.appendChild( doc.createTextNode( be->getCharacter() ) );
00399 }
00400 else {
00401
00402 QString s;
00403 op.appendChild( doc.createEntityReference( s.sprintf( "#x%05X", be->getCharacter().unicode() ) ) );
00404 }
00405 TextElement* te = static_cast<TextElement*>( be );
00406 QString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
00407 if ( !mathvariant.isNull() )
00408 op.setAttribute( "mathvariant", mathvariant );
00409
00410 de.appendChild( op );
00411 }
00412
00413 OperatorType::OperatorType( SequenceParser* parser )
00414 : AbstractOperatorType( parser )
00415 {
00416 }
00417
00418 luPt OperatorType::getSpaceBefore( const ContextStyle& context,
00419 ContextStyle::TextStyle tstyle )
00420 {
00421 if ( getPrev() != 0 ) {
00422 return getPrev()->getSpaceAfter( this, context, tstyle );
00423 }
00424 return 0;
00425 }
00426
00427 luPt OperatorType::getSpaceAfter( MultiElementType*,
00428 const ContextStyle& context,
00429 ContextStyle::TextStyle tstyle )
00430 {
00431 return mediumSpaceIfNotScript( context, tstyle );
00432 }
00433
00434 luPt OperatorType::getSpaceAfter( BracketType*,
00435 const ContextStyle& context,
00436 ContextStyle::TextStyle tstyle )
00437 {
00438 return mediumSpaceIfNotScript( context, tstyle );
00439 }
00440
00441 luPt OperatorType::getSpaceAfter( ComplexElementType*,
00442 const ContextStyle& context,
00443 ContextStyle::TextStyle tstyle )
00444 {
00445 return mediumSpaceIfNotScript( context, tstyle );
00446 }
00447
00448 luPt OperatorType::getSpaceAfter( InnerElementType*,
00449 const ContextStyle& context,
00450 ContextStyle::TextStyle tstyle )
00451 {
00452 return mediumSpaceIfNotScript( context, tstyle );
00453 }
00454
00455
00456 QFont OperatorType::getFont(const ContextStyle& context)
00457 {
00458 return context.getOperatorFont();
00459 }
00460
00461 void OperatorType::setUpPainter(const ContextStyle& context, QPainter& painter)
00462 {
00463 painter.setPen(context.getOperatorColor());
00464 }
00465
00466
00467 RelationType::RelationType( SequenceParser* parser )
00468 : AbstractOperatorType( parser )
00469 {
00470 }
00471
00472 luPt RelationType::getSpaceBefore( const ContextStyle& context,
00473 ContextStyle::TextStyle tstyle )
00474 {
00475 if ( getPrev() != 0 ) {
00476 return getPrev()->getSpaceAfter( this, context, tstyle );
00477 }
00478 return 0;
00479 }
00480
00481 luPt RelationType::getSpaceAfter( MultiElementType*,
00482 const ContextStyle& context,
00483 ContextStyle::TextStyle tstyle )
00484 {
00485 return thickSpaceIfNotScript( context, tstyle );
00486 }
00487
00488 luPt RelationType::getSpaceAfter( BracketType*,
00489 const ContextStyle& context,
00490 ContextStyle::TextStyle tstyle )
00491 {
00492 return thickSpaceIfNotScript( context, tstyle );
00493 }
00494
00495 luPt RelationType::getSpaceAfter( ComplexElementType*,
00496 const ContextStyle& context,
00497 ContextStyle::TextStyle tstyle )
00498 {
00499 return thickSpaceIfNotScript( context, tstyle );
00500 }
00501
00502 luPt RelationType::getSpaceAfter( InnerElementType*,
00503 const ContextStyle& context,
00504 ContextStyle::TextStyle tstyle )
00505 {
00506 return thickSpaceIfNotScript( context, tstyle );
00507 }
00508
00509 QFont RelationType::getFont( const ContextStyle& context )
00510 {
00511 return context.getOperatorFont();
00512 }
00513
00514 void RelationType::setUpPainter( const ContextStyle& context, QPainter& painter )
00515 {
00516 painter.setPen(context.getOperatorColor());
00517 }
00518
00519
00520
00521 PunctuationType::PunctuationType( SequenceParser* parser )
00522 : AbstractOperatorType( parser )
00523 {
00524 }
00525
00526 luPt PunctuationType::getSpaceBefore( const ContextStyle& context,
00527 ContextStyle::TextStyle tstyle )
00528 {
00529 if ( getPrev() != 0 ) {
00530 return getPrev()->getSpaceAfter( this, context, tstyle );
00531 }
00532 return 0;
00533 }
00534
00535 luPt PunctuationType::getSpaceAfter( MultiElementType*,
00536 const ContextStyle& context,
00537 ContextStyle::TextStyle tstyle )
00538 {
00539 return thinSpaceIfNotScript( context, tstyle );
00540 }
00541
00542 luPt PunctuationType::getSpaceAfter( RelationType*,
00543 const ContextStyle& context,
00544 ContextStyle::TextStyle tstyle )
00545 {
00546 return thickSpaceIfNotScript( context, tstyle );
00547 }
00548
00549 luPt PunctuationType::getSpaceAfter( PunctuationType*,
00550 const ContextStyle& context,
00551 ContextStyle::TextStyle tstyle )
00552 {
00553 return thinSpaceIfNotScript( context, tstyle );
00554 }
00555
00556 luPt PunctuationType::getSpaceAfter( BracketType*,
00557 const ContextStyle& context,
00558 ContextStyle::TextStyle tstyle )
00559 {
00560 return thinSpaceIfNotScript( context, tstyle );
00561 }
00562
00563 luPt PunctuationType::getSpaceAfter( ComplexElementType*,
00564 const ContextStyle& context,
00565 ContextStyle::TextStyle tstyle )
00566 {
00567 return thinSpaceIfNotScript( context, tstyle );
00568 }
00569
00570 luPt PunctuationType::getSpaceAfter( InnerElementType*,
00571 const ContextStyle& context,
00572 ContextStyle::TextStyle tstyle )
00573 {
00574 return thinSpaceIfNotScript( context, tstyle );
00575 }
00576
00577 QFont PunctuationType::getFont( const ContextStyle& context )
00578 {
00579 return context.getOperatorFont();
00580 }
00581
00582 void PunctuationType::setUpPainter( const ContextStyle& context, QPainter& painter )
00583 {
00584 painter.setPen( context.getDefaultColor() );
00585 }
00586
00587
00588 BracketType::BracketType( SequenceParser* parser )
00589 : SingleElementType( parser )
00590 {
00591 }
00592
00593 luPt BracketType::getSpaceBefore( const ContextStyle& context,
00594 ContextStyle::TextStyle tstyle )
00595 {
00596 if ( getPrev() != 0 ) {
00597 return getPrev()->getSpaceAfter( this, context, tstyle );
00598 }
00599 return 0;
00600 }
00601
00602 luPt BracketType::getSpaceAfter( OperatorType*,
00603 const ContextStyle& context,
00604 ContextStyle::TextStyle tstyle )
00605 {
00606 return mediumSpaceIfNotScript( context, tstyle );
00607 }
00608
00609 luPt BracketType::getSpaceAfter( RelationType*,
00610 const ContextStyle& context,
00611 ContextStyle::TextStyle tstyle )
00612 {
00613 return thickSpaceIfNotScript( context, tstyle );
00614 }
00615
00616 luPt BracketType::getSpaceAfter( InnerElementType*,
00617 const ContextStyle& context,
00618 ContextStyle::TextStyle tstyle )
00619 {
00620 return thinSpaceIfNotScript( context, tstyle );
00621 }
00622
00623
00624 ComplexElementType::ComplexElementType( SequenceParser* parser )
00625 : SingleElementType( parser )
00626 {
00627 }
00628
00629 luPt ComplexElementType::getSpaceBefore( const ContextStyle& context,
00630 ContextStyle::TextStyle tstyle )
00631 {
00632 if ( getPrev() != 0 ) {
00633 return getPrev()->getSpaceAfter( this, context, tstyle );
00634 }
00635 return 0;
00636 }
00637
00638 luPt ComplexElementType::getSpaceAfter( OperatorType*,
00639 const ContextStyle& context,
00640 ContextStyle::TextStyle tstyle )
00641 {
00642 return mediumSpaceIfNotScript( context, tstyle );
00643 }
00644
00645 luPt ComplexElementType::getSpaceAfter( RelationType*,
00646 const ContextStyle& context,
00647 ContextStyle::TextStyle tstyle )
00648 {
00649 return thickSpaceIfNotScript( context, tstyle );
00650 }
00651
00652 luPt ComplexElementType::getSpaceAfter( InnerElementType*,
00653 const ContextStyle& context,
00654 ContextStyle::TextStyle tstyle )
00655 {
00656 return thinSpaceIfNotScript( context, tstyle );
00657 }
00658
00659
00660 InnerElementType::InnerElementType( SequenceParser* parser )
00661 : SingleElementType( parser )
00662 {
00663 }
00664
00665 luPt InnerElementType::getSpaceBefore( const ContextStyle& context,
00666 ContextStyle::TextStyle tstyle )
00667 {
00668 if ( getPrev() != 0 ) {
00669 return getPrev()->getSpaceAfter( this, context, tstyle );
00670 }
00671 return 0;
00672 }
00673
00674 luPt InnerElementType::getSpaceAfter( MultiElementType*,
00675 const ContextStyle& context,
00676 ContextStyle::TextStyle tstyle )
00677 {
00678 return thinSpaceIfNotScript( context, tstyle );
00679 }
00680
00681 luPt InnerElementType::getSpaceAfter( OperatorType*,
00682 const ContextStyle& context,
00683 ContextStyle::TextStyle tstyle )
00684 {
00685 return mediumSpaceIfNotScript( context, tstyle );
00686 }
00687
00688 luPt InnerElementType::getSpaceAfter( RelationType*,
00689 const ContextStyle& context,
00690 ContextStyle::TextStyle tstyle )
00691 {
00692 return thickSpaceIfNotScript( context, tstyle );
00693 }
00694
00695 luPt InnerElementType::getSpaceAfter( PunctuationType*,
00696 const ContextStyle& context,
00697 ContextStyle::TextStyle tstyle )
00698 {
00699 return thinSpaceIfNotScript( context, tstyle );
00700 }
00701
00702 luPt InnerElementType::getSpaceAfter( BracketType*,
00703 const ContextStyle& context,
00704 ContextStyle::TextStyle tstyle )
00705 {
00706 return thinSpaceIfNotScript( context, tstyle );
00707 }
00708
00709 luPt InnerElementType::getSpaceAfter( ComplexElementType*,
00710 const ContextStyle& context,
00711 ContextStyle::TextStyle tstyle )
00712 {
00713 return thinSpaceIfNotScript( context, tstyle );
00714 }
00715
00716 luPt InnerElementType::getSpaceAfter( InnerElementType*,
00717 const ContextStyle& context,
00718 ContextStyle::TextStyle tstyle )
00719 {
00720 return thinSpaceIfNotScript( context, tstyle );
00721 }
00722
00723
00724 KFORMULA_NAMESPACE_END