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