lib Library API Documentation

cmstyle.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Ulrich Kuettler <ulrich.kuettler@gmx.de>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include <qpainter.h>
00021 #include <qpen.h>
00022 
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025 
00026 #include "kformuladefs.h"
00027 #include "cmstyle.h"
00028 
00029 
00030 KFORMULA_NAMESPACE_BEGIN
00031 
00032 #include "cmmapping.cc"
00033 
00034 bool CMStyle::init( ContextStyle* context )
00035 {
00036     SymbolTable* st = symbolTable();
00037     st->init( context );
00038 
00039     SymbolTable::NameTable tempNames;
00040     fillNameTable( tempNames );
00041 
00042     st->initFont( cmbx10Map, "cmbx10", tempNames );
00043     st->initFont( cmex10Map, "cmex10", tempNames );
00044     st->initFont( cmmi10Map, "cmmi10", tempNames );
00045     st->initFont( cmr10Map, "cmr10", tempNames );
00046     st->initFont( cmsy10Map, "cmsy10", tempNames );
00047     st->initFont( msam10Map, "msam10", tempNames );
00048     st->initFont( msbm10Map, "msbm10", tempNames );
00049 
00050     return true;
00051 }
00052 
00053 
00054 const AlphaTable* CMStyle::alphaTable() const
00055 {
00056     return &m_alphaTable;
00057 }
00058 
00059 
00060 Artwork* CMStyle::createArtwork( SymbolType type ) const
00061 {
00062     return new CMArtwork( type );
00063 }
00064 
00065 
00066 CMAlphaTable::CMAlphaTable()
00067 {
00068 }
00069 
00070 
00071 AlphaTableEntry CMAlphaTable::entry( short pos,
00072                                      CharFamily family,
00073                                      CharStyle /*style*/ ) const
00074 {
00075     /*
00076     static short uppercase_greek[] = {
00077         0x0393, // Gamma
00078         0x0394, // Delta
00079         0x0398, // Theta
00080         0x039B, // Lambda
00081         0x039E, // Xi
00082         0x03A0, // Pi
00083         0x03A3, // Sigma
00084         0x03A6, // Phi
00085         0x03A8, // Psi
00086         0x03A9, // Omega
00087         0x03D2, // Upsilon
00088         0
00089     };
00090     */
00091 
00092     AlphaTableEntry entry;
00093     switch( family ) {
00094         //case normal:
00095     case scriptFamily:
00096         /*
00097         for ( int i=0; uppercase_greek[i] != 0; ++i ) {
00098             if ( pos == uppercase_greek[i] ) {
00099                 entry.pos = pos;
00100                 entry.font = QFont( "cmsl10" );
00101                 return;
00102             }
00103         }
00104         */
00105         if ( ( pos >= 'A' ) && ( pos <= 'Z' ) ) {
00106             entry.pos = pos;
00107             entry.font = QFont( "cmsy10" );
00108         }
00109         break;
00110     case frakturFamily:
00111         break;
00112     case doubleStruckFamily:
00113         if ( ( pos >= 'A' ) && ( pos <= 'Z' ) ) {
00114             entry.pos = pos;
00115             entry.font = QFont( "msbm10" );
00116         }
00117         break;
00118     default:
00119         break;
00120     }
00121     return entry;
00122 }
00123 
00124 
00125 static const char cmex_LeftSquareBracket = 163;
00126 static const char cmex_RightSquareBracket = 164;
00127 static const char cmex_LeftCurlyBracket = 169;
00128 static const char cmex_RightCurlyBracket = 170;
00129 static const char cmex_LeftCornerBracket = 173;
00130 static const char cmex_RightCornerBracket = 174;
00131 static const char cmex_LeftRoundBracket = 161;
00132 static const char cmex_RightRoundBracket = 162;
00133 static const char cmex_SlashBracket = 177;
00134 static const char cmex_BackSlashBracket = 178;
00135 //static const char cmex_LeftLineBracket = 0x4b;
00136 //static const char cmex_RightLineBracket = 0x4b;
00137 
00138 // use the big symbols here
00139 static const char cmex_Int = 90;
00140 static const char cmex_Sum = 88;
00141 static const char cmex_Prod = 89;
00142 
00143 
00144 // cmex is a special font with symbols in four sizes.
00145 static short cmex_nextchar( short ch )
00146 {
00147     switch ( ch ) {
00148     case 161: return 179;
00149     case 162: return 180;
00150     case 163: return 104;
00151     case 164: return 105;
00152     case 169: return 110;
00153     case 170: return 111;
00154     case 165: return 106;
00155     case 166: return 107;
00156     case 167: return 108;
00157     case 168: return 109;
00158     case 173: return 68;
00159     case 174: return 69;
00160     case 177: return 46;
00161     case 178: return 47;
00162 
00163     case 179: return 181;
00164     case 180: return 182;
00165     case 104: return 183;
00166     case 105: return 184;
00167     case 110: return 189;
00168     case 111: return 190;
00169     case 106: return 185;
00170     case 107: return 186;
00171     case 108: return 187;
00172     case 109: return 188;
00173     case 68: return 191;
00174     case 69: return 192;
00175     case 46: return 193;
00176     case 47: return 194;
00177 
00178     case 181: return 195;
00179     case 182: return 33;
00180     case 183: return 34;
00181     case 184: return 35;
00182     case 189: return 40;
00183     case 190: return 41;
00184     case 185: return 36;
00185     case 186: return 37;
00186     case 187: return 38;
00187     case 188: return 39;
00188     case 191: return 42;
00189     case 192: return 43;
00190     case 193: return 44;
00191     case 194: return 45;
00192     }
00193     return 0;
00194 }
00195 
00196 CMArtwork::CMArtwork( SymbolType t )
00197     : Artwork( t ), cmChar( -1 )
00198 {
00199 }
00200 
00201 
00202 void CMArtwork::calcSizes( const ContextStyle& style,
00203                            ContextStyle::TextStyle tstyle,
00204                            luPt parentSize )
00205 {
00206     setBaseline( -1 );
00207     cmChar = -1;
00208     luPt mySize = style.getAdjustedSize( tstyle );
00209     switch (getType()) {
00210     case LeftSquareBracket:
00211         if ( calcCMDelimiterSize( style, cmex_LeftSquareBracket,
00212                                   mySize, parentSize ) ) {
00213             return;
00214         }
00215         calcRoundBracket( style, leftSquareBracket, parentSize, mySize );
00216         break;
00217     case RightSquareBracket:
00218         if ( calcCMDelimiterSize( style, cmex_RightSquareBracket,
00219                                   mySize, parentSize ) ) {
00220             return;
00221         }
00222         calcRoundBracket( style, rightSquareBracket, parentSize, mySize );
00223         break;
00224     case LeftLineBracket:
00225         calcRoundBracket( style, leftLineBracket, parentSize, mySize );
00226         setWidth( getWidth()/2 );
00227         break;
00228     case RightLineBracket:
00229         calcRoundBracket( style, rightLineBracket, parentSize, mySize );
00230         setWidth( getWidth()/2 );
00231         break;
00232     case SlashBracket:
00233         if ( calcCMDelimiterSize( style, cmex_SlashBracket,
00234                                   mySize, parentSize ) ) {
00235             return;
00236         }
00237         calcLargest( style, cmex_SlashBracket, mySize );
00238         break;
00239     case BackSlashBracket:
00240         if ( calcCMDelimiterSize( style, cmex_BackSlashBracket,
00241                                   mySize, parentSize ) ) {
00242             return;
00243         }
00244         calcLargest( style, cmex_BackSlashBracket, mySize );
00245         break;
00246     case LeftCornerBracket:
00247         if ( calcCMDelimiterSize( style, cmex_LeftCornerBracket,
00248                                   mySize, parentSize ) ) {
00249             return;
00250         }
00251         calcLargest( style, cmex_LeftCornerBracket, mySize );
00252         break;
00253     case RightCornerBracket:
00254         if ( calcCMDelimiterSize( style, cmex_RightCornerBracket,
00255                                   mySize, parentSize ) ) {
00256             return;
00257         }
00258         calcLargest( style, cmex_RightCornerBracket, mySize );
00259         break;
00260     case LeftRoundBracket:
00261         if ( calcCMDelimiterSize( style, cmex_LeftRoundBracket,
00262                                   mySize, parentSize ) ) {
00263             return;
00264         }
00265         calcRoundBracket( style, leftRoundBracket, parentSize, mySize );
00266         break;
00267     case RightRoundBracket:
00268         if ( calcCMDelimiterSize( style, cmex_RightRoundBracket,
00269                                   mySize, parentSize ) ) {
00270             return;
00271         }
00272         calcRoundBracket( style, rightRoundBracket, parentSize, mySize );
00273         break;
00274     case EmptyBracket:
00275         setHeight(parentSize);
00276         //setWidth(style.getEmptyRectWidth());
00277         setWidth(0);
00278         break;
00279     case LeftCurlyBracket:
00280         if ( calcCMDelimiterSize( style, cmex_LeftCurlyBracket,
00281                                   mySize, parentSize ) ) {
00282             return;
00283         }
00284         calcCurlyBracket( style, leftCurlyBracket, parentSize, mySize );
00285         break;
00286     case RightCurlyBracket:
00287         if ( calcCMDelimiterSize( style, cmex_RightCurlyBracket,
00288                                   mySize, parentSize ) ) {
00289             return;
00290         }
00291         calcCurlyBracket( style, rightCurlyBracket, parentSize, mySize );
00292         break;
00293     case Integral:
00294         calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Int );
00295         break;
00296     case Sum:
00297         calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Sum );
00298         break;
00299     case Product:
00300         calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Prod );
00301         break;
00302     }
00303 }
00304 
00305 
00306 void CMArtwork::calcSizes( const ContextStyle& style,
00307                            ContextStyle::TextStyle tstyle )
00308 {
00309     luPt mySize = style.getAdjustedSize( tstyle );
00310     switch (getType()) {
00311     case LeftLineBracket:
00312     case RightLineBracket:
00313         calcCharSize(style, mySize, 0x2223);
00314         break;
00315     default:
00316         Artwork::calcSizes( style, tstyle );
00317         break;
00318     }
00319 }
00320 
00321 
00322 void CMArtwork::draw( QPainter& painter, const LuPixelRect& r,
00323                       const ContextStyle& style,
00324                       ContextStyle::TextStyle tstyle,
00325                       const LuPixelPoint& parentOrigin )
00326 {
00327     luPt mySize = style.getAdjustedSize( tstyle );
00328     luPixel myX = parentOrigin.x() + getX();
00329     luPixel myY = parentOrigin.y() + getY();
00330     if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00331         return;
00332 
00333     painter.setPen(style.getDefaultColor());
00334 
00335     switch (getType()) {
00336     case LeftLineBracket:
00337     case RightLineBracket:
00338         drawCharacter(painter, style, myX, myY, mySize, 0x2223);
00339         break;
00340     default:
00341         Artwork::draw( painter, r, style, tstyle, parentOrigin );
00342         break;
00343     }
00344 }
00345 
00346 
00347 void CMArtwork::draw(QPainter& painter, const LuPixelRect& r,
00348                      const ContextStyle& style, ContextStyle::TextStyle tstyle,
00349                      luPt /*parentSize*/, const LuPixelPoint& origin)
00350 {
00351     luPt mySize = style.getAdjustedSize( tstyle );
00352     luPixel myX = origin.x() + getX();
00353     luPixel myY = origin.y() + getY();
00354     if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00355         return;
00356 
00357     painter.setPen(style.getDefaultColor());
00358 
00359     switch (getType()) {
00360     case LeftSquareBracket:
00361         if ( cmChar != -1 ) {
00362             drawCMDelimiter( painter, style, myX, myY, mySize );
00363         }
00364         else {
00365             drawBigRoundBracket( painter, style, leftSquareBracket, myX, myY, mySize );
00366         }
00367         break;
00368     case RightSquareBracket:
00369         if ( cmChar != -1 ) {
00370             drawCMDelimiter( painter, style, myX, myY, mySize );
00371         }
00372         else {
00373             drawBigRoundBracket( painter, style, rightSquareBracket, myX, myY, mySize );
00374         }
00375         break;
00376     case LeftCurlyBracket:
00377         if ( cmChar != -1 ) {
00378             drawCMDelimiter( painter, style, myX, myY, mySize );
00379         }
00380         else {
00381             drawBigCurlyBracket( painter, style, leftCurlyBracket, myX, myY, mySize );
00382         }
00383         break;
00384     case RightCurlyBracket:
00385         if ( cmChar != -1 ) {
00386             drawCMDelimiter( painter, style, myX, myY, mySize );
00387         }
00388         else {
00389             drawBigCurlyBracket( painter, style, rightCurlyBracket, myX, myY, mySize );
00390         }
00391         break;
00392     case LeftLineBracket: {
00393         luPixel halfWidth = getWidth()/2;
00394         drawBigRoundBracket( painter, style, leftLineBracket,
00395                              myX-halfWidth, myY, mySize );
00396     }
00397         break;
00398     case RightLineBracket: {
00399         luPixel halfWidth = getWidth()/2;
00400         drawBigRoundBracket( painter, style, rightLineBracket,
00401                              myX-halfWidth, myY, mySize );
00402     }
00403         break;
00404     case SlashBracket:
00405         if ( cmChar != -1 ) {
00406             drawCMDelimiter( painter, style, myX, myY, mySize );
00407         }
00408         break;
00409     case BackSlashBracket:
00410         if ( cmChar != -1 ) {
00411             drawCMDelimiter( painter, style, myX, myY, mySize );
00412         }
00413         break;
00414     case LeftCornerBracket:
00415         if ( cmChar != -1 ) {
00416             drawCMDelimiter( painter, style, myX, myY, mySize );
00417         }
00418         else drawCharacter(painter, style, myX, myY, mySize, leftAngleBracketChar);
00419         break;
00420     case RightCornerBracket:
00421         if ( cmChar != -1 ) {
00422             drawCMDelimiter( painter, style, myX, myY, mySize );
00423         }
00424         else drawCharacter(painter, style, myX, myY, mySize, rightAngleBracketChar);
00425         break;
00426     case LeftRoundBracket:
00427         if ( cmChar != -1 ) {
00428             drawCMDelimiter( painter, style, myX, myY, mySize );
00429         }
00430         else {
00431             drawBigRoundBracket( painter, style, leftRoundBracket, myX, myY, mySize );
00432         }
00433         break;
00434     case RightRoundBracket:
00435         if ( cmChar != -1 ) {
00436             drawCMDelimiter( painter, style, myX, myY, mySize );
00437         }
00438         else {
00439             drawBigRoundBracket( painter, style, rightRoundBracket, myX, myY, mySize );
00440         }
00441         break;
00442     case EmptyBracket:
00443         break;
00444     case Integral:
00445         drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Int);
00446         break;
00447     case Sum:
00448         drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Sum);
00449         break;
00450     case Product:
00451         drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Prod);
00452         break;
00453     }
00454 
00455     // debug
00456 //     painter.setBrush(Qt::NoBrush);
00457 //     painter.setPen(Qt::green);
00458 //     painter.drawRect( style.layoutUnitToPixelX( myX ),
00459 //                       style.layoutUnitToPixelY( myY ),
00460 //                       style.layoutUnitToPixelX( getWidth() ),
00461 //                       style.layoutUnitToPixelY( getHeight() ) );
00462 }
00463 
00464 
00465 bool CMArtwork::isNormalChar() const
00466 {
00467     return Artwork::isNormalChar() && ( cmChar == -1 );
00468 }
00469 
00470 double CMArtwork::slant() const
00471 {
00472     if ( getType() == Integral ) {
00473         return 0.25;
00474     }
00475     return 0;
00476 }
00477 
00478 bool CMArtwork::calcCMDelimiterSize( const ContextStyle& context,
00479                                      uchar c,
00480                                      luPt fontSize,
00481                                      luPt parentSize )
00482 {
00483     QFont f( "cmex10" );
00484     f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00485     QFontMetrics fm( f );
00486 
00487     for ( char i=1; c != 0; ++i ) {
00488         LuPixelRect bound = fm.boundingRect( c );
00489 
00490         luPt height = context.ptToLayoutUnitPt( bound.height() );
00491         if ( height >= parentSize ) {
00492             luPt width = context.ptToLayoutUnitPt( fm.width( c ) );
00493             luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00494 
00495             cmChar = c;
00496 
00497             setHeight( height );
00498             setWidth( width );
00499             setBaseline( baseline );
00500 
00501             return true;
00502         }
00503         c = cmex_nextchar( c );
00504     }
00505 
00506     // Build it up from pieces.
00507     return false;
00508 }
00509 
00510 
00511 void CMArtwork::calcLargest( const ContextStyle& context,
00512                              uchar c, luPt fontSize )
00513 {
00514     QFont f( "cmex10" );
00515     f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00516     QFontMetrics fm( f );
00517 
00518     cmChar = c;
00519     for ( ;; ) {
00520         c = cmex_nextchar( c );
00521         if ( c == 0 ) {
00522             break;
00523         }
00524         cmChar = c;
00525     }
00526 
00527     LuPixelRect bound = fm.boundingRect( cmChar );
00528 
00529     luPt height = context.ptToLayoutUnitPt( bound.height() );
00530     luPt width = context.ptToLayoutUnitPt( fm.width( cmChar ) );
00531     luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00532 
00533     setHeight( height );
00534     setWidth( width );
00535     setBaseline( baseline );
00536 }
00537 
00538 
00539 void CMArtwork::drawCMDelimiter( QPainter& painter, const ContextStyle& style,
00540                                  luPixel x, luPixel y,
00541                                  luPt height )
00542 {
00543     QFont f( "cmex10" );
00544     f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00545 
00546     painter.setFont( f );
00547     painter.drawText( style.layoutUnitToPixelX( x ),
00548                       style.layoutUnitToPixelY( y + getBaseline() ),
00549                       QString( QChar( cmChar ) ) );
00550 
00551     // Debug
00552 #if 0
00553     QFontMetrics fm( f );
00554     LuPixelRect bound = fm.boundingRect( cmChar );
00555     painter.setBrush(Qt::NoBrush);
00556     painter.setPen(Qt::green);
00557     painter.drawRect( style.layoutUnitToPixelX( x ),
00558                       style.layoutUnitToPixelY( y ),
00559                       fm.width( cmChar ),
00560                       bound.height() );
00561 #endif
00562 }
00563 
00564 
00565 KFORMULA_NAMESPACE_END
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Mar 20 14:25:23 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003