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