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 QStringList CMStyle::missingFonts()
00066 {
00067     QStringList missing;
00068 
00069     testFont( missing, "cmbx10" );
00070     testFont( missing, "cmex10" );
00071     testFont( missing, "cmmi10" );
00072     testFont( missing, "cmr10" );
00073     testFont( missing, "cmsy10" );
00074     testFont( missing, "msam10" );
00075     testFont( missing, "msbm10" );
00076 
00077     return missing;
00078 }
00079 
00080 
00081 CMAlphaTable::CMAlphaTable()
00082 {
00083 }
00084 
00085 
00086 AlphaTableEntry CMAlphaTable::entry( short pos,
00087                                      CharFamily family,
00088                                      CharStyle /*style*/ ) const
00089 {
00090     /*
00091     static short uppercase_greek[] = {
00092         0x0393, // Gamma
00093         0x0394, // Delta
00094         0x0398, // Theta
00095         0x039B, // Lambda
00096         0x039E, // Xi
00097         0x03A0, // Pi
00098         0x03A3, // Sigma
00099         0x03A6, // Phi
00100         0x03A8, // Psi
00101         0x03A9, // Omega
00102         0x03D2, // Upsilon
00103         0
00104     };
00105     */
00106 
00107     AlphaTableEntry entry;
00108     switch( family ) {
00109         //case normal:
00110     case scriptFamily:
00111         /*
00112         for ( int i=0; uppercase_greek[i] != 0; ++i ) {
00113             if ( pos == uppercase_greek[i] ) {
00114                 entry.pos = pos;
00115                 entry.font = QFont( "cmsl10" );
00116                 return;
00117             }
00118         }
00119         */
00120         if ( ( pos >= 'A' ) && ( pos <= 'Z' ) ) {
00121             entry.pos = pos;
00122             entry.font = QFont( "cmsy10" );
00123         }
00124         break;
00125     case frakturFamily:
00126         break;
00127     case doubleStruckFamily:
00128         if ( ( pos >= 'A' ) && ( pos <= 'Z' ) ) {
00129             entry.pos = pos;
00130             entry.font = QFont( "msbm10" );
00131         }
00132         break;
00133     default:
00134         break;
00135     }
00136     return entry;
00137 }
00138 
00139 
00140 static const char cmex_LeftSquareBracket = 163;
00141 static const char cmex_RightSquareBracket = 164;
00142 static const char cmex_LeftCurlyBracket = 169;
00143 static const char cmex_RightCurlyBracket = 170;
00144 static const char cmex_LeftCornerBracket = 173;
00145 static const char cmex_RightCornerBracket = 174;
00146 static const char cmex_LeftRoundBracket = 161;
00147 static const char cmex_RightRoundBracket = 162;
00148 static const char cmex_SlashBracket = 177;
00149 static const char cmex_BackSlashBracket = 178;
00150 //static const char cmex_LeftLineBracket = 0x4b;
00151 //static const char cmex_RightLineBracket = 0x4b;
00152 
00153 // use the big symbols here
00154 static const char cmex_Int = 90;
00155 static const char cmex_Sum = 88;
00156 static const char cmex_Prod = 89;
00157 
00158 
00159 // cmex is a special font with symbols in four sizes.
00160 static short cmex_nextchar( short ch )
00161 {
00162     switch ( ch ) {
00163     case 161: return 179;
00164     case 162: return 180;
00165     case 163: return 104;
00166     case 164: return 105;
00167     case 169: return 110;
00168     case 170: return 111;
00169     case 165: return 106;
00170     case 166: return 107;
00171     case 167: return 108;
00172     case 168: return 109;
00173     case 173: return 68;
00174     case 174: return 69;
00175     case 177: return 46;
00176     case 178: return 47;
00177 
00178     case 179: return 181;
00179     case 180: return 182;
00180     case 104: return 183;
00181     case 105: return 184;
00182     case 110: return 189;
00183     case 111: return 190;
00184     case 106: return 185;
00185     case 107: return 186;
00186     case 108: return 187;
00187     case 109: return 188;
00188     case 68: return 191;
00189     case 69: return 192;
00190     case 46: return 193;
00191     case 47: return 194;
00192 
00193     case 181: return 195;
00194     case 182: return 33;
00195     case 183: return 34;
00196     case 184: return 35;
00197     case 189: return 40;
00198     case 190: return 41;
00199     case 185: return 36;
00200     case 186: return 37;
00201     case 187: return 38;
00202     case 188: return 39;
00203     case 191: return 42;
00204     case 192: return 43;
00205     case 193: return 44;
00206     case 194: return 45;
00207     }
00208     return 0;
00209 }
00210 
00211 CMArtwork::CMArtwork( SymbolType t )
00212     : Artwork( t ), cmChar( -1 )
00213 {
00214 }
00215 
00216 
00217 void CMArtwork::calcSizes( const ContextStyle& style,
00218                            ContextStyle::TextStyle tstyle,
00219                            luPt parentSize )
00220 {
00221     setBaseline( -1 );
00222     cmChar = -1;
00223     luPt mySize = style.getAdjustedSize( tstyle );
00224     switch (getType()) {
00225     case LeftSquareBracket:
00226         if ( calcCMDelimiterSize( style, cmex_LeftSquareBracket,
00227                                   mySize, parentSize ) ) {
00228             return;
00229         }
00230         calcRoundBracket( style, leftSquareBracket, parentSize, mySize );
00231         break;
00232     case RightSquareBracket:
00233         if ( calcCMDelimiterSize( style, cmex_RightSquareBracket,
00234                                   mySize, parentSize ) ) {
00235             return;
00236         }
00237         calcRoundBracket( style, rightSquareBracket, parentSize, mySize );
00238         break;
00239     case LeftLineBracket:
00240         calcRoundBracket( style, leftLineBracket, parentSize, mySize );
00241         setWidth( getWidth()/2 );
00242         break;
00243     case RightLineBracket:
00244         calcRoundBracket( style, rightLineBracket, parentSize, mySize );
00245         setWidth( getWidth()/2 );
00246         break;
00247     case SlashBracket:
00248         if ( calcCMDelimiterSize( style, cmex_SlashBracket,
00249                                   mySize, parentSize ) ) {
00250             return;
00251         }
00252         calcLargest( style, cmex_SlashBracket, mySize );
00253         break;
00254     case BackSlashBracket:
00255         if ( calcCMDelimiterSize( style, cmex_BackSlashBracket,
00256                                   mySize, parentSize ) ) {
00257             return;
00258         }
00259         calcLargest( style, cmex_BackSlashBracket, mySize );
00260         break;
00261     case LeftCornerBracket:
00262         if ( calcCMDelimiterSize( style, cmex_LeftCornerBracket,
00263                                   mySize, parentSize ) ) {
00264             return;
00265         }
00266         calcLargest( style, cmex_LeftCornerBracket, mySize );
00267         break;
00268     case RightCornerBracket:
00269         if ( calcCMDelimiterSize( style, cmex_RightCornerBracket,
00270                                   mySize, parentSize ) ) {
00271             return;
00272         }
00273         calcLargest( style, cmex_RightCornerBracket, mySize );
00274         break;
00275     case LeftRoundBracket:
00276         if ( calcCMDelimiterSize( style, cmex_LeftRoundBracket,
00277                                   mySize, parentSize ) ) {
00278             return;
00279         }
00280         calcRoundBracket( style, leftRoundBracket, parentSize, mySize );
00281         break;
00282     case RightRoundBracket:
00283         if ( calcCMDelimiterSize( style, cmex_RightRoundBracket,
00284                                   mySize, parentSize ) ) {
00285             return;
00286         }
00287         calcRoundBracket( style, rightRoundBracket, parentSize, mySize );
00288         break;
00289     case EmptyBracket:
00290         setHeight(parentSize);
00291         //setWidth(style.getEmptyRectWidth());
00292         setWidth(0);
00293         break;
00294     case LeftCurlyBracket:
00295         if ( calcCMDelimiterSize( style, cmex_LeftCurlyBracket,
00296                                   mySize, parentSize ) ) {
00297             return;
00298         }
00299         calcCurlyBracket( style, leftCurlyBracket, parentSize, mySize );
00300         break;
00301     case RightCurlyBracket:
00302         if ( calcCMDelimiterSize( style, cmex_RightCurlyBracket,
00303                                   mySize, parentSize ) ) {
00304             return;
00305         }
00306         calcCurlyBracket( style, rightCurlyBracket, parentSize, mySize );
00307         break;
00308     case Integral:
00309         calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Int );
00310         break;
00311     case Sum:
00312         calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Sum );
00313         break;
00314     case Product:
00315         calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Prod );
00316         break;
00317     }
00318 }
00319 
00320 
00321 void CMArtwork::calcSizes( const ContextStyle& style,
00322                            ContextStyle::TextStyle tstyle )
00323 {
00324     luPt mySize = style.getAdjustedSize( tstyle );
00325     switch (getType()) {
00326     case LeftLineBracket:
00327     case RightLineBracket:
00328         calcCharSize(style, mySize, 0x2223);
00329         break;
00330     default:
00331         Artwork::calcSizes( style, tstyle );
00332         break;
00333     }
00334 }
00335 
00336 
00337 void CMArtwork::draw( QPainter& painter, const LuPixelRect& r,
00338                       const ContextStyle& style,
00339                       ContextStyle::TextStyle tstyle,
00340                       const LuPixelPoint& parentOrigin )
00341 {
00342     luPt mySize = style.getAdjustedSize( tstyle );
00343     luPixel myX = parentOrigin.x() + getX();
00344     luPixel myY = parentOrigin.y() + getY();
00345     if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00346         return;
00347 
00348     painter.setPen(style.getDefaultColor());
00349 
00350     switch (getType()) {
00351     case LeftLineBracket:
00352     case RightLineBracket:
00353         drawCharacter(painter, style, myX, myY, mySize, 0x2223);
00354         break;
00355     default:
00356         Artwork::draw( painter, r, style, tstyle, parentOrigin );
00357         break;
00358     }
00359 }
00360 
00361 
00362 void CMArtwork::draw(QPainter& painter, const LuPixelRect& r,
00363                      const ContextStyle& style, ContextStyle::TextStyle tstyle,
00364                      luPt /*parentSize*/, const LuPixelPoint& origin)
00365 {
00366     luPt mySize = style.getAdjustedSize( tstyle );
00367     luPixel myX = origin.x() + getX();
00368     luPixel myY = origin.y() + getY();
00369     if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00370         return;
00371 
00372     painter.setPen(style.getDefaultColor());
00373 
00374     switch (getType()) {
00375     case LeftSquareBracket:
00376         if ( cmChar != -1 ) {
00377             drawCMDelimiter( painter, style, myX, myY, mySize );
00378         }
00379         else {
00380             drawBigRoundBracket( painter, style, leftSquareBracket, myX, myY, mySize );
00381         }
00382         break;
00383     case RightSquareBracket:
00384         if ( cmChar != -1 ) {
00385             drawCMDelimiter( painter, style, myX, myY, mySize );
00386         }
00387         else {
00388             drawBigRoundBracket( painter, style, rightSquareBracket, myX, myY, mySize );
00389         }
00390         break;
00391     case LeftCurlyBracket:
00392         if ( cmChar != -1 ) {
00393             drawCMDelimiter( painter, style, myX, myY, mySize );
00394         }
00395         else {
00396             drawBigCurlyBracket( painter, style, leftCurlyBracket, myX, myY, mySize );
00397         }
00398         break;
00399     case RightCurlyBracket:
00400         if ( cmChar != -1 ) {
00401             drawCMDelimiter( painter, style, myX, myY, mySize );
00402         }
00403         else {
00404             drawBigCurlyBracket( painter, style, rightCurlyBracket, myX, myY, mySize );
00405         }
00406         break;
00407     case LeftLineBracket: {
00408         luPixel halfWidth = getWidth()/2;
00409         drawBigRoundBracket( painter, style, leftLineBracket,
00410                              myX-halfWidth, myY, mySize );
00411     }
00412         break;
00413     case RightLineBracket: {
00414         luPixel halfWidth = getWidth()/2;
00415         drawBigRoundBracket( painter, style, rightLineBracket,
00416                              myX-halfWidth, myY, mySize );
00417     }
00418         break;
00419     case SlashBracket:
00420         if ( cmChar != -1 ) {
00421             drawCMDelimiter( painter, style, myX, myY, mySize );
00422         }
00423         break;
00424     case BackSlashBracket:
00425         if ( cmChar != -1 ) {
00426             drawCMDelimiter( painter, style, myX, myY, mySize );
00427         }
00428         break;
00429     case LeftCornerBracket:
00430         if ( cmChar != -1 ) {
00431             drawCMDelimiter( painter, style, myX, myY, mySize );
00432         }
00433         else drawCharacter(painter, style, myX, myY, mySize, leftAngleBracketChar);
00434         break;
00435     case RightCornerBracket:
00436         if ( cmChar != -1 ) {
00437             drawCMDelimiter( painter, style, myX, myY, mySize );
00438         }
00439         else drawCharacter(painter, style, myX, myY, mySize, rightAngleBracketChar);
00440         break;
00441     case LeftRoundBracket:
00442         if ( cmChar != -1 ) {
00443             drawCMDelimiter( painter, style, myX, myY, mySize );
00444         }
00445         else {
00446             drawBigRoundBracket( painter, style, leftRoundBracket, myX, myY, mySize );
00447         }
00448         break;
00449     case RightRoundBracket:
00450         if ( cmChar != -1 ) {
00451             drawCMDelimiter( painter, style, myX, myY, mySize );
00452         }
00453         else {
00454             drawBigRoundBracket( painter, style, rightRoundBracket, myX, myY, mySize );
00455         }
00456         break;
00457     case EmptyBracket:
00458         break;
00459     case Integral:
00460         drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Int);
00461         break;
00462     case Sum:
00463         drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Sum);
00464         break;
00465     case Product:
00466         drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Prod);
00467         break;
00468     }
00469 
00470     // debug
00471 //     painter.setBrush(Qt::NoBrush);
00472 //     painter.setPen(Qt::green);
00473 //     painter.drawRect( style.layoutUnitToPixelX( myX ),
00474 //                       style.layoutUnitToPixelY( myY ),
00475 //                       style.layoutUnitToPixelX( getWidth() ),
00476 //                       style.layoutUnitToPixelY( getHeight() ) );
00477 }
00478 
00479 
00480 bool CMArtwork::isNormalChar() const
00481 {
00482     return Artwork::isNormalChar() && ( cmChar == -1 );
00483 }
00484 
00485 double CMArtwork::slant() const
00486 {
00487     if ( getType() == Integral ) {
00488         return 0.25;
00489     }
00490     return 0;
00491 }
00492 
00493 bool CMArtwork::calcCMDelimiterSize( const ContextStyle& context,
00494                                      uchar c,
00495                                      luPt fontSize,
00496                                      luPt parentSize )
00497 {
00498     QFont f( "cmex10" );
00499     f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00500     QFontMetrics fm( f );
00501 
00502     for ( char i=1; c != 0; ++i ) {
00503         LuPixelRect bound = fm.boundingRect( c );
00504 
00505         luPt height = context.ptToLayoutUnitPt( bound.height() );
00506         if ( height >= parentSize ) {
00507             luPt width = context.ptToLayoutUnitPt( fm.width( c ) );
00508             luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00509 
00510             cmChar = c;
00511 
00512             setHeight( height );
00513             setWidth( width );
00514             setBaseline( baseline );
00515 
00516             return true;
00517         }
00518         c = cmex_nextchar( c );
00519     }
00520 
00521     // Build it up from pieces.
00522     return false;
00523 }
00524 
00525 
00526 void CMArtwork::calcLargest( const ContextStyle& context,
00527                              uchar c, luPt fontSize )
00528 {
00529     QFont f( "cmex10" );
00530     f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00531     QFontMetrics fm( f );
00532 
00533     cmChar = c;
00534     for ( ;; ) {
00535         c = cmex_nextchar( c );
00536         if ( c == 0 ) {
00537             break;
00538         }
00539         cmChar = c;
00540     }
00541 
00542     LuPixelRect bound = fm.boundingRect( cmChar );
00543 
00544     luPt height = context.ptToLayoutUnitPt( bound.height() );
00545     luPt width = context.ptToLayoutUnitPt( fm.width( cmChar ) );
00546     luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00547 
00548     setHeight( height );
00549     setWidth( width );
00550     setBaseline( baseline );
00551 }
00552 
00553 
00554 void CMArtwork::drawCMDelimiter( QPainter& painter, const ContextStyle& style,
00555                                  luPixel x, luPixel y,
00556                                  luPt height )
00557 {
00558     QFont f( "cmex10" );
00559     f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00560 
00561     painter.setFont( f );
00562     painter.drawText( style.layoutUnitToPixelX( x ),
00563                       style.layoutUnitToPixelY( y + getBaseline() ),
00564                       QString( QChar( cmChar ) ) );
00565 
00566     // Debug
00567 #if 0
00568     QFontMetrics fm( f );
00569     LuPixelRect bound = fm.boundingRect( cmChar );
00570     painter.setBrush(Qt::NoBrush);
00571     painter.setPen(Qt::green);
00572     painter.drawRect( style.layoutUnitToPixelX( x ),
00573                       style.layoutUnitToPixelY( y ),
00574                       fm.width( cmChar ),
00575                       bound.height() );
00576 #endif
00577 }
00578 
00579 
00580 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