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
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025
00026 #include "kformuladefs.h"
00027 #include "cmstyle.h"
00028
00029
00030 KFORMULA_NAMESPACE_BEGIN
00031
00032 #include "cmmapping.cc"
00033
00034 bool CMStyle::init( ContextStyle* context )
00035 {
00036 SymbolTable* st = symbolTable();
00037 st->init( context );
00038
00039 SymbolTable::NameTable tempNames;
00040 fillNameTable( tempNames );
00041
00042 st->initFont( cmbx10Map, "cmbx10", tempNames );
00043 st->initFont( cmex10Map, "cmex10", tempNames );
00044 st->initFont( cmmi10Map, "cmmi10", tempNames );
00045 st->initFont( cmr10Map, "cmr10", tempNames );
00046 st->initFont( cmsy10Map, "cmsy10", tempNames );
00047 st->initFont( msam10Map, "msam10", tempNames );
00048 st->initFont( msbm10Map, "msbm10", tempNames );
00049
00050 return true;
00051 }
00052
00053
00054 const AlphaTable* CMStyle::alphaTable() const
00055 {
00056 return &m_alphaTable;
00057 }
00058
00059
00060 Artwork* CMStyle::createArtwork( SymbolType type ) const
00061 {
00062 return new CMArtwork( type );
00063 }
00064
00065 QStringList CMStyle::missingFonts()
00066 {
00067 QStringList missing;
00068
00069 testFont( missing, "cmbx10" );
00070 testFont( missing, "cmex10" );
00071 testFont( missing, "cmmi10" );
00072 testFont( missing, "cmr10" );
00073 testFont( missing, "cmsy10" );
00074 testFont( missing, "msam10" );
00075 testFont( missing, "msbm10" );
00076
00077 return missing;
00078 }
00079
00080
00081 CMAlphaTable::CMAlphaTable()
00082 {
00083 }
00084
00085
00086 AlphaTableEntry CMAlphaTable::entry( short pos,
00087 CharFamily family,
00088 CharStyle ) const
00089 {
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 AlphaTableEntry entry;
00108 switch( family ) {
00109
00110 case scriptFamily:
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 if ( ( pos >= 'A' ) && ( pos <= 'Z' ) ) {
00121 entry.pos = pos;
00122 entry.font = QFont( "cmsy10" );
00123 }
00124 break;
00125 case frakturFamily:
00126 break;
00127 case doubleStruckFamily:
00128 if ( ( pos >= 'A' ) && ( pos <= 'Z' ) ) {
00129 entry.pos = pos;
00130 entry.font = QFont( "msbm10" );
00131 }
00132 break;
00133 default:
00134 break;
00135 }
00136 return entry;
00137 }
00138
00139
00140 static const char cmex_LeftSquareBracket = 163;
00141 static const char cmex_RightSquareBracket = 164;
00142 static const char cmex_LeftCurlyBracket = 169;
00143 static const char cmex_RightCurlyBracket = 170;
00144 static const char cmex_LeftCornerBracket = 173;
00145 static const char cmex_RightCornerBracket = 174;
00146 static const char cmex_LeftRoundBracket = 161;
00147 static const char cmex_RightRoundBracket = 162;
00148 static const char cmex_SlashBracket = 177;
00149 static const char cmex_BackSlashBracket = 178;
00150
00151
00152
00153
00154 static const char cmex_Int = 90;
00155 static const char cmex_Sum = 88;
00156 static const char cmex_Prod = 89;
00157
00158
00159
00160 static short cmex_nextchar( short ch )
00161 {
00162 switch ( ch ) {
00163 case 161: return 179;
00164 case 162: return 180;
00165 case 163: return 104;
00166 case 164: return 105;
00167 case 169: return 110;
00168 case 170: return 111;
00169 case 165: return 106;
00170 case 166: return 107;
00171 case 167: return 108;
00172 case 168: return 109;
00173 case 173: return 68;
00174 case 174: return 69;
00175 case 177: return 46;
00176 case 178: return 47;
00177
00178 case 179: return 181;
00179 case 180: return 182;
00180 case 104: return 183;
00181 case 105: return 184;
00182 case 110: return 189;
00183 case 111: return 190;
00184 case 106: return 185;
00185 case 107: return 186;
00186 case 108: return 187;
00187 case 109: return 188;
00188 case 68: return 191;
00189 case 69: return 192;
00190 case 46: return 193;
00191 case 47: return 194;
00192
00193 case 181: return 195;
00194 case 182: return 33;
00195 case 183: return 34;
00196 case 184: return 35;
00197 case 189: return 40;
00198 case 190: return 41;
00199 case 185: return 36;
00200 case 186: return 37;
00201 case 187: return 38;
00202 case 188: return 39;
00203 case 191: return 42;
00204 case 192: return 43;
00205 case 193: return 44;
00206 case 194: return 45;
00207 }
00208 return 0;
00209 }
00210
00211 CMArtwork::CMArtwork( SymbolType t )
00212 : Artwork( t ), cmChar( -1 )
00213 {
00214 }
00215
00216
00217 void CMArtwork::calcSizes( const ContextStyle& style,
00218 ContextStyle::TextStyle tstyle,
00219 luPt parentSize )
00220 {
00221 setBaseline( -1 );
00222 cmChar = -1;
00223 luPt mySize = style.getAdjustedSize( tstyle );
00224 switch (getType()) {
00225 case LeftSquareBracket:
00226 if ( calcCMDelimiterSize( style, cmex_LeftSquareBracket,
00227 mySize, parentSize ) ) {
00228 return;
00229 }
00230 calcRoundBracket( style, leftSquareBracket, parentSize, mySize );
00231 break;
00232 case RightSquareBracket:
00233 if ( calcCMDelimiterSize( style, cmex_RightSquareBracket,
00234 mySize, parentSize ) ) {
00235 return;
00236 }
00237 calcRoundBracket( style, rightSquareBracket, parentSize, mySize );
00238 break;
00239 case LeftLineBracket:
00240 calcRoundBracket( style, leftLineBracket, parentSize, mySize );
00241 setWidth( getWidth()/2 );
00242 break;
00243 case RightLineBracket:
00244 calcRoundBracket( style, rightLineBracket, parentSize, mySize );
00245 setWidth( getWidth()/2 );
00246 break;
00247 case SlashBracket:
00248 if ( calcCMDelimiterSize( style, cmex_SlashBracket,
00249 mySize, parentSize ) ) {
00250 return;
00251 }
00252 calcLargest( style, cmex_SlashBracket, mySize );
00253 break;
00254 case BackSlashBracket:
00255 if ( calcCMDelimiterSize( style, cmex_BackSlashBracket,
00256 mySize, parentSize ) ) {
00257 return;
00258 }
00259 calcLargest( style, cmex_BackSlashBracket, mySize );
00260 break;
00261 case LeftCornerBracket:
00262 if ( calcCMDelimiterSize( style, cmex_LeftCornerBracket,
00263 mySize, parentSize ) ) {
00264 return;
00265 }
00266 calcLargest( style, cmex_LeftCornerBracket, mySize );
00267 break;
00268 case RightCornerBracket:
00269 if ( calcCMDelimiterSize( style, cmex_RightCornerBracket,
00270 mySize, parentSize ) ) {
00271 return;
00272 }
00273 calcLargest( style, cmex_RightCornerBracket, mySize );
00274 break;
00275 case LeftRoundBracket:
00276 if ( calcCMDelimiterSize( style, cmex_LeftRoundBracket,
00277 mySize, parentSize ) ) {
00278 return;
00279 }
00280 calcRoundBracket( style, leftRoundBracket, parentSize, mySize );
00281 break;
00282 case RightRoundBracket:
00283 if ( calcCMDelimiterSize( style, cmex_RightRoundBracket,
00284 mySize, parentSize ) ) {
00285 return;
00286 }
00287 calcRoundBracket( style, rightRoundBracket, parentSize, mySize );
00288 break;
00289 case EmptyBracket:
00290 setHeight(parentSize);
00291
00292 setWidth(0);
00293 break;
00294 case LeftCurlyBracket:
00295 if ( calcCMDelimiterSize( style, cmex_LeftCurlyBracket,
00296 mySize, parentSize ) ) {
00297 return;
00298 }
00299 calcCurlyBracket( style, leftCurlyBracket, parentSize, mySize );
00300 break;
00301 case RightCurlyBracket:
00302 if ( calcCMDelimiterSize( style, cmex_RightCurlyBracket,
00303 mySize, parentSize ) ) {
00304 return;
00305 }
00306 calcCurlyBracket( style, rightCurlyBracket, parentSize, mySize );
00307 break;
00308 case Integral:
00309 calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Int );
00310 break;
00311 case Sum:
00312 calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Sum );
00313 break;
00314 case Product:
00315 calcCharSize( style, QFont( "cmex10" ), mySize, cmex_Prod );
00316 break;
00317 }
00318 }
00319
00320
00321 void CMArtwork::calcSizes( const ContextStyle& style,
00322 ContextStyle::TextStyle tstyle )
00323 {
00324 luPt mySize = style.getAdjustedSize( tstyle );
00325 switch (getType()) {
00326 case LeftLineBracket:
00327 case RightLineBracket:
00328 calcCharSize(style, mySize, 0x2223);
00329 break;
00330 default:
00331 Artwork::calcSizes( style, tstyle );
00332 break;
00333 }
00334 }
00335
00336
00337 void CMArtwork::draw( QPainter& painter, const LuPixelRect& r,
00338 const ContextStyle& style,
00339 ContextStyle::TextStyle tstyle,
00340 const LuPixelPoint& parentOrigin )
00341 {
00342 luPt mySize = style.getAdjustedSize( tstyle );
00343 luPixel myX = parentOrigin.x() + getX();
00344 luPixel myY = parentOrigin.y() + getY();
00345 if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00346 return;
00347
00348 painter.setPen(style.getDefaultColor());
00349
00350 switch (getType()) {
00351 case LeftLineBracket:
00352 case RightLineBracket:
00353 drawCharacter(painter, style, myX, myY, mySize, 0x2223);
00354 break;
00355 default:
00356 Artwork::draw( painter, r, style, tstyle, parentOrigin );
00357 break;
00358 }
00359 }
00360
00361
00362 void CMArtwork::draw(QPainter& painter, const LuPixelRect& r,
00363 const ContextStyle& style, ContextStyle::TextStyle tstyle,
00364 luPt , const LuPixelPoint& origin)
00365 {
00366 luPt mySize = style.getAdjustedSize( tstyle );
00367 luPixel myX = origin.x() + getX();
00368 luPixel myY = origin.y() + getY();
00369 if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
00370 return;
00371
00372 painter.setPen(style.getDefaultColor());
00373
00374 switch (getType()) {
00375 case LeftSquareBracket:
00376 if ( cmChar != -1 ) {
00377 drawCMDelimiter( painter, style, myX, myY, mySize );
00378 }
00379 else {
00380 drawBigRoundBracket( painter, style, leftSquareBracket, myX, myY, mySize );
00381 }
00382 break;
00383 case RightSquareBracket:
00384 if ( cmChar != -1 ) {
00385 drawCMDelimiter( painter, style, myX, myY, mySize );
00386 }
00387 else {
00388 drawBigRoundBracket( painter, style, rightSquareBracket, myX, myY, mySize );
00389 }
00390 break;
00391 case LeftCurlyBracket:
00392 if ( cmChar != -1 ) {
00393 drawCMDelimiter( painter, style, myX, myY, mySize );
00394 }
00395 else {
00396 drawBigCurlyBracket( painter, style, leftCurlyBracket, myX, myY, mySize );
00397 }
00398 break;
00399 case RightCurlyBracket:
00400 if ( cmChar != -1 ) {
00401 drawCMDelimiter( painter, style, myX, myY, mySize );
00402 }
00403 else {
00404 drawBigCurlyBracket( painter, style, rightCurlyBracket, myX, myY, mySize );
00405 }
00406 break;
00407 case LeftLineBracket: {
00408 luPixel halfWidth = getWidth()/2;
00409 drawBigRoundBracket( painter, style, leftLineBracket,
00410 myX-halfWidth, myY, mySize );
00411 }
00412 break;
00413 case RightLineBracket: {
00414 luPixel halfWidth = getWidth()/2;
00415 drawBigRoundBracket( painter, style, rightLineBracket,
00416 myX-halfWidth, myY, mySize );
00417 }
00418 break;
00419 case SlashBracket:
00420 if ( cmChar != -1 ) {
00421 drawCMDelimiter( painter, style, myX, myY, mySize );
00422 }
00423 break;
00424 case BackSlashBracket:
00425 if ( cmChar != -1 ) {
00426 drawCMDelimiter( painter, style, myX, myY, mySize );
00427 }
00428 break;
00429 case LeftCornerBracket:
00430 if ( cmChar != -1 ) {
00431 drawCMDelimiter( painter, style, myX, myY, mySize );
00432 }
00433 else drawCharacter(painter, style, myX, myY, mySize, leftAngleBracketChar);
00434 break;
00435 case RightCornerBracket:
00436 if ( cmChar != -1 ) {
00437 drawCMDelimiter( painter, style, myX, myY, mySize );
00438 }
00439 else drawCharacter(painter, style, myX, myY, mySize, rightAngleBracketChar);
00440 break;
00441 case LeftRoundBracket:
00442 if ( cmChar != -1 ) {
00443 drawCMDelimiter( painter, style, myX, myY, mySize );
00444 }
00445 else {
00446 drawBigRoundBracket( painter, style, leftRoundBracket, myX, myY, mySize );
00447 }
00448 break;
00449 case RightRoundBracket:
00450 if ( cmChar != -1 ) {
00451 drawCMDelimiter( painter, style, myX, myY, mySize );
00452 }
00453 else {
00454 drawBigRoundBracket( painter, style, rightRoundBracket, myX, myY, mySize );
00455 }
00456 break;
00457 case EmptyBracket:
00458 break;
00459 case Integral:
00460 drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Int);
00461 break;
00462 case Sum:
00463 drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Sum);
00464 break;
00465 case Product:
00466 drawCharacter(painter, style, QFont( "cmex10" ), myX, myY, mySize, cmex_Prod);
00467 break;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477 }
00478
00479
00480 bool CMArtwork::isNormalChar() const
00481 {
00482 return Artwork::isNormalChar() && ( cmChar == -1 );
00483 }
00484
00485 double CMArtwork::slant() const
00486 {
00487 if ( getType() == Integral ) {
00488 return 0.25;
00489 }
00490 return 0;
00491 }
00492
00493 bool CMArtwork::calcCMDelimiterSize( const ContextStyle& context,
00494 uchar c,
00495 luPt fontSize,
00496 luPt parentSize )
00497 {
00498 QFont f( "cmex10" );
00499 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00500 QFontMetrics fm( f );
00501
00502 for ( char i=1; c != 0; ++i ) {
00503 LuPixelRect bound = fm.boundingRect( c );
00504
00505 luPt height = context.ptToLayoutUnitPt( bound.height() );
00506 if ( height >= parentSize ) {
00507 luPt width = context.ptToLayoutUnitPt( fm.width( c ) );
00508 luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00509
00510 cmChar = c;
00511
00512 setHeight( height );
00513 setWidth( width );
00514 setBaseline( baseline );
00515
00516 return true;
00517 }
00518 c = cmex_nextchar( c );
00519 }
00520
00521
00522 return false;
00523 }
00524
00525
00526 void CMArtwork::calcLargest( const ContextStyle& context,
00527 uchar c, luPt fontSize )
00528 {
00529 QFont f( "cmex10" );
00530 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
00531 QFontMetrics fm( f );
00532
00533 cmChar = c;
00534 for ( ;; ) {
00535 c = cmex_nextchar( c );
00536 if ( c == 0 ) {
00537 break;
00538 }
00539 cmChar = c;
00540 }
00541
00542 LuPixelRect bound = fm.boundingRect( cmChar );
00543
00544 luPt height = context.ptToLayoutUnitPt( bound.height() );
00545 luPt width = context.ptToLayoutUnitPt( fm.width( cmChar ) );
00546 luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
00547
00548 setHeight( height );
00549 setWidth( width );
00550 setBaseline( baseline );
00551 }
00552
00553
00554 void CMArtwork::drawCMDelimiter( QPainter& painter, const ContextStyle& style,
00555 luPixel x, luPixel y,
00556 luPt height )
00557 {
00558 QFont f( "cmex10" );
00559 f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
00560
00561 painter.setFont( f );
00562 painter.drawText( style.layoutUnitToPixelX( x ),
00563 style.layoutUnitToPixelY( y + getBaseline() ),
00564 QString( QChar( cmChar ) ) );
00565
00566
00567 #if 0
00568 QFontMetrics fm( f );
00569 LuPixelRect bound = fm.boundingRect( cmChar );
00570 painter.setBrush(Qt::NoBrush);
00571 painter.setPen(Qt::green);
00572 painter.drawRect( style.layoutUnitToPixelX( x ),
00573 style.layoutUnitToPixelY( y ),
00574 fm.width( cmChar ),
00575 bound.height() );
00576 #endif
00577 }
00578
00579
00580 KFORMULA_NAMESPACE_END