lib

fontstyle.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., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <qpainter.h>
00021 #include <qpen.h>
00022 #include <qfontdatabase.h>
00023 
00024 #include "fontstyle.h"
00025 
00026 
00027 KFORMULA_NAMESPACE_BEGIN
00028 
00029 #include "unicodenames.cc"
00030 
00031 void FontStyle::fillNameTable( SymbolTable::NameTable& names )
00032 {
00033     for ( int i=0; nameTable[i].unicode != 0; ++i ) {
00034         names[QChar( nameTable[i].unicode )] = nameTable[i].name;
00035     }
00036 }
00037 
00038 static bool fontAvailable( const QString& fontName )
00039 {
00040 #if 0 // slloooww
00041     if ( QFontInfo( QFont( fontName ) ).family().lower() == fontName.lower() )
00042 #endif
00043     QFontDatabase db;
00044     if ( db.families().findIndex( fontName ) != -1 ) // ## TODO remove foundry from families list?
00045         return true;
00046     else {
00047         kdWarning(39001) << "Font '" << fontName << "' not found" << endl;
00048         return false;
00049     }
00050 }
00051 
00052 
00053 void FontStyle::testFont( QStringList& missing, const QString& fontName ) {
00054     if ( !fontAvailable( fontName ) ) {
00055         missing.append( fontName );
00056     }
00057 }
00058 
00059 
00060 
00061 // We claim that all chars come from the same font.
00062 // It's up to the font tables to ensure this.
00063 const QChar leftRoundBracket[] = {
00064     0xF8EB, // uppercorner
00065     0xF8ED, // lowercorner
00066     0xF8EC  // line
00067 };
00068 const QChar leftSquareBracket[] = {
00069     0xF8EE, // uppercorner
00070     0xF8F0, // lowercorner
00071     0xF8EF  // line
00072 };
00073 const QChar leftCurlyBracket[] = {
00074     0xF8F1, // uppercorner
00075     0xF8F3, // lowercorner
00076     0xF8F4, // line
00077     0xF8F2  // middle
00078 };
00079 
00080 const QChar leftLineBracket[] = {
00081     0xF8EF, // line
00082     0xF8EF, // line
00083     0xF8EF  // line
00084 };
00085 const QChar rightLineBracket[] = {
00086     0xF8FA, // line
00087     0xF8FA, // line
00088     0xF8FA  // line
00089 };
00090 
00091 const QChar rightRoundBracket[] = {
00092     0xF8F6, // uppercorner
00093     0xF8F8, // lowercorner
00094     0xF8F7  // line
00095 };
00096 const QChar rightSquareBracket[] = {
00097     0xF8F9, // uppercorner
00098     0xF8FB, // lowercorner
00099     0xF8FA  // line
00100 };
00101 const QChar rightCurlyBracket[] = {
00102     0xF8FC, // uppercorner
00103     0xF8FE, // lowercorner
00104     0xF8F4, // line
00105     0xF8FD  // middle
00106 };
00107 
00108 
00109 Artwork::Artwork(SymbolType t)
00110     : baseline( -1 ), type(t)
00111 {
00112 }
00113 
00114 
00115 void Artwork::calcSizes( const ContextStyle& style,
00116                          ContextStyle::TextStyle tstyle )
00117 {
00118     luPt mySize = style.getAdjustedSize( tstyle );
00119     switch (type) {
00120     case LeftSquareBracket:
00121         calcCharSize(style, mySize, leftSquareBracketChar);
00122         break;
00123     case RightSquareBracket:
00124         calcCharSize(style, mySize, rightSquareBracketChar);
00125         break;
00126     case LeftLineBracket:
00127     case RightLineBracket:
00128         calcCharSize(style, mySize, verticalLineChar);
00129         break;
00130     case SlashBracket:
00131         calcCharSize(style, mySize, slashChar);
00132         break;
00133     case BackSlashBracket:
00134         calcCharSize(style, mySize, backSlashChar);
00135         break;
00136     case LeftCornerBracket:
00137         calcCharSize(style, mySize, leftAngleBracketChar);
00138         break;
00139     case RightCornerBracket:
00140         calcCharSize(style, mySize, rightAngleBracketChar);
00141         break;
00142     case LeftRoundBracket:
00143         calcCharSize(style, mySize, leftParenthesisChar);
00144         break;
00145     case RightRoundBracket:
00146         calcCharSize(style, mySize, rightParenthesisChar);
00147         break;
00148     case EmptyBracket:
00149         //calcCharSize(style, mySize, spaceChar);
00150         setHeight(0);
00151         //setWidth(style.getEmptyRectWidth());
00152         setWidth(0);
00153         break;
00154     case LeftCurlyBracket:
00155         calcCharSize(style, mySize, leftCurlyBracketChar);
00156         break;
00157     case RightCurlyBracket:
00158         calcCharSize(style, mySize, rightCurlyBracketChar);
00159         break;
00160     case Integral:
00161     case Sum:
00162     case Product:
00163         break;
00164     }
00165 }
00166 
00167 
00168 void Artwork::draw(QPainter& painter, const LuPixelRect& /*r*/,
00169                    const ContextStyle& style, ContextStyle::TextStyle tstyle,
00170                    const LuPixelPoint& parentOrigin)
00171 {
00172     luPt mySize = style.getAdjustedSize( tstyle );
00173     luPixel myX = parentOrigin.x() + getX();
00174     luPixel myY = parentOrigin.y() + getY();
00175     /*
00176     if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00177         return;
00178     */
00179 
00180     painter.setPen(style.getDefaultColor());
00181 
00182     switch (type) {
00183     case LeftSquareBracket:
00184         drawCharacter(painter, style, myX, myY, mySize, leftSquareBracketChar);
00185         break;
00186     case RightSquareBracket:
00187         drawCharacter(painter, style, myX, myY, mySize, rightSquareBracketChar);
00188         break;
00189     case LeftCurlyBracket:
00190         drawCharacter(painter, style, myX, myY, mySize, leftCurlyBracketChar);
00191         break;
00192     case RightCurlyBracket:
00193         drawCharacter(painter, style, myX, myY, mySize, rightCurlyBracketChar);
00194         break;
00195     case LeftLineBracket:
00196     case RightLineBracket:
00197         drawCharacter(painter, style, myX, myY, mySize, verticalLineChar);
00198         break;
00199     case SlashBracket:
00200         drawCharacter(painter, style, myX, myY, mySize, slashChar);
00201         break;
00202     case BackSlashBracket:
00203         drawCharacter(painter, style, myX, myY, mySize, backSlashChar);
00204         break;
00205     case LeftCornerBracket:
00206         drawCharacter(painter, style, myX, myY, mySize, leftAngleBracketChar);
00207         break;
00208     case RightCornerBracket:
00209         drawCharacter(painter, style, myX, myY, mySize, rightAngleBracketChar);
00210         break;
00211     case LeftRoundBracket:
00212         drawCharacter(painter, style, myX, myY, mySize, leftParenthesisChar);
00213         break;
00214     case RightRoundBracket:
00215         drawCharacter(painter, style, myX, myY, mySize, rightParenthesisChar);
00216         break;
00217     case EmptyBracket:
00218         break;
00219     case Integral:
00220     case Sum:
00221     case Product:
00222         break;
00223     }
00224 }
00225 
00226 
00227 void Artwork::calcCharSize( const ContextStyle& style, luPt height, QChar ch )
00228 {
00229     //QFont f = style.getSymbolFont();
00230     uchar c = style.symbolTable().character( ch );
00231     QFont f = style.symbolTable().font( ch );
00232     calcCharSize( style, f, height, c );
00233 }
00234 
00235 
00236 void Artwork::drawCharacter( QPainter& painter, const ContextStyle& style,
00237                              luPixel x, luPixel y,
00238                              luPt height, QChar ch )
00239 {
00240     uchar c = style.symbolTable().character( ch );
00241     QFont f = style.symbolTable().font( ch );
00242     drawCharacter( painter, style, f, x, y, height, c );
00243 }
00244 
00245 
00246 void Artwork::calcCharSize( const ContextStyle& style, QFont f,
00247                             luPt height, uchar c )
00248 {
00249     f.setPointSizeFloat( style.layoutUnitPtToPt( height ) );
00250     //f.setPointSize( height );
00251     QFontMetrics fm(f);
00252     setWidth( style.ptToLayoutUnitPt( fm.width( c ) ) );
00253     LuPixelRect bound = fm.boundingRect( c );
00254     setHeight( style.ptToLayoutUnitPt( bound.height() ) );
00255     setBaseline( style.ptToLayoutUnitPt( -bound.top() ) );
00256 }
00257 
00258 
00259 void Artwork::drawCharacter( QPainter& painter, const ContextStyle& style,
00260                              QFont f,
00261                              luPixel x, luPixel y, luPt height, uchar c )
00262 {
00263     f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00264 
00265     painter.setFont( f );
00266     painter.drawText( style.layoutUnitToPixelX( x ),
00267                       style.layoutUnitToPixelY( y+getBaseline() ),
00268                       QString( QChar( c ) ) );
00269 }
00270 
00271 
00272 void Artwork::calcRoundBracket( const ContextStyle& style, const QChar chars[],
00273                                 luPt height, luPt charHeight )
00274 {
00275     uchar uppercorner = style.symbolTable().character( chars[0] );
00276     uchar lowercorner = style.symbolTable().character( chars[1] );
00277     //uchar line = style.symbolTable().character( chars[2] );
00278 
00279     QFont f = style.symbolTable().font( chars[0] );
00280     f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
00281     QFontMetrics fm( f );
00282     LuPtRect upperBound = fm.boundingRect( uppercorner );
00283     LuPtRect lowerBound = fm.boundingRect( lowercorner );
00284     //LuPtRect lineBound = fm.boundingRect( line );
00285 
00286     setWidth( style.ptToLayoutUnitPt( fm.width( QChar( uppercorner ) ) ) );
00287     luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+lowerBound.height() );
00288     //luPt lineHeight = style.ptToLayoutUnitPt( lineBound.height() );
00289 
00290     //setHeight( edgeHeight + ( ( height-edgeHeight-1 ) / lineHeight + 1 ) * lineHeight );
00291     setHeight( QMAX( edgeHeight, height ) );
00292 }
00293 
00294 void Artwork::drawBigRoundBracket( QPainter& p, const ContextStyle& style, const QChar chars[],
00295                                    luPixel x, luPixel y, luPt charHeight )
00296 {
00297     uchar uppercorner = style.symbolTable().character( chars[0] );
00298     uchar lowercorner = style.symbolTable().character( chars[1] );
00299     uchar line = style.symbolTable().character( chars[2] );
00300 
00301     QFont f = style.symbolTable().font( chars[0] );
00302     f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
00303     p.setFont(f);
00304 
00305     QFontMetrics fm(f);
00306     QRect upperBound = fm.boundingRect(uppercorner);
00307     QRect lowerBound = fm.boundingRect(lowercorner);
00308     QRect lineBound = fm.boundingRect(line);
00309 
00310     pixel ptX = style.layoutUnitToPixelX( x );
00311     pixel ptY = style.layoutUnitToPixelY( y );
00312     pixel height = style.layoutUnitToPixelY( getHeight() );
00313 
00314 //     p.setPen( Qt::red );
00315 //     //p.drawRect( ptX, ptY, upperBound.width(), upperBound.height() + lowerBound.height() );
00316 //     p.drawRect( ptX, ptY, style.layoutUnitToPixelX( getWidth() ),
00317 //                 style.layoutUnitToPixelY( getHeight() ) );
00318 
00319 //     p.setPen( Qt::black );
00320     p.drawText( ptX, ptY-upperBound.top(), QString( QChar( uppercorner ) ) );
00321     p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
00322                 QString( QChar( lowercorner ) ) );
00323 
00324     // for printing
00325     //pt safety = lineBound.height() / 10.0;
00326     pixel safety = 0;
00327 
00328     pixel gap = height - upperBound.height() - lowerBound.height();
00329     pixel lineHeight = lineBound.height() - safety;
00330     int lineCount = qRound( static_cast<double>( gap ) / lineHeight );
00331     pixel start = upperBound.height()-lineBound.top() - safety;
00332 
00333     for (int i = 0; i < lineCount; i++) {
00334         p.drawText( ptX, ptY+start+i*lineHeight, QString(QChar(line)));
00335     }
00336     pixel remaining = gap - lineCount*lineHeight;
00337     pixel dist = ( lineHeight - remaining ) / 2;
00338     p.drawText( ptX, ptY+height-upperBound.height()+dist-lineBound.height()-lineBound.top(),
00339                 QString( QChar( line ) ) );
00340 }
00341 
00342 void Artwork::calcCurlyBracket( const ContextStyle& style, const QChar chars[],
00343                                 luPt height, luPt charHeight )
00344 {
00345     uchar uppercorner = style.symbolTable().character( chars[0] );
00346     uchar lowercorner = style.symbolTable().character( chars[1] );
00347     //uchar line = style.symbolTable().character( chars[2] );
00348     uchar middle = style.symbolTable().character( chars[3] );
00349 
00350     QFont f = style.symbolTable().font( chars[0] );
00351     f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
00352     QFontMetrics fm( f );
00353     LuPtRect upperBound = fm.boundingRect( uppercorner );
00354     LuPtRect lowerBound = fm.boundingRect( lowercorner );
00355     //LuPtRect lineBound = fm.boundingRect( line );
00356     LuPtRect middleBound = fm.boundingRect( middle );
00357 
00358     setWidth( style.ptToLayoutUnitPt( fm.width( QChar( uppercorner ) ) ) );
00359     luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+
00360                                               lowerBound.height()+
00361                                               middleBound.height() );
00362     //luPt lineHeight = style.ptToLayoutUnitPt( lineBound.height() );
00363 
00364     //setHeight( edgeHeight + ( ( height-edgeHeight-1 ) / lineHeight + 1 ) * lineHeight );
00365     setHeight( QMAX( edgeHeight, height ) );
00366 }
00367 
00368 void Artwork::drawBigCurlyBracket( QPainter& p, const ContextStyle& style, const QChar chars[],
00369                                    luPixel x, luPixel y, luPt charHeight )
00370 {
00371     //QFont f = style.getSymbolFont();
00372     QFont f = style.symbolTable().font( chars[0] );
00373     f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
00374     p.setFont(f);
00375 
00376     uchar uppercorner = style.symbolTable().character( chars[0] );
00377     uchar lowercorner = style.symbolTable().character( chars[1] );
00378     uchar line = style.symbolTable().character( chars[2] );
00379     uchar middle = style.symbolTable().character( chars[3] );
00380 
00381     QFontMetrics fm(p.fontMetrics());
00382     QRect upperBound = fm.boundingRect(uppercorner);
00383     QRect lowerBound = fm.boundingRect(lowercorner);
00384     QRect middleBound = fm.boundingRect(middle);
00385     QRect lineBound = fm.boundingRect(line);
00386 
00387     pixel ptX = style.layoutUnitToPixelX( x );
00388     pixel ptY = style.layoutUnitToPixelY( y );
00389     pixel height = style.layoutUnitToPixelY( getHeight() );
00390 
00391     //p.setPen(Qt::gray);
00392     //p.drawRect(x, y, upperBound.width() + offset, height);
00393 
00394     p.drawText( ptX, ptY-upperBound.top(), QString( QChar( uppercorner ) ) );
00395     p.drawText( ptX, ptY+(height-middleBound.height())/2-middleBound.top(),
00396                 QString( QChar( middle ) ) );
00397     p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
00398                 QString( QChar( lowercorner ) ) );
00399 
00400     // for printing
00401     // If the world was perfect and the urw-symbol font correct
00402     // this could be 0.
00403     //lu safety = lineBound.height() / 10;
00404     pixel safety = 0;
00405 
00406     pixel lineHeight = lineBound.height() - safety;
00407     pixel gap = height/2 - upperBound.height() - middleBound.height() / 2;
00408 
00409     if (gap > 0) {
00410         QString ch = QString(QChar(line));
00411         int lineCount = qRound( gap / lineHeight ) + 1;
00412 
00413         pixel start = (height - middleBound.height()) / 2 + safety;
00414         for (int i = 0; i < lineCount; i++) {
00415             p.drawText( ptX, ptY-lineBound.top()+QMAX( start-(i+1)*lineHeight,
00416                                                        upperBound.width() ),
00417                         ch );
00418         }
00419 
00420         start = (height + middleBound.height()) / 2 - safety;
00421         for (int i = 0; i < lineCount; i++) {
00422             p.drawText( ptX, ptY-lineBound.top()+QMIN( start+i*lineHeight,
00423                                                        height-upperBound.width()-lineBound.height() ),
00424                         ch );
00425         }
00426     }
00427 }
00428 
00429 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys