00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qpainter.h>
00022 #include <qpen.h>
00023 #include <qfontdatabase.h>
00024 #include <qapplication.h>
00025
00026 #include <kstaticdeleter.h>
00027 #include <klocale.h>
00028 #include <kstandarddirs.h>
00029 #include <kio/netaccess.h>
00030 #include <kio/job.h>
00031 #include <kmessagebox.h>
00032
00033 #include "fontstyle.h"
00034
00035
00036 KFORMULA_NAMESPACE_BEGIN
00037
00038 #include "unicodetable.cc"
00039
00040 bool FontStyle::m_installed = false;
00041
00042 bool FontStyle::init( ContextStyle* style, bool install )
00043 {
00044 if (!m_installed && install)
00045 installFonts();
00046 m_symbolTable.init( style->getMathFont() );
00047
00048 return true;
00049 }
00050
00051
00052 class FontList {
00053 public:
00054 FontList() {
00055 QFontDatabase db;
00056 const QStringList lst = db.families();
00057 for ( QStringList::const_iterator it = lst.begin(), end = lst.end() ; it != end ; ++it ) {
00058 const QString name = *it;
00059 int i = name.find('[');
00060 QString family = name;
00061
00062 if ( i > -1 ) {
00063 const int li = name.findRev(']');
00064 if (i < li) {
00065 if (name[i - 1] == ' ')
00066 i--;
00067 family = name.left(i);
00068 }
00069 }
00070 m_fontNames.append( family.lower() );
00071 }
00072 }
00073 bool hasFont( const QString& fontName ) const {
00074 return m_fontNames.find( fontName ) != m_fontNames.end();
00075 }
00076 QStringList m_fontNames;
00077 };
00078 static FontList* s_fontList = 0;
00079 static KStaticDeleter<FontList> s_fontList_sd;
00080
00081 void FontStyle::testFont( QStringList& missing, const QString& fontName ) {
00082 if ( !s_fontList )
00083 s_fontList_sd.setObject( s_fontList, new FontList() );
00084 if ( !s_fontList->hasFont( fontName ) ) {
00085 kdWarning(39001) << "Font '" << fontName << "' not found" << endl;
00086 missing.append( fontName );
00087 }
00088 }
00089
00090
00091 QStringList FontStyle::missingFonts( bool install )
00092 {
00093 if (!m_installed && install)
00094 installFonts();
00095
00096 QStringList missing = missingFontsInternal();
00097 return missing;
00098 }
00099
00100 QStringList FontStyle::missingFontsInternal()
00101 {
00102 QStringList missing;
00103
00104 testFont( missing, "cmex10" );
00105 testFont( missing, "arev sans");
00106
00107 return missing;
00108 }
00109
00110 void FontStyle::installFonts()
00111 {
00112 if (m_installed)
00113 return;
00114 QStringList missing = missingFontsInternal();
00115 if (!missing.isEmpty())
00116 {
00117 QStringList urlList;
00118 for (QStringList::iterator it = missing.begin(); it != missing.end(); ++it)
00119 {
00120 if ( *it == "arev sans" ) {
00121 if (!KIO::NetAccess::exists("fonts:/Personal/Arev.ttf", true, NULL))
00122 urlList.append(locate("data", "kformula/fonts/Arev.ttf"));
00123 if (!KIO::NetAccess::exists("fonts:/Personal/ArevIt.ttf", true, NULL))
00124 urlList.append(locate("data", "kformula/fonts/ArevIt.ttf"));
00125 if (!KIO::NetAccess::exists("fonts:/Personal/ArevBd.ttf", true, NULL))
00126 urlList.append(locate("data", "kformula/fonts/ArevBd.ttf"));
00127 if (!KIO::NetAccess::exists("fonts:/Personal/ArevBI.ttf", true, NULL))
00128 urlList.append(locate("data", "kformula/fonts/ArevBI.ttf"));
00129 }
00130 else {
00131 if (!KIO::NetAccess::exists("fonts:/Personal/" + *it + ".ttf", true, NULL))
00132 urlList.append(locate("data", "kformula/fonts/" + *it + ".ttf"));
00133 }
00134 }
00135 KIO::copy(urlList, "fonts:/Personal/", false);
00136 KMessageBox::information(qApp->mainWidget(),
00137 i18n("Some fonts have been installed to assure that symbols in formulas are properly visualized. You must restart the application in order so that changes take effect"));
00138 }
00139 m_installed = true;
00140 }
00141
00142 Artwork* FontStyle::createArtwork( SymbolType type ) const
00143 {
00144 return new Artwork( type );
00145 }
00146
00147
00148
00149 const QChar leftRoundBracket[] = {
00150 0x30,
00151 0x40,
00152 0x42
00153 };
00154 const QChar leftSquareBracket[] = {
00155 0x32,
00156 0x34,
00157 0x36
00158 };
00159 const QChar leftCurlyBracket[] = {
00160 0x38,
00161 0x3A,
00162 0x3E,
00163 0x3C
00164 };
00165
00166 const QChar leftLineBracket[] = {
00167 0x36,
00168 0x36,
00169 0x36
00170 };
00171 const QChar rightLineBracket[] = {
00172 0x37,
00173 0x37,
00174 0x37
00175 };
00176
00177 const QChar rightRoundBracket[] = {
00178 0x31,
00179 0x41,
00180 0x43
00181 };
00182 const QChar rightSquareBracket[] = {
00183 0x33,
00184 0x35,
00185 0x37
00186 };
00187 const QChar rightCurlyBracket[] = {
00188 0x39,
00189 0x3B,
00190 0x3E,
00191 0x3D
00192 };
00193
00194
00195 static const char cmex_LeftSquareBracket = 163;
00196 static const char cmex_RightSquareBracket = 164;
00197 static const char cmex_LeftCurlyBracket = 169;
00198 static const char cmex_RightCurlyBracket = 170;
00199 static const char cmex_LeftCornerBracket = 173;
00200 static const char cmex_RightCornerBracket = 174;
00201 static const char cmex_LeftRoundBracket = 161;
00202 static const char cmex_RightRoundBracket = 162;
00203 static const char cmex_SlashBracket = 177;
00204 static const char cmex_BackSlashBracket = 178;
00205
00206
00207
00208
00209 static const char cmex_Int = 90;
00210 static const char cmex_Sum = 88;
00211 static const char cmex_Prod = 89;
00212
00213
00214
00215 static short cmex_nextchar( short ch )
00216 {
00217 switch ( ch ) {
00218 case 161: return 179;
00219 case 162: return 180;
00220 case 163: return 104;
00221 case 164: return 105;
00222 case 169: return 110;
00223 case 170: return 111;
00224 case 165: return 106;
00225 case 166: return 107;
00226 case 167: return 108;
00227 case 168: return 109;
00228 case 173: return 68;
00229 case 174: return 69;
00230 case 177: return 46;
00231 case 178: return 47;
00232
00233 case 179: return 181;
00234 case 180: return 182;
00235 case 104: return 183;
00236 case 105: return 184;
00237 case 110: return 189;
00238 case 111: return 190;
00239 case 106: return 185;
00240 case 107: return 186;
00241 case 108: return 187;
00242 case 109: return 188;
00243 case 68: return 191;
00244 case 69: return 192;
00245 case 46: return 193;
00246 case 47: return 194;
00247
00248 case 181: return 195;
00249 case 182: return 33;
00250 case 183: return 34;
00251 case 184: return 35;
00252 case 189: return 40;
00253 case 190: return 41;
00254 case 185: return 36;
00255 case 186: return 37;
00256 case 187: return 38;
00257 case 188: return 39;
00258 case 191: return 42;
00259 case 192: return 43;
00260 case 193: return 44;
00261 case 194: return 45;
00262 }
00263 return 0;
00264 }
00265
00266 bool Artwork::calcCMDelimiterSize( const ContextStyle& context,
00267 uchar c,
00268 luPt fontSize,
00269 luPt parentSize )
00270 {
00271 QFont f( "cmex10" );
00272 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00273 QFontMetrics fm( f );
00274
00275 for ( char i=1; c != 0; ++i ) {
00276 LuPixelRect bound = fm.boundingRect( c );
00277
00278 luPt height = context.ptToLayoutUnitPt( bound.height() );
00279 if ( height >= parentSize ) {
00280 luPt width = context.ptToLayoutUnitPt( fm.width( c ) );
00281 luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00282
00283 cmChar = c;
00284
00285 setHeight( height );
00286 setWidth( width );
00287 setBaseline( baseline );
00288
00289 return true;
00290 }
00291 c = cmex_nextchar( c );
00292 }
00293
00294
00295 return false;
00296 }
00297
00298
00299 void Artwork::calcLargest( const ContextStyle& context,
00300 uchar c, luPt fontSize )
00301 {
00302 QFont f( "cmex10" );
00303 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00304 QFontMetrics fm( f );
00305
00306 cmChar = c;
00307 for ( ;; ) {
00308 c = cmex_nextchar( c );
00309 if ( c == 0 ) {
00310 break;
00311 }
00312 cmChar = c;
00313 }
00314
00315 LuPixelRect bound = fm.boundingRect( cmChar );
00316
00317 luPt height = context.ptToLayoutUnitPt( bound.height() );
00318 luPt width = context.ptToLayoutUnitPt( fm.width( cmChar ) );
00319 luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00320
00321 setHeight( height );
00322 setWidth( width );
00323 setBaseline( baseline );
00324 }
00325
00326
00327 void Artwork::drawCMDelimiter( QPainter& painter, const ContextStyle& style,
00328 luPixel x, luPixel y,
00329 luPt height )
00330 {
00331 QFont f( "cmex10" );
00332 f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00333
00334 painter.setFont( f );
00335 painter.drawText( style.layoutUnitToPixelX( x ),
00336 style.layoutUnitToPixelY( y + getBaseline() ),
00337 QString( QChar( cmChar ) ) );
00338
00339
00340 #if 0
00341 QFontMetrics fm( f );
00342 LuPixelRect bound = fm.boundingRect( cmChar );
00343 painter.setBrush(Qt::NoBrush);
00344 painter.setPen(Qt::green);
00345 painter.drawRect( style.layoutUnitToPixelX( x ),
00346 style.layoutUnitToPixelY( y ),
00347 fm.width( cmChar ),
00348 bound.height() );
00349 #endif
00350 }
00351
00352
00353 Artwork::Artwork(SymbolType t)
00354 : baseline( -1 ), type(t)
00355 {
00356 }
00357
00358
00359 void Artwork::calcSizes( const ContextStyle& style,
00360 ContextStyle::TextStyle tstyle,
00361 double factor,
00362 luPt parentSize )
00363 {
00364 setBaseline( -1 );
00365 cmChar = -1;
00366 luPt mySize = style.getAdjustedSize( tstyle, factor );
00367 switch (getType()) {
00368 case LeftSquareBracket:
00369 if ( calcCMDelimiterSize( style, cmex_LeftSquareBracket,
00370 mySize, parentSize ) ) {
00371 return;
00372 }
00373 calcRoundBracket( style, leftSquareBracket, parentSize, mySize );
00374 break;
00375 case RightSquareBracket:
00376 if ( calcCMDelimiterSize( style, cmex_RightSquareBracket,
00377 mySize, parentSize ) ) {
00378 return;
00379 }
00380 calcRoundBracket( style, rightSquareBracket, parentSize, mySize );
00381 break;
00382 case LeftLineBracket:
00383 calcRoundBracket( style, leftLineBracket, parentSize, mySize );
00384 setWidth( getWidth()/2 );
00385 break;
00386 case RightLineBracket:
00387 calcRoundBracket( style, rightLineBracket, parentSize, mySize );
00388 setWidth( getWidth()/2 );
00389 break;
00390 case SlashBracket:
00391 if ( calcCMDelimiterSize( style, cmex_SlashBracket,
00392 mySize, parentSize ) ) {
00393 return;
00394 }
00395 calcLargest( style, cmex_SlashBracket, mySize );
00396 break;
00397 case BackSlashBracket:
00398 if ( calcCMDelimiterSize( style, cmex_BackSlashBracket,
00399 mySize, parentSize ) ) {
00400 return;
00401 }
00402 calcLargest( style, cmex_BackSlashBracket, mySize );
00403 break;
00404 case LeftCornerBracket:
00405 if ( calcCMDelimiterSize( style, cmex_LeftCornerBracket,
00406 mySize, parentSize ) ) {
00407 return;
00408 }
00409 calcLargest( style, cmex_LeftCornerBracket, mySize );
00410 break;
00411 case RightCornerBracket:
00412 if ( calcCMDelimiterSize( style, cmex_RightCornerBracket,
00413 mySize, parentSize ) ) {
00414 return;
00415 }
00416 calcLargest( style, cmex_RightCornerBracket, mySize );
00417 break;
00418 case LeftRoundBracket:
00419 if ( calcCMDelimiterSize( style, cmex_LeftRoundBracket,
00420 mySize, parentSize ) ) {
00421 return;
00422 }
00423 calcRoundBracket( style, leftRoundBracket, parentSize, mySize );
00424 break;
00425 case RightRoundBracket:
00426 if ( calcCMDelimiterSize( style, cmex_RightRoundBracket,
00427 mySize, parentSize ) ) {
00428 return;
00429 }
00430 calcRoundBracket( style, rightRoundBracket, parentSize, mySize );
00431 break;
00432 case EmptyBracket:
00433 setHeight(parentSize);
00434
00435 setWidth(0);
00436 break;
00437 case LeftCurlyBracket:
00438 if ( calcCMDelimiterSize( style, cmex_LeftCurlyBracket,
00439 mySize, parentSize ) ) {
00440 return;
00441 }
00442 calcCurlyBracket( style, leftCurlyBracket, parentSize, mySize );
00443 break;
00444 case RightCurlyBracket:
00445 if ( calcCMDelimiterSize( style, cmex_RightCurlyBracket,
00446 mySize, parentSize ) ) {
00447 return;
00448 }
00449 calcCurlyBracket( style, rightCurlyBracket, parentSize, mySize );
00450 break;
00451 case Integral:
00452 calcCharSize( style, style.getBracketFont(), mySize, cmex_Int );
00453 break;
00454 case Sum:
00455 calcCharSize( style, style.getBracketFont(), mySize, cmex_Sum );
00456 break;
00457 case Product:
00458 calcCharSize( style, style.getBracketFont(), mySize, cmex_Prod );
00459 break;
00460 }
00461 }
00462
00463 void Artwork::calcSizes( const ContextStyle& style,
00464 ContextStyle::TextStyle tstyle,
00465 double factor )
00466 {
00467 luPt mySize = style.getAdjustedSize( tstyle, factor );
00468 switch (type) {
00469 case LeftSquareBracket:
00470 calcCharSize(style, mySize, leftSquareBracketChar);
00471 break;
00472 case RightSquareBracket:
00473 calcCharSize(style, mySize, rightSquareBracketChar);
00474 break;
00475 case LeftLineBracket:
00476 case RightLineBracket:
00477 calcCharSize(style, mySize, verticalLineChar);
00478 break;
00479 case SlashBracket:
00480 calcCharSize(style, mySize, slashChar);
00481 break;
00482 case BackSlashBracket:
00483 calcCharSize(style, mySize, backSlashChar);
00484 break;
00485 case LeftCornerBracket:
00486 calcCharSize(style, mySize, leftAngleBracketChar);
00487 break;
00488 case RightCornerBracket:
00489 calcCharSize(style, mySize, rightAngleBracketChar);
00490 break;
00491 case LeftRoundBracket:
00492 calcCharSize(style, mySize, leftParenthesisChar);
00493 break;
00494 case RightRoundBracket:
00495 calcCharSize(style, mySize, rightParenthesisChar);
00496 break;
00497 case EmptyBracket:
00498
00499 setHeight(0);
00500
00501 setWidth(0);
00502 break;
00503 case LeftCurlyBracket:
00504 calcCharSize(style, mySize, leftCurlyBracketChar);
00505 break;
00506 case RightCurlyBracket:
00507 calcCharSize(style, mySize, rightCurlyBracketChar);
00508 break;
00509 case Integral:
00510 case Sum:
00511 case Product:
00512 break;
00513 }
00514 }
00515
00516
00517 void Artwork::draw(QPainter& painter, const LuPixelRect& ,
00518 const ContextStyle& context, ContextStyle::TextStyle tstyle,
00519 StyleAttributes& style, const LuPixelPoint& parentOrigin)
00520 {
00521 luPt mySize = context.getAdjustedSize( tstyle, style.sizeFactor() );
00522 luPixel myX = parentOrigin.x() + getX();
00523 luPixel myY = parentOrigin.y() + getY();
00524
00525
00526
00527
00528
00529 painter.setPen(context.getDefaultColor());
00530
00531 switch (type) {
00532 case LeftSquareBracket:
00533 drawCharacter(painter, context, myX, myY, mySize, leftSquareBracketChar);
00534 break;
00535 case RightSquareBracket:
00536 drawCharacter(painter, context, myX, myY, mySize, rightSquareBracketChar);
00537 break;
00538 case LeftCurlyBracket:
00539 drawCharacter(painter, context, myX, myY, mySize, leftCurlyBracketChar);
00540 break;
00541 case RightCurlyBracket:
00542 drawCharacter(painter, context, myX, myY, mySize, rightCurlyBracketChar);
00543 break;
00544 case LeftLineBracket:
00545 case RightLineBracket:
00546 drawCharacter(painter, context, myX, myY, mySize, verticalLineChar);
00547 break;
00548 case SlashBracket:
00549 drawCharacter(painter, context, myX, myY, mySize, slashChar);
00550 break;
00551 case BackSlashBracket:
00552 drawCharacter(painter, context, myX, myY, mySize, backSlashChar);
00553 break;
00554 case LeftCornerBracket:
00555 drawCharacter(painter, context, myX, myY, mySize, leftAngleBracketChar);
00556 break;
00557 case RightCornerBracket:
00558 drawCharacter(painter, context, myX, myY, mySize, rightAngleBracketChar);
00559 break;
00560 case LeftRoundBracket:
00561 drawCharacter(painter, context, myX, myY, mySize, leftParenthesisChar);
00562 break;
00563 case RightRoundBracket:
00564 drawCharacter(painter, context, myX, myY, mySize, rightParenthesisChar);
00565 break;
00566 case EmptyBracket:
00567 break;
00568 case Integral:
00569 case Sum:
00570 case Product:
00571 break;
00572 }
00573 }
00574
00575 void Artwork::draw(QPainter& painter, const LuPixelRect& ,
00576 const ContextStyle& context, ContextStyle::TextStyle tstyle,
00577 StyleAttributes& style, luPt , const LuPixelPoint& origin)
00578 {
00579 luPt mySize = context.getAdjustedSize( tstyle, style.sizeFactor() );
00580 luPixel myX = origin.x() + getX();
00581 luPixel myY = origin.y() + getY();
00582
00583
00584
00585
00586
00587 painter.setPen(context.getDefaultColor());
00588
00589 switch (getType()) {
00590 case LeftSquareBracket:
00591 if ( cmChar != -1 ) {
00592 drawCMDelimiter( painter, context, myX, myY, mySize );
00593 }
00594 else {
00595 drawBigRoundBracket( painter, context, leftSquareBracket, myX, myY, mySize );
00596 }
00597 break;
00598 case RightSquareBracket:
00599 if ( cmChar != -1 ) {
00600 drawCMDelimiter( painter, context, myX, myY, mySize );
00601 }
00602 else {
00603 drawBigRoundBracket( painter, context, rightSquareBracket, myX, myY, mySize );
00604 }
00605 break;
00606 case LeftCurlyBracket:
00607 if ( cmChar != -1 ) {
00608 drawCMDelimiter( painter, context, myX, myY, mySize );
00609 }
00610 else {
00611 drawBigCurlyBracket( painter, context, leftCurlyBracket, myX, myY, mySize );
00612 }
00613 break;
00614 case RightCurlyBracket:
00615 if ( cmChar != -1 ) {
00616 drawCMDelimiter( painter, context, myX, myY, mySize );
00617 }
00618 else {
00619 drawBigCurlyBracket( painter, context, rightCurlyBracket, myX, myY, mySize );
00620 }
00621 break;
00622 case LeftLineBracket: {
00623 luPixel halfWidth = getWidth()/2;
00624 drawBigRoundBracket( painter, context, leftLineBracket,
00625 myX-halfWidth, myY, mySize );
00626 }
00627 break;
00628 case RightLineBracket: {
00629 luPixel halfWidth = getWidth()/2;
00630 drawBigRoundBracket( painter, context, rightLineBracket,
00631 myX-halfWidth, myY, mySize );
00632 }
00633 break;
00634 case SlashBracket:
00635 if ( cmChar != -1 ) {
00636 drawCMDelimiter( painter, context, myX, myY, mySize );
00637 }
00638 break;
00639 case BackSlashBracket:
00640 if ( cmChar != -1 ) {
00641 drawCMDelimiter( painter, context, myX, myY, mySize );
00642 }
00643 break;
00644 case LeftCornerBracket:
00645 if ( cmChar != -1 ) {
00646 drawCMDelimiter( painter, context, myX, myY, mySize );
00647 }
00648 else drawCharacter(painter, context, myX, myY, mySize, leftAngleBracketChar);
00649 break;
00650 case RightCornerBracket:
00651 if ( cmChar != -1 ) {
00652 drawCMDelimiter( painter, context, myX, myY, mySize );
00653 }
00654 else drawCharacter(painter, context, myX, myY, mySize, rightAngleBracketChar);
00655 break;
00656 case LeftRoundBracket:
00657 if ( cmChar != -1 ) {
00658 drawCMDelimiter( painter, context, myX, myY, mySize );
00659 }
00660 else {
00661 drawBigRoundBracket( painter, context, leftRoundBracket, myX, myY, mySize );
00662 }
00663 break;
00664 case RightRoundBracket:
00665 if ( cmChar != -1 ) {
00666 drawCMDelimiter( painter, context, myX, myY, mySize );
00667 }
00668 else {
00669 drawBigRoundBracket( painter, context, rightRoundBracket, myX, myY, mySize );
00670 }
00671 break;
00672 case EmptyBracket:
00673 break;
00674 case Integral:
00675 drawCharacter(painter, context, QFont( "cmex10" ), myX, myY, mySize, cmex_Int);
00676 break;
00677 case Sum:
00678 drawCharacter(painter, context, QFont( "cmex10" ), myX, myY, mySize, cmex_Sum);
00679 break;
00680 case Product:
00681 drawCharacter(painter, context, QFont( "cmex10" ), myX, myY, mySize, cmex_Prod);
00682 break;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692 }
00693
00694 void Artwork::calcCharSize( const ContextStyle& style, luPt height, QChar ch )
00695 {
00696 calcCharSize( style, style.getMathFont(), height, ch );
00697 }
00698
00699
00700 void Artwork::drawCharacter( QPainter& painter, const ContextStyle& style,
00701 luPixel x, luPixel y,
00702 luPt height, QChar ch )
00703 {
00704 drawCharacter( painter, style, style.getMathFont(), x, y, height, ch );
00705 }
00706
00707
00708 void Artwork::calcCharSize( const ContextStyle& style, QFont f,
00709 luPt height, QChar c )
00710 {
00711 f.setPointSizeFloat( style.layoutUnitPtToPt( height ) );
00712
00713 QFontMetrics fm(f);
00714 setWidth( style.ptToLayoutUnitPt( fm.width( c ) ) );
00715 LuPixelRect bound = fm.boundingRect( c );
00716 setHeight( style.ptToLayoutUnitPt( bound.height() ) );
00717 setBaseline( style.ptToLayoutUnitPt( -bound.top() ) );
00718 }
00719
00720
00721 void Artwork::drawCharacter( QPainter& painter, const ContextStyle& style,
00722 QFont f,
00723 luPixel x, luPixel y, luPt height, uchar c )
00724 {
00725 f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00726
00727 painter.setFont( f );
00728 painter.drawText( style.layoutUnitToPixelX( x ),
00729 style.layoutUnitToPixelY( y+getBaseline() ),
00730 QString( QChar( c ) ) );
00731 }
00732
00733
00734 void Artwork::calcRoundBracket( const ContextStyle& style, const QChar chars[],
00735 luPt height, luPt charHeight )
00736 {
00737 uchar uppercorner = chars[0];
00738 uchar lowercorner = chars[1];
00739
00740
00741 QFont f = style.getBracketFont();
00742 f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
00743 QFontMetrics fm( f );
00744 LuPtRect upperBound = fm.boundingRect( uppercorner );
00745 LuPtRect lowerBound = fm.boundingRect( lowercorner );
00746
00747
00748 setWidth( style.ptToLayoutUnitPt( fm.width( QChar( uppercorner ) ) ) );
00749 luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+lowerBound.height() );
00750
00751
00752
00753 setHeight( QMAX( edgeHeight, height ) );
00754 }
00755
00756 void Artwork::drawBigRoundBracket( QPainter& p, const ContextStyle& style, const QChar chars[],
00757 luPixel x, luPixel y, luPt charHeight )
00758 {
00759 uchar uppercorner = chars[0];
00760 uchar lowercorner = chars[1];
00761 uchar line = chars[2];
00762
00763 QFont f = style.getBracketFont();
00764 f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
00765 p.setFont(f);
00766
00767 QFontMetrics fm(f);
00768 QRect upperBound = fm.boundingRect(uppercorner);
00769 QRect lowerBound = fm.boundingRect(lowercorner);
00770 QRect lineBound = fm.boundingRect(line);
00771
00772 pixel ptX = style.layoutUnitToPixelX( x );
00773 pixel ptY = style.layoutUnitToPixelY( y );
00774 pixel height = style.layoutUnitToPixelY( getHeight() );
00775
00776
00777
00778
00779
00780
00781
00782 p.drawText( ptX, ptY-upperBound.top(), QString( QChar( uppercorner ) ) );
00783 p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
00784 QString( QChar( lowercorner ) ) );
00785
00786
00787
00788 pixel safety = 0;
00789
00790 pixel gap = height - upperBound.height() - lowerBound.height();
00791 pixel lineHeight = lineBound.height() - safety;
00792 int lineCount = qRound( static_cast<double>( gap ) / lineHeight );
00793 pixel start = upperBound.height()-lineBound.top() - safety;
00794
00795 for (int i = 0; i < lineCount; i++) {
00796 p.drawText( ptX, ptY+start+i*lineHeight, QString(QChar(line)));
00797 }
00798 pixel remaining = gap - lineCount*lineHeight;
00799 pixel dist = ( lineHeight - remaining ) / 2;
00800 p.drawText( ptX, ptY+height-upperBound.height()+dist-lineBound.height()-lineBound.top(),
00801 QString( QChar( line ) ) );
00802 }
00803
00804 void Artwork::calcCurlyBracket( const ContextStyle& style, const QChar chars[],
00805 luPt height, luPt charHeight )
00806 {
00807 uchar uppercorner = chars[0];
00808 uchar lowercorner = chars[1];
00809
00810 uchar middle = chars[3];
00811
00812 QFont f = style.getBracketFont();
00813 f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
00814 QFontMetrics fm( f );
00815 LuPtRect upperBound = fm.boundingRect( uppercorner );
00816 LuPtRect lowerBound = fm.boundingRect( lowercorner );
00817
00818 LuPtRect middleBound = fm.boundingRect( middle );
00819
00820 setWidth( style.ptToLayoutUnitPt( fm.width( QChar( uppercorner ) ) ) );
00821 luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+
00822 lowerBound.height()+
00823 middleBound.height() );
00824
00825
00826
00827 setHeight( QMAX( edgeHeight, height ) );
00828 }
00829
00830 void Artwork::drawBigCurlyBracket( QPainter& p, const ContextStyle& style, const QChar chars[],
00831 luPixel x, luPixel y, luPt charHeight )
00832 {
00833
00834 QFont f = style.getBracketFont();
00835 f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
00836 p.setFont(f);
00837
00838 uchar uppercorner = chars[0];
00839 uchar lowercorner = chars[1];
00840 uchar line = chars[2];
00841 uchar middle = chars[3];
00842
00843 QFontMetrics fm(p.fontMetrics());
00844 QRect upperBound = fm.boundingRect(uppercorner);
00845 QRect lowerBound = fm.boundingRect(lowercorner);
00846 QRect middleBound = fm.boundingRect(middle);
00847 QRect lineBound = fm.boundingRect(line);
00848
00849 pixel ptX = style.layoutUnitToPixelX( x );
00850 pixel ptY = style.layoutUnitToPixelY( y );
00851 pixel height = style.layoutUnitToPixelY( getHeight() );
00852
00853
00854
00855
00856 p.drawText( ptX, ptY-upperBound.top(), QString( QChar( uppercorner ) ) );
00857 p.drawText( ptX, ptY+(height-middleBound.height())/2-middleBound.top(),
00858 QString( QChar( middle ) ) );
00859 p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
00860 QString( QChar( lowercorner ) ) );
00861
00862
00863
00864
00865
00866 pixel safety = 0;
00867
00868 pixel lineHeight = lineBound.height() - safety;
00869 pixel gap = height/2 - upperBound.height() - middleBound.height() / 2;
00870
00871 if (gap > 0) {
00872 QString ch = QString(QChar(line));
00873 int lineCount = qRound( gap / lineHeight ) + 1;
00874
00875 pixel start = (height - middleBound.height()) / 2 + safety;
00876 for (int i = 0; i < lineCount; i++) {
00877 p.drawText( ptX, ptY-lineBound.top()+QMAX( start-(i+1)*lineHeight,
00878 upperBound.width() ),
00879 ch );
00880 }
00881
00882 start = (height + middleBound.height()) / 2 - safety;
00883 for (int i = 0; i < lineCount; i++) {
00884 p.drawText( ptX, ptY-lineBound.top()+QMIN( start+i*lineHeight,
00885 height-upperBound.width()-lineBound.height() ),
00886 ch );
00887 }
00888 }
00889 }
00890
00891 KFORMULA_NAMESPACE_END