lib Library API Documentation

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., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, 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     if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00176         return;
00177 
00178     painter.setPen(style.getDefaultColor());
00179 
00180     switch (type) {
00181     case LeftSquareBracket:
00182         drawCharacter(painter, style, myX, myY, mySize, leftSquareBracketChar);
00183         break;
00184     case RightSquareBracket:
00185         drawCharacter(painter, style, myX, myY, mySize, rightSquareBracketChar);
00186         break;
00187     case LeftCurlyBracket:
00188         drawCharacter(painter, style, myX, myY, mySize, leftCurlyBracketChar);
00189         break;
00190     case RightCurlyBracket:
00191         drawCharacter(painter, style, myX, myY, mySize, rightCurlyBracketChar);
00192         break;
00193     case LeftLineBracket:
00194     case RightLineBracket:
00195         drawCharacter(painter, style, myX, myY, mySize, verticalLineChar);
00196         break;
00197     case SlashBracket:
00198         drawCharacter(painter, style, myX, myY, mySize, slashChar);
00199         break;
00200     case BackSlashBracket:
00201         drawCharacter(painter, style, myX, myY, mySize, backSlashChar);
00202         break;
00203     case LeftCornerBracket:
00204         drawCharacter(painter, style, myX, myY, mySize, leftAngleBracketChar);
00205         break;
00206     case RightCornerBracket:
00207         drawCharacter(painter, style, myX, myY, mySize, rightAngleBracketChar);
00208         break;
00209     case LeftRoundBracket:
00210         drawCharacter(painter, style, myX, myY, mySize, leftParenthesisChar);
00211         break;
00212     case RightRoundBracket:
00213         drawCharacter(painter, style, myX, myY, mySize, rightParenthesisChar);
00214         break;
00215     case EmptyBracket:
00216         break;
00217     case Integral:
00218     case Sum:
00219     case Product:
00220         break;
00221     }
00222 }
00223 
00224 
00225 void Artwork::calcCharSize( const ContextStyle& style, luPt height, QChar ch )
00226 {
00227     //QFont f = style.getSymbolFont();
00228     uchar c = style.symbolTable().character( ch );
00229     QFont f = style.symbolTable().font( ch );
00230     calcCharSize( style, f, height, c );
00231 }
00232 
00233 
00234 void Artwork::drawCharacter( QPainter& painter, const ContextStyle& style,
00235                              luPixel x, luPixel y,
00236                              luPt height, QChar ch )
00237 {
00238     uchar c = style.symbolTable().character( ch );
00239     QFont f = style.symbolTable().font( ch );
00240     drawCharacter( painter, style, f, x, y, height, c );
00241 }
00242 
00243 
00244 void Artwork::calcCharSize( const ContextStyle& style, QFont f,
00245                             luPt height, uchar c )
00246 {
00247     f.setPointSizeFloat( style.layoutUnitPtToPt( height ) );
00248     //f.setPointSize( height );
00249     QFontMetrics fm(f);
00250     setWidth( style.ptToLayoutUnitPt( fm.width( c ) ) );
00251     LuPixelRect bound = fm.boundingRect( c );
00252     setHeight( style.ptToLayoutUnitPt( bound.height() ) );
00253     setBaseline( style.ptToLayoutUnitPt( -bound.top() ) );
00254 }
00255 
00256 
00257 void Artwork::drawCharacter( QPainter& painter, const ContextStyle& style,
00258                              QFont f,
00259                              luPixel x, luPixel y, luPt height, uchar c )
00260 {
00261     f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00262 
00263     painter.setFont( f );
00264     painter.drawText( style.layoutUnitToPixelX( x ),
00265                       style.layoutUnitToPixelY( y+getBaseline() ),
00266                       QString( QChar( c ) ) );
00267 }
00268 
00269 
00270 void Artwork::calcRoundBracket( const ContextStyle& style, const QChar chars[],
00271                                 luPt height, luPt charHeight )
00272 {
00273     uchar uppercorner = style.symbolTable().character( chars[0] );
00274     uchar lowercorner = style.symbolTable().character( chars[1] );
00275     //uchar line = style.symbolTable().character( chars[2] );
00276 
00277     QFont f = style.symbolTable().font( chars[0] );
00278     f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
00279     QFontMetrics fm( f );
00280     LuPtRect upperBound = fm.boundingRect( uppercorner );
00281     LuPtRect lowerBound = fm.boundingRect( lowercorner );
00282     //LuPtRect lineBound = fm.boundingRect( line );
00283 
00284     setWidth( style.ptToLayoutUnitPt( fm.width( QChar( uppercorner ) ) ) );
00285     luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+lowerBound.height() );
00286     //luPt lineHeight = style.ptToLayoutUnitPt( lineBound.height() );
00287 
00288     //setHeight( edgeHeight + ( ( height-edgeHeight-1 ) / lineHeight + 1 ) * lineHeight );
00289     setHeight( QMAX( edgeHeight, height ) );
00290 }
00291 
00292 void Artwork::drawBigRoundBracket( QPainter& p, const ContextStyle& style, const QChar chars[],
00293                                    luPixel x, luPixel y, luPt charHeight )
00294 {
00295     uchar uppercorner = style.symbolTable().character( chars[0] );
00296     uchar lowercorner = style.symbolTable().character( chars[1] );
00297     uchar line = style.symbolTable().character( chars[2] );
00298 
00299     QFont f = style.symbolTable().font( chars[0] );
00300     f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
00301     p.setFont(f);
00302 
00303     QFontMetrics fm(f);
00304     QRect upperBound = fm.boundingRect(uppercorner);
00305     QRect lowerBound = fm.boundingRect(lowercorner);
00306     QRect lineBound = fm.boundingRect(line);
00307 
00308     pixel ptX = style.layoutUnitToPixelX( x );
00309     pixel ptY = style.layoutUnitToPixelY( y );
00310     pixel height = style.layoutUnitToPixelY( getHeight() );
00311 
00312 //     p.setPen( Qt::red );
00313 //     //p.drawRect( ptX, ptY, upperBound.width(), upperBound.height() + lowerBound.height() );
00314 //     p.drawRect( ptX, ptY, style.layoutUnitToPixelX( getWidth() ),
00315 //                 style.layoutUnitToPixelY( getHeight() ) );
00316 
00317 //     p.setPen( Qt::black );
00318     p.drawText( ptX, ptY-upperBound.top(), QString( QChar( uppercorner ) ) );
00319     p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
00320                 QString( QChar( lowercorner ) ) );
00321 
00322     // for printing
00323     //pt safety = lineBound.height() / 10.0;
00324     pixel safety = 0;
00325 
00326     pixel gap = height - upperBound.height() - lowerBound.height();
00327     pixel lineHeight = lineBound.height() - safety;
00328     int lineCount = qRound( static_cast<double>( gap ) / lineHeight );
00329     pixel start = upperBound.height()-lineBound.top() - safety;
00330 
00331     for (int i = 0; i < lineCount; i++) {
00332         p.drawText( ptX, ptY+start+i*lineHeight, QString(QChar(line)));
00333     }
00334     pixel remaining = gap - lineCount*lineHeight;
00335     pixel dist = ( lineHeight - remaining ) / 2;
00336     p.drawText( ptX, ptY+height-upperBound.height()+dist-lineBound.height()-lineBound.top(),
00337                 QString( QChar( line ) ) );
00338 }
00339 
00340 void Artwork::calcCurlyBracket( const ContextStyle& style, const QChar chars[],
00341                                 luPt height, luPt charHeight )
00342 {
00343     uchar uppercorner = style.symbolTable().character( chars[0] );
00344     uchar lowercorner = style.symbolTable().character( chars[1] );
00345     //uchar line = style.symbolTable().character( chars[2] );
00346     uchar middle = style.symbolTable().character( chars[3] );
00347 
00348     QFont f = style.symbolTable().font( chars[0] );
00349     f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
00350     QFontMetrics fm( f );
00351     LuPtRect upperBound = fm.boundingRect( uppercorner );
00352     LuPtRect lowerBound = fm.boundingRect( lowercorner );
00353     //LuPtRect lineBound = fm.boundingRect( line );
00354     LuPtRect middleBound = fm.boundingRect( middle );
00355 
00356     setWidth( style.ptToLayoutUnitPt( fm.width( QChar( uppercorner ) ) ) );
00357     luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+
00358                                               lowerBound.height()+
00359                                               middleBound.height() );
00360     //luPt lineHeight = style.ptToLayoutUnitPt( lineBound.height() );
00361 
00362     //setHeight( edgeHeight + ( ( height-edgeHeight-1 ) / lineHeight + 1 ) * lineHeight );
00363     setHeight( QMAX( edgeHeight, height ) );
00364 }
00365 
00366 void Artwork::drawBigCurlyBracket( QPainter& p, const ContextStyle& style, const QChar chars[],
00367                                    luPixel x, luPixel y, luPt charHeight )
00368 {
00369     //QFont f = style.getSymbolFont();
00370     QFont f = style.symbolTable().font( chars[0] );
00371     f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
00372     p.setFont(f);
00373 
00374     uchar uppercorner = style.symbolTable().character( chars[0] );
00375     uchar lowercorner = style.symbolTable().character( chars[1] );
00376     uchar line = style.symbolTable().character( chars[2] );
00377     uchar middle = style.symbolTable().character( chars[3] );
00378 
00379     QFontMetrics fm(p.fontMetrics());
00380     QRect upperBound = fm.boundingRect(uppercorner);
00381     QRect lowerBound = fm.boundingRect(lowercorner);
00382     QRect middleBound = fm.boundingRect(middle);
00383     QRect lineBound = fm.boundingRect(line);
00384 
00385     pixel ptX = style.layoutUnitToPixelX( x );
00386     pixel ptY = style.layoutUnitToPixelY( y );
00387     pixel height = style.layoutUnitToPixelY( getHeight() );
00388 
00389     //p.setPen(Qt::gray);
00390     //p.drawRect(x, y, upperBound.width() + offset, height);
00391 
00392     p.drawText( ptX, ptY-upperBound.top(), QString( QChar( uppercorner ) ) );
00393     p.drawText( ptX, ptY+(height-middleBound.height())/2-middleBound.top(),
00394                 QString( QChar( middle ) ) );
00395     p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
00396                 QString( QChar( lowercorner ) ) );
00397 
00398     // for printing
00399     // If the world was perfect and the urw-symbol font correct
00400     // this could be 0.
00401     //lu safety = lineBound.height() / 10;
00402     pixel safety = 0;
00403 
00404     pixel lineHeight = lineBound.height() - safety;
00405     pixel gap = height/2 - upperBound.height() - middleBound.height() / 2;
00406 
00407     if (gap > 0) {
00408         QString ch = QString(QChar(line));
00409         int lineCount = qRound( gap / lineHeight ) + 1;
00410 
00411         pixel start = (height - middleBound.height()) / 2 + safety;
00412         for (int i = 0; i < lineCount; i++) {
00413             p.drawText( ptX, ptY-lineBound.top()+QMAX( start-(i+1)*lineHeight,
00414                                                        upperBound.width() ),
00415                         ch );
00416         }
00417 
00418         start = (height + middleBound.height()) / 2 - safety;
00419         for (int i = 0; i < lineCount; i++) {
00420             p.drawText( ptX, ptY-lineBound.top()+QMIN( start+i*lineHeight,
00421                                                        height-upperBound.width()-lineBound.height() ),
00422                         ch );
00423         }
00424     }
00425 }
00426 
00427 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:56 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003