lib Library API Documentation

elementtype.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
00003                   Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
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  * Converts CharStyle and CharFamily to the MathML 'mathvariant'
00041  * attribute (see MathML spec 3.2.2).
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         //cerr << "SequenceType::SequenceType(): " << parser->getTokenType() << " "
00220         //     << parser->getStart() << " " << parser->getEnd() << endl;
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     QDomElement name = doc.createElement( "mi" );
00325     QString value;
00326     for ( uint i = start(); i < end(); ++i ) {
00327         BasicElement* be = se->getChild( i );
00328         //TextElement* te = static_cast<TextElement*>( be );
00329         value += be->getCharacter();
00330     }
00331     name.appendChild( doc.createTextNode( value ) );
00332     de.appendChild( name );*/
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         // latin-1 char
00391         op.appendChild( doc.createTextNode( be->getCharacter() ) );
00392     }
00393     else {
00394         // unicode char
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
KDE Logo
This file is part of the documentation for lib Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:39:55 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003