00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <qfontmetrics.h>
00023 #include <qpainter.h>
00024
00025 #include <kdebug.h>
00026 #include <kprinter.h>
00027
00028 #include "contextstyle.h"
00029 #include "elementvisitor.h"
00030 #include "spaceelement.h"
00031
00032
00033 KFORMULA_NAMESPACE_BEGIN
00034
00035
00036 SpaceElement::SpaceElement( SpaceWidth space, bool tab, BasicElement* parent )
00037 : BasicElement( parent ),
00038 m_tab( tab ),
00039 m_widthType( NoSize ),
00040 m_heightType( NoSize ),
00041 m_depthType( NoSize ),
00042 m_lineBreak( NoBreakType )
00043 {
00044
00045 switch ( space ) {
00046 case NEGTHIN:
00047 m_widthType = NegativeThinMathSpace;
00048 break;
00049 case THIN:
00050 m_widthType = ThinMathSpace;
00051 break;
00052 case MEDIUM:
00053 m_widthType = MediumMathSpace;
00054 break;
00055 case THICK:
00056 m_widthType = ThickMathSpace;
00057 break;
00058 case QUAD:
00059 m_widthType = VeryVeryThickMathSpace;
00060 break;
00061 }
00062 }
00063
00064
00065 SpaceElement::SpaceElement( const SpaceElement& other )
00066 : BasicElement( other ),
00067 m_widthType( other.m_widthType ),
00068 m_width( other.m_width ),
00069 m_heightType( other.m_heightType ),
00070 m_height( other.m_height ),
00071 m_depthType( other.m_depthType ),
00072 m_depth( other.m_depth ),
00073 m_lineBreak( other.m_lineBreak )
00074 {
00075 }
00076
00077
00078 bool SpaceElement::accept( ElementVisitor* visitor )
00079 {
00080 return visitor->visit( this );
00081 }
00082
00083
00084 void SpaceElement::calcSizes( const ContextStyle& context,
00085 ContextStyle::TextStyle tstyle,
00086 ContextStyle::IndexStyle ,
00087 StyleAttributes& style )
00088 {
00089 double factor = style.sizeFactor();
00090 luPt mySize = context.getAdjustedSize( tstyle, factor );
00091 QFont font = context.getDefaultFont();
00092 font.setPointSize( mySize );
00093
00094 QFontMetrics fm( font );
00095 QChar w = 'M';
00096 LuPixelRect hbound = fm.boundingRect( w );
00097 QChar h = 'x';
00098 LuPixelRect vbound = fm.boundingRect( h );
00099
00100 double width = style.getSpace( m_widthType, m_width );
00101 if ( m_widthType == AbsoluteSize ) {
00102 width = m_width / context.layoutUnitPtToPt( context.getBaseSize() );
00103 }
00104 else if ( m_widthType == PixelSize ) {
00105 width = context.pixelYToPt( m_width ) / context.layoutUnitPtToPt( context.getBaseSize() );
00106 }
00107 double height = style.getSpace( m_heightType, m_height );
00108 if ( m_heightType == AbsoluteSize ) {
00109 height = m_height / context.layoutUnitPtToPt( context.getBaseSize() );
00110 }
00111 else if ( m_heightType == PixelSize ) {
00112 height = context.pixelYToPt( m_height ) / context.layoutUnitPtToPt( context.getBaseSize() );
00113 }
00114 double depth = style.getSpace( m_depthType, m_depth );
00115 if ( m_depthType == AbsoluteSize ) {
00116 depth = m_depth / context.layoutUnitPtToPt( context.getBaseSize() );
00117 }
00118 else if ( m_depthType == PixelSize ) {
00119 depth = context.pixelYToPt( m_depth ) / context.layoutUnitPtToPt( context.getBaseSize() );
00120 }
00121
00122 setWidth( hbound.width() * width );
00123 setHeight( vbound.height() * height + vbound.height() * depth );
00124 setBaseline( vbound.height() * height );
00125
00126 if ( m_tab ) {
00127 getParent()->registerTab( this );
00128 }
00129 }
00130
00131 void SpaceElement::draw( QPainter& painter, const LuPixelRect& ,
00132 const ContextStyle& context,
00133 ContextStyle::TextStyle ,
00134 ContextStyle::IndexStyle ,
00135 StyleAttributes& ,
00136 const LuPixelPoint& parentOrigin )
00137 {
00138 LuPixelPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY());
00139
00140
00141
00142
00143 if ( context.edit() ) {
00144 painter.setPen( context.getEmptyColor() );
00145 painter.drawLine( context.layoutUnitToPixelX( myPos.x() ),
00146 context.layoutUnitToPixelY( myPos.y()+getHeight() ),
00147 context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ),
00148 context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00149 painter.drawLine( context.layoutUnitToPixelX( myPos.x() ),
00150 context.layoutUnitToPixelY( myPos.y()+getHeight() ),
00151 context.layoutUnitToPixelX( myPos.x() ),
00152 context.layoutUnitToPixelY( myPos.y()+getHeight()-getHeight()/5 ) );
00153 painter.drawLine( context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ),
00154 context.layoutUnitToPixelY( myPos.y()+getHeight() ),
00155 context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ),
00156 context.layoutUnitToPixelY( myPos.y()+getHeight()-getHeight()/5 ) );
00157 }
00158 }
00159
00160
00161 void SpaceElement::writeDom(QDomElement element)
00162 {
00163 BasicElement::writeDom(element);
00164 switch ( m_widthType ) {
00165 case NegativeVeryVeryThinMathSpace:
00166 case NegativeVeryThinMathSpace:
00167 case NegativeThinMathSpace:
00168 case NegativeMediumMathSpace:
00169 case NegativeThickMathSpace:
00170 case NegativeVeryThickMathSpace:
00171 case NegativeVeryVeryThickMathSpace:
00172 element.setAttribute( "WIDTH", "negthin" );
00173 break;
00174 case VeryVeryThinMathSpace:
00175 case VeryThinMathSpace:
00176 case ThinMathSpace:
00177 element.setAttribute( "WIDTH", "thin" );
00178 break;
00179 case MediumMathSpace:
00180 element.setAttribute( "WIDTH", "medium" );
00181 break;
00182 case ThickMathSpace:
00183 element.setAttribute( "WIDTH", "thick" );
00184 break;
00185 case VeryThickMathSpace:
00186 case VeryVeryThickMathSpace:
00187 element.setAttribute( "WIDTH", "quad" );
00188 break;
00189 case AbsoluteSize:
00190 case RelativeSize:
00191 case PixelSize:
00192 if ( m_width < 0 ) {
00193 element.setAttribute( "WIDTH", "negthin" );
00194 }
00195 else {
00196 element.setAttribute( "WIDTH", "thin" );
00197 }
00198 default:
00199 break;
00200 }
00201 if ( m_tab ) {
00202 element.setAttribute( "TAB", "true" );
00203 }
00204 }
00205
00206 bool SpaceElement::readAttributesFromDom( QDomElement element )
00207 {
00208 if ( !BasicElement::readAttributesFromDom( element ) ) {
00209 return false;
00210 }
00211 QString widthStr = element.attribute( "WIDTH" );
00212 if( !widthStr.isNull() ) {
00213 if ( widthStr.lower() == "quad" ) {
00214 m_widthType = VeryVeryThickMathSpace;
00215 }
00216 else if ( widthStr.lower() == "thick" ) {
00217 m_widthType = ThickMathSpace;
00218 }
00219 else if ( widthStr.lower() == "medium" ) {
00220 m_widthType = MediumMathSpace;
00221 }
00222 else if ( widthStr.lower() == "negthin" ) {
00223 m_widthType = NegativeThinMathSpace;
00224 }
00225 else {
00226 m_widthType = ThinMathSpace;
00227 }
00228 }
00229 else {
00230 return false;
00231 }
00232 QString tabStr = element.attribute( "TAB" );
00233 m_tab = !tabStr.isNull();
00234 return true;
00235 }
00236
00237 bool SpaceElement::readContentFromDom(QDomNode& node)
00238 {
00239 return BasicElement::readContentFromDom( node );
00240 }
00241
00242 bool SpaceElement::readAttributesFromMathMLDom(const QDomElement& element)
00243 {
00244 if ( ! BasicElement::readAttributesFromMathMLDom( element ) ) {
00245 return false;
00246 }
00247
00248 QString widthStr = element.attribute( "width" ).stripWhiteSpace().lower();
00249 if ( ! widthStr.isNull() ) {
00250 m_width = getSize( widthStr, &m_widthType );
00251 if ( m_widthType == NoSize ) {
00252 m_widthType = getSpace( widthStr );
00253 }
00254 }
00255 QString heightStr = element.attribute( "height" ).stripWhiteSpace().lower();
00256 if ( ! heightStr.isNull() ) {
00257 m_height = getSize( heightStr, &m_heightType );
00258 }
00259 QString depthStr = element.attribute( "depth" ).stripWhiteSpace().lower();
00260 if ( ! depthStr.isNull() ) {
00261 m_depth = getSize( depthStr, &m_depthType );
00262 }
00263 QString linebreakStr = element.attribute( "linebreak" ).stripWhiteSpace().lower();
00264 if ( ! linebreakStr.isNull() ) {
00265 if ( linebreakStr == "auto" ) {
00266 m_lineBreak = AutoBreak;
00267 }
00268 else if ( linebreakStr == "newline" ) {
00269 m_lineBreak = NewLineBreak;
00270 }
00271 else if ( linebreakStr == "indentingnewline" ) {
00272 m_lineBreak = IndentingNewLineBreak;
00273 }
00274 else if ( linebreakStr == "nobreak" ) {
00275 m_lineBreak = NoBreak;
00276 }
00277 else if ( linebreakStr == "goodbreak" ) {
00278 m_lineBreak = GoodBreak;
00279 }
00280 else if ( linebreakStr == "badbreak" ) {
00281 m_lineBreak = BadBreak;
00282 }
00283 }
00284 return true;
00285 }
00286
00287 void SpaceElement::writeMathMLAttributes( QDomElement& element ) const
00288 {
00289 switch ( m_widthType ) {
00290 case AbsoluteSize:
00291 element.setAttribute( "width", QString( "%1pt" ).arg( m_width ) );
00292 break;
00293 case RelativeSize:
00294 element.setAttribute( "width", QString( "%1%" ).arg( m_width * 100.0 ) );
00295 break;
00296 case PixelSize:
00297 element.setAttribute( "width", QString( "%1px" ).arg( m_width ) );
00298 break;
00299 case NegativeVeryVeryThinMathSpace:
00300 element.setAttribute( "width", "negativeveryverythinmathspace" );
00301 break;
00302 case NegativeVeryThinMathSpace:
00303 element.setAttribute( "width", "negativeverythinmathspace" );
00304 break;
00305 case NegativeThinMathSpace:
00306 element.setAttribute( "width", "negativethinmathspace" );
00307 break;
00308 case NegativeMediumMathSpace:
00309 element.setAttribute( "width", "negativemediummathspace" );
00310 break;
00311 case NegativeThickMathSpace:
00312 element.setAttribute( "width", "negativethickmathspace" );
00313 break;
00314 case NegativeVeryThickMathSpace:
00315 element.setAttribute( "width", "negativeverythickmathspace" );
00316 break;
00317 case NegativeVeryVeryThickMathSpace:
00318 element.setAttribute( "width", "negativeveryverythickmathspace" );
00319 break;
00320 case VeryVeryThinMathSpace:
00321 element.setAttribute( "width", "veryverythinmathspace" );
00322 break;
00323 case VeryThinMathSpace:
00324 element.setAttribute( "width", "verythinmathspace" );
00325 break;
00326 case ThinMathSpace:
00327 element.setAttribute( "width", "thinmathspace" );
00328 break;
00329 case MediumMathSpace:
00330 element.setAttribute( "width", "mediummathspace" );
00331 break;
00332 case ThickMathSpace:
00333 element.setAttribute( "width", "thickmathspace" );
00334 break;
00335 case VeryThickMathSpace:
00336 element.setAttribute( "width", "verythickmathspace" );
00337 break;
00338 case VeryVeryThickMathSpace:
00339 element.setAttribute( "width", "veryverythickmathspace" );
00340 break;
00341 default:
00342 break;
00343 }
00344 switch ( m_heightType ) {
00345 case AbsoluteSize:
00346 element.setAttribute( "height", QString( "%1pt" ).arg( m_height ) );
00347 break;
00348 case RelativeSize:
00349 element.setAttribute( "height", QString( "%1%" ).arg( m_height * 100.0 ) );
00350 break;
00351 case PixelSize:
00352 element.setAttribute( "height", QString( "%1px" ).arg( m_height ) );
00353 break;
00354 default:
00355 break;
00356 }
00357 switch ( m_depthType ) {
00358 case AbsoluteSize:
00359 element.setAttribute( "depth", QString( "%1pt" ).arg( m_depth ) );
00360 break;
00361 case RelativeSize:
00362 element.setAttribute( "depth", QString( "%1%" ).arg( m_depth * 100.0 ) );
00363 break;
00364 case PixelSize:
00365 element.setAttribute( "depth", QString( "%1px" ).arg( m_depth ) );
00366 break;
00367 default:
00368 break;
00369 }
00370 switch ( m_lineBreak ) {
00371 case AutoBreak:
00372 element.setAttribute( "linebreak", "auto" );
00373 break;
00374 case NewLineBreak:
00375 element.setAttribute( "linebreak", "newline" );
00376 break;
00377 case IndentingNewLineBreak:
00378 element.setAttribute( "linebreak", "indentingnewline" );
00379 break;
00380 case NoBreak:
00381 element.setAttribute( "linebreak", "nobreak" );
00382 break;
00383 case GoodBreak:
00384 element.setAttribute( "linebreak", "goodbreak" );
00385 break;
00386 case BadBreak:
00387 element.setAttribute( "linebreak", "badbreak" );
00388 break;
00389 default:
00390 break;
00391 }
00392 }
00393
00394 QString SpaceElement::toLatex()
00395 {
00396 switch ( m_widthType ) {
00397 case NegativeVeryVeryThinMathSpace:
00398 case NegativeVeryThinMathSpace:
00399 case NegativeThinMathSpace:
00400 case NegativeMediumMathSpace:
00401 case NegativeThickMathSpace:
00402 case NegativeVeryThickMathSpace:
00403 case NegativeVeryVeryThickMathSpace:
00404 return "\\!";
00405 case VeryVeryThinMathSpace:
00406 case VeryThinMathSpace:
00407 case ThinMathSpace:
00408 return "\\,";
00409 case MediumMathSpace:
00410 return "\\>";
00411 case ThickMathSpace:
00412 return "\\;";
00413 case VeryThickMathSpace:
00414 case VeryVeryThickMathSpace:
00415 return "\\quad ";
00416 case AbsoluteSize:
00417 case RelativeSize:
00418 case PixelSize:
00419 if ( m_width < 0 ) {
00420 return "\\!";
00421 }
00422 else {
00423 return "\\,";
00424 }
00425 default:
00426 break;
00427 }
00428 return "";
00429 }
00430
00431 KFORMULA_NAMESPACE_END