lib Library API Documentation

textelement.cc

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org> 00003 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include <qfontmetrics.h> 00022 #include <qpainter.h> 00023 00024 #include <kdebug.h> 00025 00026 #include "basicelement.h" 00027 #include "contextstyle.h" 00028 #include "elementtype.h" 00029 #include "elementvisitor.h" 00030 #include "fontstyle.h" 00031 #include "formulaelement.h" 00032 #include "kformulacommand.h" 00033 #include "sequenceelement.h" 00034 #include "symboltable.h" 00035 #include "textelement.h" 00036 00037 00038 KFORMULA_NAMESPACE_BEGIN 00039 00040 TextElement::TextElement(QChar ch, bool beSymbol, BasicElement* parent) 00041 : BasicElement(parent), character(ch), symbol(beSymbol) 00042 { 00043 charStyle( anyChar ); 00044 charFamily( anyFamily ); 00045 } 00046 00047 00048 TextElement::TextElement( const TextElement& other ) 00049 : BasicElement( other ), 00050 character( other.character ), 00051 symbol( other.symbol ), 00052 m_format( other.m_format ) 00053 { 00054 } 00055 00056 00057 bool TextElement::accept( ElementVisitor* visitor ) 00058 { 00059 return visitor->visit( this ); 00060 } 00061 00062 00063 TokenType TextElement::getTokenType() const 00064 { 00065 if ( isSymbol() ) { 00066 return getSymbolTable().charClass( character ); 00067 } 00068 00069 switch ( character.unicode() ) { 00070 case '+': 00071 case '-': 00072 case '*': 00073 //case '/': because it counts as text -- no extra spaces 00074 return BINOP; 00075 case '=': 00076 case '<': 00077 case '>': 00078 return RELATION; 00079 case ',': 00080 case ';': 00081 case ':': 00082 return PUNCTUATION; 00083 case '\\': 00084 return SEPARATOR; 00085 case '\0': 00086 return ELEMENT; 00087 default: 00088 if ( character.isNumber() ) { 00089 return NUMBER; 00090 } 00091 else { 00092 return ORDINARY; 00093 } 00094 } 00095 } 00096 00097 00098 bool TextElement::isInvisible() const 00099 { 00100 if (getElementType() != 0) { 00101 return getElementType()->isInvisible(*this); 00102 } 00103 return false; 00104 } 00105 00106 00111 void TextElement::calcSizes(const ContextStyle& context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle /*istyle*/) 00112 { 00113 luPt mySize = context.getAdjustedSize( tstyle ); 00114 //kdDebug( DEBUGID ) << "TextElement::calcSizes size=" << mySize << endl; 00115 00116 QFont font = getFont( context ); 00117 font.setPointSizeFloat( context.layoutUnitPtToPt( mySize ) ); 00118 00119 QFontMetrics fm( font ); 00120 QChar ch = getRealCharacter(context); 00121 if ( ch != QChar::null ) { 00122 QRect bound = fm.boundingRect( ch ); 00123 setWidth( context.ptToLayoutUnitPt( fm.width( ch ) ) ); 00124 setHeight( context.ptToLayoutUnitPt( bound.height() ) ); 00125 setBaseline( context.ptToLayoutUnitPt( -bound.top() ) ); 00126 00127 // There are some glyphs in TeX that have 00128 // baseline==0. (\int, \sum, \prod) 00129 if ( getBaseline() == 0 ) { 00130 //setBaseline( getHeight()/2 + context.axisHeight( tstyle ) ); 00131 setBaseline( -1 ); 00132 } 00133 } 00134 else { 00135 setWidth( qRound( context.getEmptyRectWidth() * 2./3. ) ); 00136 setHeight( qRound( context.getEmptyRectHeight() * 2./3. ) ); 00137 setBaseline( getHeight() ); 00138 } 00139 00140 //kdDebug( DEBUGID ) << "height: " << getHeight() << endl; 00141 //kdDebug( DEBUGID ) << "width: " << getWidth() << endl; 00142 } 00143 00149 void TextElement::draw( QPainter& painter, const LuPixelRect& /*r*/, 00150 const ContextStyle& context, 00151 ContextStyle::TextStyle tstyle, 00152 ContextStyle::IndexStyle /*istyle*/, 00153 const LuPixelPoint& parentOrigin ) 00154 { 00155 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); 00156 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) 00157 // return; 00158 00159 setUpPainter( context, painter ); 00160 00161 luPt mySize = context.getAdjustedSize( tstyle ); 00162 QFont font = getFont( context ); 00163 font.setPointSizeFloat( context.layoutUnitToFontSize( mySize, false ) ); 00164 painter.setFont( font ); 00165 00166 //kdDebug( DEBUGID ) << "TextElement::draw font=" << font.rawName() << endl; 00167 //kdDebug( DEBUGID ) << "TextElement::draw size=" << mySize << endl; 00168 //kdDebug( DEBUGID ) << "TextElement::draw size=" << context.layoutUnitToFontSize( mySize, false ) << endl; 00169 //kdDebug( DEBUGID ) << "TextElement::draw height: " << getHeight() << endl; 00170 //kdDebug( DEBUGID ) << "TextElement::draw width: " << getWidth() << endl; 00171 //kdDebug( DEBUGID ) << endl; 00172 00173 // Each starting element draws the whole token 00174 ElementType* token = getElementType(); 00175 if ( ( token != 0 ) && !symbol ) { 00176 QString text = token->text( static_cast<SequenceElement*>( getParent() ) ); 00177 // kdDebug() << "draw text: " << text[0].unicode() 00178 // << " " << painter.font().family().latin1() 00179 // << endl; 00180 painter.drawText( context.layoutUnitToPixelX( myPos.x() ), 00181 context.layoutUnitToPixelY( myPos.y()+getBaseline() ), 00182 text ); 00183 } 00184 else { 00185 //kdDebug() << "draw char" << endl; 00186 QChar ch = getRealCharacter(context); 00187 if ( ch != QChar::null ) { 00188 luPixel bl = getBaseline(); 00189 if ( bl == -1 ) { 00190 // That's quite hacky and actually not the way it's 00191 // meant to be. You shouldn't calculate a lot in 00192 // draw. But I don't see how else to deal with 00193 // baseline==0 glyphs without yet another flag. 00194 bl = -( getHeight()/2 + context.axisHeight( tstyle ) ); 00195 } 00196 painter.drawText( context.layoutUnitToPixelX( myPos.x() ), 00197 context.layoutUnitToPixelY( myPos.y()+bl ), 00198 ch ); 00199 } 00200 else { 00201 painter.setPen( QPen( context.getErrorColor(), 00202 context.layoutUnitToPixelX( context.getLineWidth() ) ) ); 00203 painter.drawRect( context.layoutUnitToPixelX( myPos.x() ), 00204 context.layoutUnitToPixelY( myPos.y() ), 00205 context.layoutUnitToPixelX( getWidth() ), 00206 context.layoutUnitToPixelY( getHeight() ) ); 00207 } 00208 } 00209 00210 // Debug 00211 //painter.setBrush(Qt::NoBrush); 00212 // if ( isSymbol() ) { 00213 // painter.setPen( Qt::red ); 00214 // painter.drawRect( context.layoutUnitToPixelX( myPos.x() ), 00215 // context.layoutUnitToPixelX( myPos.y() ), 00216 // context.layoutUnitToPixelX( getWidth() ), 00217 // context.layoutUnitToPixelX( getHeight() ) ); 00218 // painter.setPen(Qt::green); 00219 // painter.drawLine(myPos.x(), myPos.y()+axis( context, tstyle ), 00220 // myPos.x()+getWidth(), myPos.y()+axis( context, tstyle )); 00221 // } 00222 } 00223 00224 00225 void TextElement::dispatchFontCommand( FontCommand* cmd ) 00226 { 00227 cmd->addTextElement( this ); 00228 } 00229 00230 void TextElement::setCharStyle( CharStyle cs ) 00231 { 00232 charStyle( cs ); 00233 formula()->changed(); 00234 } 00235 00236 void TextElement::setCharFamily( CharFamily cf ) 00237 { 00238 charFamily( cf ); 00239 formula()->changed(); 00240 } 00241 00242 QChar TextElement::getRealCharacter(const ContextStyle& context) 00243 { 00244 if ( !isSymbol() ) { 00245 const FontStyle& fontStyle = context.fontStyle(); 00246 const AlphaTable* alphaTable = fontStyle.alphaTable(); 00247 if ( alphaTable != 0 ) { 00248 AlphaTableEntry ate = alphaTable->entry( character, 00249 charFamily(), 00250 charStyle() ); 00251 if ( ate.valid() ) { 00252 return ate.pos; 00253 } 00254 } 00255 return character; 00256 } 00257 else { 00258 return getSymbolTable().character(character, charStyle()); 00259 } 00260 } 00261 00262 00263 QFont TextElement::getFont(const ContextStyle& context) 00264 { 00265 if ( !isSymbol() ) { 00266 const FontStyle& fontStyle = context.fontStyle(); 00267 const AlphaTable* alphaTable = fontStyle.alphaTable(); 00268 if ( alphaTable != 0 ) { 00269 AlphaTableEntry ate = alphaTable->entry( character, 00270 charFamily(), 00271 charStyle() ); 00272 if ( ate.valid() ) { 00273 return ate.font; 00274 } 00275 } 00276 QFont font; 00277 if (getElementType() != 0) { 00278 font = getElementType()->getFont(context); 00279 } 00280 else { 00281 font = context.getDefaultFont(); 00282 } 00283 switch ( charStyle() ) { 00284 case anyChar: 00285 break; 00286 case normalChar: 00287 font.setItalic( false ); 00288 font.setBold( false ); 00289 break; 00290 case boldChar: 00291 font.setItalic( false ); 00292 font.setBold( true ); 00293 break; 00294 case italicChar: 00295 font.setItalic( true ); 00296 font.setBold( false ); 00297 break; 00298 case boldItalicChar: 00299 font.setItalic( true ); 00300 font.setBold( true ); 00301 break; 00302 } 00303 return font; 00304 } 00305 return context.symbolTable().font( character, charStyle() ); 00306 } 00307 00308 00309 void TextElement::setUpPainter(const ContextStyle& context, QPainter& painter) 00310 { 00311 if (getElementType() != 0) { 00312 getElementType()->setUpPainter(context, painter); 00313 } 00314 else { 00315 painter.setPen(Qt::red); 00316 } 00317 } 00318 00319 const SymbolTable& TextElement::getSymbolTable() const 00320 { 00321 return formula()->getSymbolTable(); 00322 } 00323 00324 00328 void TextElement::writeDom(QDomElement element) 00329 { 00330 BasicElement::writeDom(element); 00331 element.setAttribute("CHAR", QString(character)); 00332 //QString s; 00333 //element.setAttribute("CHAR", s.sprintf( "#x%05X", character ) ); 00334 if (symbol) element.setAttribute("SYMBOL", "3"); 00335 00336 switch ( charStyle() ) { 00337 case anyChar: break; 00338 case normalChar: element.setAttribute("STYLE", "normal"); break; 00339 case boldChar: element.setAttribute("STYLE", "bold"); break; 00340 case italicChar: element.setAttribute("STYLE", "italic"); break; 00341 case boldItalicChar: element.setAttribute("STYLE", "bolditalic"); break; 00342 } 00343 00344 switch ( charFamily() ) { 00345 case normalFamily: element.setAttribute("FAMILY", "normal"); break; 00346 case scriptFamily: element.setAttribute("FAMILY", "script"); break; 00347 case frakturFamily: element.setAttribute("FAMILY", "fraktur"); break; 00348 case doubleStruckFamily: element.setAttribute("FAMILY", "doublestruck"); break; 00349 case anyFamily: break; 00350 } 00351 } 00352 00357 bool TextElement::readAttributesFromDom(QDomElement element) 00358 { 00359 if (!BasicElement::readAttributesFromDom(element)) { 00360 return false; 00361 } 00362 QString charStr = element.attribute("CHAR"); 00363 if(!charStr.isNull()) { 00364 character = charStr.at(0); 00365 } 00366 QString symbolStr = element.attribute("SYMBOL"); 00367 if(!symbolStr.isNull()) { 00368 int symbolInt = symbolStr.toInt(); 00369 if ( symbolInt == 1 ) { 00370 character = getSymbolTable().unicodeFromSymbolFont(character); 00371 } 00372 if ( symbolInt == 2 ) { 00373 switch ( character.unicode() ) { 00374 case 0x03D5: character = 0x03C6; break; 00375 case 0x03C6: character = 0x03D5; break; 00376 case 0x03Ba: character = 0x03BA; break; 00377 case 0x00B4: character = 0x2032; break; 00378 case 0x2215: character = 0x2244; break; 00379 case 0x00B7: character = 0x2022; break; 00380 case 0x1D574: character = 0x2111; break; 00381 case 0x1D579: character = 0x211C; break; 00382 case 0x2219: character = 0x22C5; break; 00383 case 0x2662: character = 0x26C4; break; 00384 case 0x220B: character = 0x220D; break; 00385 case 0x224C: character = 0x2245; break; 00386 case 0x03DB: character = 0x03C2; break; 00387 } 00388 } 00389 symbol = symbolInt != 0; 00390 } 00391 00392 QString styleStr = element.attribute("STYLE"); 00393 if ( styleStr == "normal" ) { 00394 charStyle( normalChar ); 00395 } 00396 else if ( styleStr == "bold" ) { 00397 charStyle( boldChar ); 00398 } 00399 else if ( styleStr == "italic" ) { 00400 charStyle( italicChar ); 00401 } 00402 else if ( styleStr == "bolditalic" ) { 00403 charStyle( boldItalicChar ); 00404 } 00405 else { 00406 charStyle( anyChar ); 00407 } 00408 00409 QString familyStr = element.attribute( "FAMILY" ); 00410 if ( familyStr == "normal" ) { 00411 charFamily( normalFamily ); 00412 } 00413 else if ( familyStr == "script" ) { 00414 charFamily( scriptFamily ); 00415 } 00416 else if ( familyStr == "fraktur" ) { 00417 charFamily( frakturFamily ); 00418 } 00419 else if ( familyStr == "doublestruck" ) { 00420 charFamily( doubleStruckFamily ); 00421 } 00422 else { 00423 charFamily( anyFamily ); 00424 } 00425 00426 // kdDebug() << "charStyle=" << charStyle() 00427 // << " charFamily=" << charFamily() 00428 // << " format=" << int( format() ) << endl; 00429 00430 return true; 00431 } 00432 00438 bool TextElement::readContentFromDom(QDomNode& node) 00439 { 00440 return BasicElement::readContentFromDom(node); 00441 } 00442 00443 QString TextElement::toLatex() 00444 { 00445 if ( isSymbol() ) { 00446 QString texName = getSymbolTable().name( character ); 00447 if ( !texName.isNull() ) 00448 return "\\" + texName; 00449 return " ? "; 00450 } 00451 else { 00452 return character; 00453 } 00454 } 00455 00456 QString TextElement::formulaString() 00457 { 00458 if ( isSymbol() ) { 00459 QString texName = getSymbolTable().name( character ); 00460 if ( !texName.isNull() ) 00461 return " " + texName + " "; 00462 return " ? "; 00463 } 00464 else { 00465 return character; 00466 } 00467 } 00468 00469 00470 EmptyElement::EmptyElement( BasicElement* parent ) 00471 : BasicElement( parent ) 00472 { 00473 } 00474 00475 EmptyElement::EmptyElement( const EmptyElement& other ) 00476 : BasicElement( other ) 00477 { 00478 } 00479 00480 00481 bool EmptyElement::accept( ElementVisitor* visitor ) 00482 { 00483 return visitor->visit( this ); 00484 } 00485 00486 00487 void EmptyElement::calcSizes( const ContextStyle& context, 00488 ContextStyle::TextStyle tstyle, 00489 ContextStyle::IndexStyle /*istyle*/ ) 00490 { 00491 luPt mySize = context.getAdjustedSize( tstyle ); 00492 //kdDebug( DEBUGID ) << "TextElement::calcSizes size=" << mySize << endl; 00493 00494 QFont font = context.getDefaultFont(); 00495 font.setPointSizeFloat( context.layoutUnitPtToPt( mySize ) ); 00496 00497 QFontMetrics fm( font ); 00498 QChar ch = 'A'; 00499 QRect bound = fm.boundingRect( ch ); 00500 setWidth( 0 ); 00501 setHeight( context.ptToLayoutUnitPt( bound.height() ) ); 00502 setBaseline( context.ptToLayoutUnitPt( -bound.top() ) ); 00503 } 00504 00505 void EmptyElement::draw( QPainter& painter, const LuPixelRect& /*r*/, 00506 const ContextStyle& context, 00507 ContextStyle::TextStyle /*tstyle*/, 00508 ContextStyle::IndexStyle /*istyle*/, 00509 const LuPixelPoint& parentOrigin ) 00510 { 00511 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); 00512 /* 00513 if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) 00514 return; 00515 */ 00516 00517 if ( context.edit() ) { 00518 painter.setPen( context.getHelpColor() ); 00519 painter.drawLine( context.layoutUnitToPixelX( myPos.x() ), 00520 context.layoutUnitToPixelY( myPos.y() ), 00521 context.layoutUnitToPixelX( myPos.x() ), 00522 context.layoutUnitToPixelY( myPos.y()+getHeight() ) ); 00523 } 00524 } 00525 00526 QString EmptyElement::toLatex() 00527 { 00528 return "{}"; 00529 } 00530 00531 KFORMULA_NAMESPACE_END
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:29 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003