lib

styleelement.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "basicelement.h"
00021 #include "styleelement.h"
00022 
00023 KFORMULA_NAMESPACE_BEGIN
00024 
00025 StyleElement::StyleElement( BasicElement* parent ) : TokenStyleElement( parent ),
00026                                                      m_scriptMinSizeType( NoSize ),
00027                                                      m_veryVeryThinMathSpaceType( NoSize ),
00028                                                      m_veryThinMathSpaceType( NoSize ),
00029                                                      m_thinMathSpaceType( NoSize ),
00030                                                      m_mediumMathSpaceType( NoSize ),
00031                                                      m_thickMathSpaceType( NoSize ),
00032                                                      m_veryThickMathSpaceType( NoSize ),
00033                                                      m_veryVeryThickMathSpaceType( NoSize ),
00034                                                      m_customScriptLevel( false ),
00035                                                      m_relativeScriptLevel( false ),
00036                                                      m_customDisplayStyle( false ),
00037                                                      m_customScriptSizeMultiplier( false ),
00038                                                      m_customBackground( false )
00039 {
00040 }
00041 
00042 bool StyleElement::readAttributesFromMathMLDom( const QDomElement& element )
00043 {
00044     if ( !BasicElement::readAttributesFromMathMLDom( element ) ) {
00045         return false;
00046     }
00047     
00048     QString scriptlevelStr = element.attribute( "scriptlevel" );
00049     if ( ! scriptlevelStr.isNull() ) {
00050         if ( scriptlevelStr[0] == '+' || scriptlevelStr[0] == '-' ) {
00051             m_relativeScriptLevel = true;
00052         }
00053         bool ok;
00054         m_scriptLevel = scriptlevelStr.toInt( &ok );
00055         if ( ! ok ) {
00056             kdWarning( DEBUGID ) << "Invalid scriptlevel attribute value: " 
00057                                  << scriptlevelStr << endl;
00058         }
00059         else {
00060             m_customScriptLevel = true;
00061         }
00062     }
00063     QString displaystyleStr = element.attribute( "displaystyle" );
00064     if ( ! displaystyleStr.isNull() ) {
00065         if ( displaystyleStr.lower() == "true" ) {
00066             m_displayStyle = true;
00067         }
00068         else {
00069             m_displayStyle = false;
00070         }
00071         m_customDisplayStyle = true;
00072     }
00073     QString scriptsizemultiplierStr = element.attribute( "scriptsizemultiplier" );
00074     if ( ! scriptsizemultiplierStr.isNull() ) {
00075         bool ok;
00076         m_scriptSizeMultiplier = scriptsizemultiplierStr.toDouble( &ok );
00077         if ( ! ok ) {
00078             kdWarning( DEBUGID ) << "Invalid scriptsizemultiplier attribute value: " 
00079                                  << scriptsizemultiplierStr << endl;
00080         }
00081         else {
00082             m_customScriptSizeMultiplier = true;
00083         }
00084     }
00085     QString scriptminsizeStr = element.attribute( "scriptminsize" );
00086     if ( ! scriptminsizeStr.isNull() ) {
00087         readSizeAttribute( scriptminsizeStr, &m_scriptMinSizeType, &m_scriptMinSize );
00088     }
00089     QString backgroundStr = element.attribute( "background" );
00090     if ( ! backgroundStr.isNull() ) {
00091         // TODO: tranparent background
00092         m_customBackground = true;
00093         if ( backgroundStr[0] != '#' ) {
00094             m_background = QColor( getHtmlColor( backgroundStr ) );
00095         }
00096         else {
00097             m_background = QColor( backgroundStr );
00098         }
00099     }
00100     QString veryverythinmathspaceStr = element.attribute( "veryverythinmathspace" );
00101     if ( ! veryverythinmathspaceStr.isNull() ) {
00102         readSizeAttribute( veryverythinmathspaceStr, &m_veryVeryThinMathSpaceType, &m_veryVeryThinMathSpace );
00103     }
00104     QString verythinmathspaceStr = element.attribute( "verythinmathspace" );
00105     if ( ! verythinmathspaceStr.isNull() ) {
00106         readSizeAttribute( verythinmathspaceStr, &m_veryThinMathSpaceType, &m_veryThinMathSpace );
00107     }
00108     QString thinmathspaceStr = element.attribute( "thinmathspace" );
00109     if ( ! thinmathspaceStr.isNull() ) {
00110         readSizeAttribute( thinmathspaceStr, &m_thinMathSpaceType, &m_thinMathSpace );
00111     }
00112     QString mediummathspaceStr = element.attribute( "mediummathspace" );
00113     if ( ! mediummathspaceStr.isNull() ) {
00114         readSizeAttribute( mediummathspaceStr, &m_mediumMathSpaceType, &m_mediumMathSpace );
00115     }
00116     QString thickmathspaceStr = element.attribute( "thickmathspace" );
00117     if ( ! thickmathspaceStr.isNull() ) {
00118         readSizeAttribute( thickmathspaceStr, &m_thickMathSpaceType, &m_thickMathSpace );
00119     }
00120     QString verythickmathspaceStr = element.attribute( "verythickmathspace" );
00121     if ( ! verythickmathspaceStr.isNull() ) {
00122         readSizeAttribute( verythickmathspaceStr, &m_veryThickMathSpaceType, &m_veryThickMathSpace );
00123     }
00124     QString veryverythickmathspaceStr = element.attribute( "veryverythickmathspace" );
00125     if ( ! veryverythickmathspaceStr.isNull() ) {
00126         readSizeAttribute( veryverythickmathspaceStr, &m_veryVeryThickMathSpaceType, &m_veryVeryThickMathSpace );
00127     }
00128     return inherited::readAttributesFromMathMLDom( element );
00129 }
00130 
00131 void StyleElement::writeMathMLAttributes( QDomElement& element ) const
00132 {
00133     if ( m_customScriptLevel ) {
00134         QString prefix;
00135         if ( m_relativeScriptLevel && m_scriptLevel >= 0 ) {
00136             prefix = "+";
00137         }
00138         element.setAttribute( "scriptlevel", prefix + QString( "%1" ).arg( m_scriptLevel ) );
00139     }
00140     if ( m_customDisplayStyle ) {
00141         element.setAttribute( "displaystyle", m_displayStyle ? "true" : "false" );
00142     }
00143     if ( m_customScriptSizeMultiplier ) {
00144         element.setAttribute( "scriptsizemultiplier", QString( "%1" ).arg( m_scriptSizeMultiplier ) );
00145     }
00146     writeSizeAttribute( element, "scriptminsize", m_scriptMinSizeType, m_scriptMinSize );
00147     if ( m_customBackground ) {
00148         element.setAttribute( "background", m_background.name() );
00149     }
00150     writeSizeAttribute( element, "veryverythinmathspace", m_veryVeryThinMathSpaceType, m_veryVeryThinMathSpace );
00151     writeSizeAttribute( element, "verythinmathspace", m_veryThinMathSpaceType, m_veryThinMathSpace );
00152     writeSizeAttribute( element, "thinmathspace", m_thinMathSpaceType, m_thinMathSpace );
00153     writeSizeAttribute( element, "mediummathspace", m_mediumMathSpaceType, m_mediumMathSpace );
00154     writeSizeAttribute( element, "thickmathspace", m_thickMathSpaceType, m_thickMathSpace );
00155     writeSizeAttribute( element, "verythickmathspace", m_veryThickMathSpaceType, m_veryThickMathSpace );
00156     writeSizeAttribute( element, "veryverythickmathspace", m_veryVeryThickMathSpaceType, m_veryVeryThickMathSpace );
00157 
00158     inherited::writeMathMLAttributes( element );
00159 }
00160 
00161 
00162 void StyleElement::setStyleSize( const ContextStyle& context, StyleAttributes& style )
00163 {
00164     if ( m_customScriptLevel ) {
00165         if ( m_relativeScriptLevel ) {
00166             style.setScriptLevel( style.scriptLevel() + m_scriptLevel );
00167         }
00168         else {
00169             style.setScriptLevel( m_scriptLevel );
00170         }
00171     }
00172     else {
00173         style.setScriptLevel( style.scriptLevel() );
00174     }
00175     if ( m_customDisplayStyle || style.customDisplayStyle() ) {
00176         style.setCustomDisplayStyle( true );
00177         if ( m_customDisplayStyle ) {
00178             style.setDisplayStyle( m_displayStyle );
00179         }
00180         else {
00181             style.setDisplayStyle( style.displayStyle() );
00182         }
00183     }
00184     else {
00185         style.setCustomDisplayStyle( false );
00186     }
00187     if ( m_customScriptSizeMultiplier ) {
00188         style.setScriptSizeMultiplier( m_scriptSizeMultiplier );
00189     }
00190     else {
00191         style.setScriptSizeMultiplier( style.scriptSizeMultiplier() );
00192     }
00193 
00194     // Get scriptminsize attribute in absolute units, so we don't depend on 
00195     // context to get the default value
00196     double basesize = context.layoutUnitPtToPt( context.getBaseSize() );
00197     double size = style.scriptMinSize();
00198     switch ( m_scriptMinSizeType ) {
00199     case AbsoluteSize:
00200         size = m_scriptMinSize;
00201     case RelativeSize:
00202         size = m_scriptMinSize * basesize;
00203     case PixelSize:
00204         size = context.pixelXToPt( m_scriptMinSize );
00205     default:
00206         break;
00207     }
00208     style.setScriptMinSize( size );
00209 
00210     style.setVeryVeryThinMathSpace( sizeFactor( context, 
00211                                                 m_veryVeryThinMathSpaceType,
00212                                                 m_veryVeryThinMathSpace,
00213                                                 style.veryVeryThinMathSpace() ));
00214     style.setVeryThinMathSpace( sizeFactor( context,  m_veryThinMathSpaceType,
00215                                             m_veryThinMathSpace,
00216                                             style.veryThinMathSpace() ));
00217     style.setThinMathSpace( sizeFactor( context, m_thinMathSpaceType,
00218                                         m_thinMathSpace, 
00219                                         style.thinMathSpace() ));
00220     style.setMediumMathSpace( sizeFactor( context, m_mediumMathSpaceType,
00221                                           m_mediumMathSpace,
00222                                           style.mediumMathSpace() ));
00223     style.setThickMathSpace( sizeFactor( context,  m_thickMathSpaceType,
00224                                          m_thickMathSpace,
00225                                          style.thickMathSpace() ));
00226     style.setVeryThickMathSpace( sizeFactor( context, m_veryThickMathSpaceType,
00227                                              m_veryThickMathSpace,
00228                                              style.veryThickMathSpace() ));
00229     style.setVeryVeryThickMathSpace( sizeFactor( context, 
00230                                                  m_veryVeryThickMathSpaceType,
00231                                                  m_veryVeryThickMathSpace,
00232                                                  style.veryVeryThickMathSpace() ));
00233     inherited::setStyleSize( context, style );
00234 }
00235 
00236 double StyleElement::sizeFactor( const ContextStyle& context, SizeType st, 
00237                                  double length, double defvalue )
00238 {
00239     double basesize = context.layoutUnitPtToPt( context.getBaseSize() );
00240     switch ( st ) {
00241     case AbsoluteSize:
00242         return length / basesize;
00243     case RelativeSize:
00244         return length;
00245     case PixelSize:
00246         return context.pixelXToPt( length ) / basesize;
00247     default:
00248         break;
00249     }
00250     return defvalue;
00251 }
00252 
00253 void StyleElement::setStyleVariant( StyleAttributes& style )
00254 {
00255     if ( customMathVariant() ) {
00256         style.setCustomMathVariant ( true );
00257         style.setCustomFontWeight( false );
00258         style.setCustomFontStyle( false );
00259         style.setCustomFont( false );
00260         if ( customMathVariant() ) {
00261             style.setCharFamily ( charFamily() );
00262             style.setCharStyle( charStyle() );
00263         }
00264         else {
00265             style.setCharFamily( style.charFamily() );
00266             style.setCharStyle( style.charStyle() );
00267         }
00268     }
00269     else {
00270         style.setCustomMathVariant( false );
00271         if ( customFontFamily() ) {
00272             style.setCustomFont( true );
00273             style.setFont( QFont(fontFamily()) );
00274         }
00275 
00276         bool fontweight = false;
00277         if ( customFontWeight() || style.customFontWeight() ) {
00278             style.setCustomFontWeight( true );
00279             if ( customFontWeight() ) {
00280                 fontweight = fontWeight();
00281             }
00282             else {
00283                 fontweight = style.fontWeight();
00284             }
00285             style.setFontWeight( fontweight );
00286         }
00287         else {
00288             style.setCustomFontWeight( false );
00289         }
00290 
00291         bool fontstyle = false;
00292         if ( customFontStyle() || style.customFontStyle() ) {
00293             style.setCustomFontStyle( true );
00294             if ( customFontStyle() ) {
00295                 fontstyle = fontStyle();
00296             }
00297             else {
00298                 fontstyle = style.fontStyle();
00299             }
00300             style.setFontStyle( fontstyle );
00301         }
00302         else {
00303             style.setCustomFontStyle( false );
00304         }
00305 
00306         if ( fontweight && fontstyle ) {
00307             style.setCharStyle( boldItalicChar );
00308         }
00309         else if ( fontweight && ! fontstyle ) {
00310             style.setCharStyle( boldChar );
00311         }
00312         else if ( ! fontweight && fontstyle ) {
00313             style.setCharStyle( italicChar );
00314         }
00315         else {
00316             style.setCharStyle( normalChar );
00317         }
00318     }
00319 }
00320 
00321 void StyleElement::setStyleBackground( StyleAttributes& style )
00322 {
00323     if ( customMathBackground() ) {
00324         style.setBackground( mathBackground() );
00325     }
00326     else if ( m_customBackground ) {
00327         style.setBackground( m_background );
00328     }
00329     else {
00330         style.setBackground( style.background() );
00331     }
00332 }
00333 
00334 void StyleElement::resetStyle( StyleAttributes& style )
00335 {
00336     inherited::resetStyle( style );
00337     style.resetScriptLevel();
00338     style.resetScriptSizeMultiplier();
00339     style.resetScriptMinSize();
00340     style.resetVeryVeryThinMathSpace();
00341     style.resetVeryThinMathSpace();
00342     style.resetThinMathSpace();
00343     style.resetMediumMathSpace();
00344     style.resetThickMathSpace();
00345     style.resetVeryThickMathSpace();
00346     style.resetVeryVeryThickMathSpace();
00347     style.resetDisplayStyle();
00348 }
00349 
00350 void StyleElement::readSizeAttribute( const QString& str, SizeType* st, double* s )
00351 {
00352     if ( st == 0 || s == 0 ){
00353         return;
00354     }
00355     if ( str == "small" ) {
00356         *st = RelativeSize;
00357         *s = 0.8; // ### Arbitrary size
00358     }
00359     else if ( str == "normal" ) {
00360         *st = RelativeSize;
00361         *s = 1.0;
00362     }
00363     else if ( str == "big" ) {
00364         *st = RelativeSize;
00365         *s = 1.2; // ### Arbitrary size
00366     }
00367     else {
00368         *s = getSize( str, st );
00369     }
00370 }
00371 
00372 void StyleElement::writeSizeAttribute( QDomElement element, const QString& str, SizeType st, double s ) const
00373 {
00374     switch ( st ) {
00375     case AbsoluteSize:
00376         element.setAttribute( str, QString( "%1pt" ).arg( s ) );
00377         break;
00378     case RelativeSize:
00379         element.setAttribute( str, QString( "%1%" ).arg( s * 100.0 ) );
00380         break;
00381     case PixelSize:
00382         element.setAttribute( str, QString( "%1px" ).arg( s ) );
00383         break;
00384     default:
00385         break;
00386     }
00387 }
00388 
00389 
00390 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys