00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
00083
00084 const QChar leftRoundBracket[] = {
00085 0xF8EB,
00086 0xF8ED,
00087 0xF8EC
00088 };
00089 const QChar leftSquareBracket[] = {
00090 0xF8EE,
00091 0xF8F0,
00092 0xF8EF
00093 };
00094 const QChar leftCurlyBracket[] = {
00095 0xF8F1,
00096 0xF8F3,
00097 0xF8F4,
00098 0xF8F2
00099 };
00100
00101 const QChar leftLineBracket[] = {
00102 0xF8EF,
00103 0xF8EF,
00104 0xF8EF
00105 };
00106 const QChar rightLineBracket[] = {
00107 0xF8FA,
00108 0xF8FA,
00109 0xF8FA
00110 };
00111
00112 const QChar rightRoundBracket[] = {
00113 0xF8F6,
00114 0xF8F8,
00115 0xF8F7
00116 };
00117 const QChar rightSquareBracket[] = {
00118 0xF8F9,
00119 0xF8FB,
00120 0xF8FA
00121 };
00122 const QChar rightCurlyBracket[] = {
00123 0xF8FC,
00124 0xF8FE,
00125 0xF8F4,
00126 0xF8FD
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
00171 setHeight(0);
00172
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& ,
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
00198
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
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
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
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
00305
00306 setWidth( style.ptToLayoutUnitPt( fm.width( uppercorner ) ) );
00307 luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+lowerBound.height() );
00308
00309
00310
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
00335
00336
00337
00338
00339
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
00345
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
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
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
00383
00384
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
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
00412
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
00421
00422
00423
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