F:/KPlato/koffice/libs/kformula/fontstyle.cc

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

Généré le Wed Nov 22 23:41:00 2006 pour KPlato par  doxygen 1.5.1-p1