lib

tokenstyleelement.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 <qpainter.h>
00021 
00022 #include "basicelement.h"
00023 #include "tokenstyleelement.h"
00024 
00025 KFORMULA_NAMESPACE_BEGIN
00026 
00027 TokenStyleElement::TokenStyleElement( BasicElement* parent ) : SequenceElement( parent ),
00028                                                      m_mathSizeType ( NoSize ),
00029                                                      m_charStyle( anyChar ),
00030                                                      m_charFamily( anyFamily ),
00031                                                      m_mathColor( "#000000" ),
00032                                                      m_mathBackground( "#FFFFFF" ),
00033                                                      m_fontSizeType( NoSize ),
00034                                                      m_customMathVariant( false ),
00035                                                      m_customMathColor( false ),
00036                                                      m_customMathBackground( false ),
00037                                                      m_customFontWeight( false ),
00038                                                      m_customFontStyle( false ),
00039                                                      m_customFontFamily( false ),
00040                                                      m_customColor( false )
00041 {
00042 }
00043 
00044 void TokenStyleElement::calcSizes( const ContextStyle& context,
00045                               ContextStyle::TextStyle tstyle,
00046                               ContextStyle::IndexStyle istyle,
00047                               StyleAttributes& style )
00048 {
00049     setStyleSize( context, style );
00050     setStyleVariant( style );
00051     setStyleColor( style );
00052     setStyleBackground( style );
00053     inherited::calcSizes( context, tstyle, istyle, style );
00054     resetStyle( style );
00055 }
00056 
00057 void TokenStyleElement::draw( QPainter& painter, const LuPixelRect& r,
00058                          const ContextStyle& context,
00059                          ContextStyle::TextStyle tstyle,
00060                          ContextStyle::IndexStyle istyle,
00061                          StyleAttributes& style,
00062                          const LuPixelPoint& parentOrigin )
00063 {
00064     setStyleSize( context, style );
00065     setStyleVariant( style );
00066     setStyleColor( style );
00067     setStyleBackground( style );
00068     if ( style.background() != Qt::color0 ) {
00069         painter.fillRect( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00070                           context.layoutUnitToPixelY( parentOrigin.y() + getY() ),
00071                           context.layoutUnitToPixelX( getWidth() ),
00072                           context.layoutUnitToPixelY( getHeight() ),
00073                           style.background() );
00074     }
00075     inherited::draw( painter, r, context, tstyle, istyle, style, parentOrigin );
00076     resetStyle( style );
00077 }
00078 
00079 bool TokenStyleElement::readAttributesFromMathMLDom( const QDomElement& element )
00080 {
00081     if ( !BasicElement::readAttributesFromMathMLDom( element ) ) {
00082         return false;
00083     }
00084 
00085     // MathML Section 3.2.2
00086     QString variantStr = element.attribute( "mathvariant" );
00087     if ( !variantStr.isNull() ) {
00088         if ( variantStr == "normal" ) {
00089             setCharStyle( normalChar );
00090             setCharFamily( normalFamily );
00091         }
00092         else if ( variantStr == "bold" ) {
00093             setCharStyle( boldChar );
00094             setCharFamily( normalFamily );
00095         }
00096         else if ( variantStr == "italic" ) {
00097             setCharStyle( italicChar );
00098             setCharFamily( normalFamily );
00099         }
00100         else if ( variantStr == "bold-italic" ) {
00101             setCharStyle( boldItalicChar );
00102             setCharFamily( normalFamily );
00103         }
00104         else if ( variantStr == "double-struck" ) {
00105             setCharStyle( normalChar );
00106             setCharFamily( doubleStruckFamily );
00107         }
00108         else if ( variantStr == "bold-fraktur" ) {
00109             setCharStyle( boldChar );
00110             setCharFamily( frakturFamily );
00111         }
00112         else if ( variantStr == "script" ) {
00113             setCharStyle( normalChar );
00114             setCharFamily( scriptFamily );
00115         }
00116         else if ( variantStr == "bold-script" ) {
00117             setCharStyle( boldChar );
00118             setCharFamily( scriptFamily );
00119         }
00120         else if ( variantStr == "fraktur" ) {
00121             setCharStyle( boldChar );
00122             setCharFamily( frakturFamily );
00123         }
00124         else if ( variantStr == "sans-serif" ) {
00125             setCharStyle( normalChar );
00126             setCharFamily( sansSerifFamily );
00127         }
00128         else if ( variantStr == "bold-sans-serif" ) {
00129             setCharStyle( boldChar );
00130             setCharFamily( sansSerifFamily );
00131         }
00132         else if ( variantStr == "sans-serif-italic" ) {
00133             setCharStyle( italicChar );
00134             setCharFamily( sansSerifFamily );
00135         }
00136         else if ( variantStr == "sans-serif-bold-italic" ) {
00137             setCharStyle( boldItalicChar );
00138             setCharFamily( sansSerifFamily );
00139         }
00140         else if ( variantStr == "monospace" ) {
00141             setCharStyle( normalChar );
00142             setCharFamily( monospaceFamily );
00143         }
00144     }
00145 
00146     QString sizeStr = element.attribute( "mathsize" );
00147     if ( !sizeStr.isNull() ) {
00148         if ( sizeStr == "small" ) {
00149             setRelativeSize( 0.8 ); // ### Arbitrary size
00150         }
00151         else if ( sizeStr == "normal" ) {
00152             setRelativeSize( 1.0 );
00153         }
00154         else if ( sizeStr == "big" ) {
00155             setRelativeSize( 1.2 ); // ### Arbitrary size
00156         }
00157         else {
00158             double s = getSize( sizeStr, &m_mathSizeType );
00159             switch ( m_mathSizeType ) {
00160             case AbsoluteSize:
00161                 setAbsoluteSize( s );
00162                 break;
00163             case RelativeSize:
00164                 setRelativeSize( s );
00165                 break;
00166             case PixelSize:
00167                 setPixelSize( s );
00168                 break;
00169             default:
00170                 break;
00171             }
00172         }
00173     }
00174 
00175     QString colorStr = element.attribute( "mathcolor" );
00176     if ( !colorStr.isNull() ) {
00177         if ( colorStr[0] != '#' ) {
00178             setMathColor( QColor( getHtmlColor( colorStr ) ) );
00179         }
00180         else {
00181             setMathColor( QColor( colorStr ) );
00182         }
00183     }
00184     QString backgroundStr = element.attribute( "mathbackground" );
00185     if ( !backgroundStr.isNull() ) {
00186         if ( backgroundStr[0] != '#' ) {
00187             setMathBackground( QColor( getHtmlColor( backgroundStr ) ) );
00188         }
00189         else {
00190             setMathBackground( QColor( backgroundStr ) );
00191         }
00192     }
00193 
00194     // Deprecated attributes. See Section 3.2.2.1
00195 
00196     sizeStr = element.attribute( "fontsize" );
00197     if ( ! sizeStr.isNull() ) {
00198         if ( sizeStr == "small" ) {
00199             setRelativeSize( 0.8, true ); // ### Arbitrary size
00200         }
00201         else if ( sizeStr == "normal" ) {
00202             setRelativeSize( 1.0, true );
00203         }
00204         else if ( sizeStr == "big" ) {
00205             setRelativeSize( 1.2, true ); // ### Arbitrary size
00206         }
00207         else {
00208             double s = getSize( sizeStr, &m_fontSizeType );
00209             switch ( m_fontSizeType ) {
00210             case AbsoluteSize:
00211                 setAbsoluteSize( s, true );
00212                 break;
00213             case RelativeSize:
00214                 setRelativeSize( s, true );
00215                 break;
00216             case PixelSize:
00217                 setPixelSize( s, true );
00218                 break;
00219             default:
00220                 break;
00221             }
00222         }
00223     }
00224 
00225     QString styleStr = element.attribute( "fontstyle" );
00226     if ( ! styleStr.isNull() ) {
00227         if ( styleStr.lower() == "italic" ) {
00228             setFontStyle( true );
00229         }
00230         else {
00231             setFontStyle( false );
00232         }
00233     }
00234 
00235     QString weightStr = element.attribute( "fontweight" );
00236     if ( ! weightStr.isNull() ) {
00237         if ( weightStr.lower() == "bold" ) {
00238             setFontWeight( true );
00239         }
00240         else {
00241             setFontWeight( false );
00242         }
00243     }
00244 
00245     QString familyStr =  element.attribute( "fontfamily" );
00246     if ( ! familyStr.isNull() ) {
00247         setFontFamily( familyStr );
00248     }
00249 
00250     colorStr = element.attribute( "color" );
00251     if ( ! colorStr.isNull() ) {
00252         if ( colorStr[0] != '#' ) {
00253             setColor( QColor( getHtmlColor( colorStr ) ) );
00254         }
00255         else {
00256             setColor( QColor( colorStr  ) );
00257         }
00258     }
00259 
00260     return true;
00261 }
00262 
00263 void TokenStyleElement::writeMathMLAttributes( QDomElement& element ) const
00264 {
00265     // mathvariant attribute
00266     if ( customMathVariant() ) {
00267         if ( charFamily() == normalFamily ) {
00268             if ( charStyle() == normalChar ) {
00269                 element.setAttribute( "mathvariant", "normal" );
00270             }
00271             else if ( charStyle() == boldChar ) {
00272                 element.setAttribute( "mathvariant", "bold" );
00273             }
00274             else if ( charStyle() == italicChar ) {
00275                 element.setAttribute( "mathvariant", "italic" );
00276             }
00277             else if ( charStyle() == boldItalicChar ) {
00278                 element.setAttribute( "mathvariant", "bold-italic" );
00279             }
00280             else { // anyChar or unknown, it's always an error
00281                 kdWarning( DEBUGID ) << "Mathvariant: unknown style for normal family\n";
00282             }
00283         }
00284         else if ( charFamily() == doubleStruckFamily ) {
00285             if ( charStyle() == normalChar ) {
00286                 element.setAttribute( "mathvariant", "double-struck" );
00287             }
00288             else { // Shouldn't happen, it's a bug
00289                 kdWarning( DEBUGID ) << "Mathvariant: unknown style for double-struck family\n";
00290             }
00291         }
00292         else if ( charFamily() == frakturFamily ) {
00293             if ( charStyle() == normalChar ) {
00294                 element.setAttribute( "mathvariant", "fraktur" );
00295             }
00296             else if ( charStyle() == boldChar ) {
00297                 element.setAttribute( "mathvariant", "bold-fraktur" );
00298             }
00299             else {
00300                 kdWarning( DEBUGID ) << "Mathvariant: unknown style for fraktur family\n";
00301             }
00302         }
00303         else if ( charFamily() == scriptFamily ) {
00304             if ( charStyle() == normalChar ) {
00305                 element.setAttribute( "mathvariant", "script" );
00306             }
00307             else if ( charStyle() == boldChar ) {
00308                 element.setAttribute( "mathvariant", "bold-script" );
00309             }
00310             else { // Shouldn't happen, it's a bug
00311                 kdWarning( DEBUGID ) << "Mathvariant: unknown style for script family\n";
00312             }
00313         }
00314         else if ( charFamily() == sansSerifFamily ) {
00315             if ( charStyle() == normalChar ) {
00316                 element.setAttribute( "mathvariant", "sans-serif" );
00317             }
00318             else if ( charStyle() == boldChar ) {
00319                 element.setAttribute( "mathvariant", "bold-sans-serif" );
00320             }
00321             else if ( charStyle() == italicChar ) {
00322                 element.setAttribute( "mathvariant", "sans-serif-italic" );
00323             }
00324             else if ( charStyle() == boldItalicChar ) {
00325                 element.setAttribute( "mathvariant", "sans-serif-bold-italic" );
00326             }
00327             else {
00328                 kdWarning( DEBUGID ) << "Mathvariant: unknown style for sans serif family\n";
00329             }
00330         }
00331         else if ( charFamily() == monospaceFamily ) {
00332             if ( charStyle() == normalChar ) {
00333                 element.setAttribute( "mathvariant", "monospace" );
00334             }
00335             else {
00336                 kdWarning( DEBUGID ) << "Mathvariant: unknown style for monospace family\n";
00337             }
00338         }
00339         else {
00340             kdWarning( DEBUGID ) << "Mathvariant: unknown family\n";
00341         }
00342     }
00343 
00344     // mathsize attribute
00345     switch ( m_mathSizeType ) {
00346     case AbsoluteSize:
00347         element.setAttribute( "mathsize", QString( "%1pt" ).arg( m_mathSize ) );
00348         break;
00349     case RelativeSize:
00350         element.setAttribute( "mathsize", QString( "%1%" ).arg( m_mathSize * 100.0 ) );
00351         break;
00352     case PixelSize:
00353         element.setAttribute( "mathsize", QString( "%1px" ).arg( m_mathSize ) );
00354         break;
00355     default:
00356         break;
00357     }
00358 
00359     // mathcolor attribute
00360     if ( customMathColor() ) {
00361         element.setAttribute( "mathcolor", mathColor().name() );
00362     }
00363     
00364     // mathbackground attribute
00365     if ( customMathBackground() ) {
00366         element.setAttribute( "mathbackground", mathBackground().name() );
00367     }
00368 
00369     // Deprecated MathML 1.01 Attributes
00370     // fontsize attribute
00371     switch ( m_fontSizeType ) {
00372     case AbsoluteSize:
00373         element.setAttribute( "fontsize", QString( "%1pt" ).arg( m_fontSize ) );
00374         break;
00375     case RelativeSize:
00376         element.setAttribute( "fontsize", QString( "%1%" ).arg( m_fontSize * 100.0 ) );
00377         break;
00378     case PixelSize:
00379         element.setAttribute( "fontsize", QString( "%3px" ).arg( m_fontSize ) );
00380         break;
00381     default:
00382         break;
00383     }
00384 
00385     // fontweight attribute
00386     if ( customFontWeight() ) {
00387         element.setAttribute( "fontweight", fontWeight() ? "bold" : "normal" );
00388     }
00389 
00390     // fontstyle attribute
00391     if ( customFontStyle() ) {
00392         element.setAttribute( "fontstyle", fontStyle() ? "italic" : "normal" );
00393     }
00394 
00395     // fontfamily attribute
00396     if ( customFontFamily() ) {
00397         element.setAttribute( "fontfamily", fontFamily() );
00398     }
00399 
00400     // color attribute
00401     if ( customColor() ) {
00402         element.setAttribute( "color", color().name() );
00403     }
00404 }
00405 
00406 void TokenStyleElement::setAbsoluteSize( double s, bool fontsize )
00407 { 
00408         kdDebug( DEBUGID) << "Setting absolute size: " << s << endl;
00409         if ( fontsize ) {
00410             m_fontSizeType = AbsoluteSize;
00411             m_fontSize = s;
00412         }
00413         else {
00414             m_mathSizeType = AbsoluteSize;
00415             m_mathSize = s;
00416         }
00417 }
00418 
00419 void TokenStyleElement::setRelativeSize( double f, bool fontsize )
00420 { 
00421         kdDebug( DEBUGID) << "Setting relative size: " << f << endl;
00422         if ( fontsize ) {
00423             m_fontSizeType = RelativeSize;
00424             m_fontSize = f;
00425         }
00426         else {
00427             m_mathSizeType = RelativeSize;
00428             m_mathSize = f;
00429         }
00430 }
00431 
00432 void TokenStyleElement::setPixelSize( double px, bool fontsize )
00433 {
00434         kdDebug( DEBUGID) << "Setting pixel size: " << px << endl;
00435         if ( fontsize ) {
00436             m_fontSizeType = PixelSize;
00437             m_fontSize = px;
00438         }
00439         else {
00440             m_mathSizeType = PixelSize;
00441             m_mathSize = px;
00442         }
00443 }
00444 
00445 void TokenStyleElement::setStyleSize( const ContextStyle& context, StyleAttributes& style )
00446 {
00447     style.setSizeFactor( sizeFactor( context, style.sizeFactor() ) );
00448 }
00449 
00450 void TokenStyleElement::setStyleVariant( StyleAttributes& style )
00451 {
00452     if ( customMathVariant() || style.customMathVariant() ) {
00453         style.setCustomMathVariant ( true );
00454         style.setCustomFontWeight( false );
00455         style.setCustomFontStyle( false );
00456         style.setCustomFont( false );
00457         if ( customMathVariant() ) {
00458             style.setCharFamily ( charFamily() );
00459             style.setCharStyle( charStyle() );
00460         }
00461         else {
00462             style.setCharFamily( style.charFamily() );
00463             style.setCharStyle( style.charStyle() );
00464         }
00465     }
00466     else {
00467         style.setCustomMathVariant( false );
00468         if ( customFontFamily() ) {
00469             style.setCustomFont( true );
00470             style.setFont( QFont(fontFamily()) );
00471         }
00472 
00473         bool fontweight = false;
00474         if ( customFontWeight() || style.customFontWeight() ) {
00475             style.setCustomFontWeight( true );
00476             if ( customFontWeight() ) {
00477                 fontweight = fontWeight();
00478             }
00479             else {
00480                 fontweight = style.fontWeight();
00481             }
00482             style.setFontWeight( fontweight );
00483         }
00484         else {
00485             style.setCustomFontWeight( false );
00486         }
00487 
00488         bool fontstyle = false;
00489         if ( style.customFontStyle() ) {
00490             style.setCustomFontStyle( true );
00491             fontstyle = style.fontStyle();
00492             style.setFontStyle( fontstyle );
00493         }
00494         else {
00495             style.setCustomFontStyle( false );
00496         }
00497         if ( customFontStyle() ) {
00498             fontstyle = fontStyle();
00499         }
00500 
00501         if ( fontweight && fontstyle ) {
00502             style.setCharStyle( boldItalicChar );
00503         }
00504         else if ( fontweight && ! fontstyle ) {
00505             style.setCharStyle( boldChar );
00506         }
00507         else if ( ! fontweight && fontstyle ) {
00508             style.setCharStyle( italicChar );
00509         }
00510         else {
00511             style.setCharStyle( normalChar );
00512         }
00513     }
00514 }
00515 
00516 void TokenStyleElement::setStyleColor( StyleAttributes& style )
00517 {
00518     if ( customMathColor() ) {
00519         style.setColor( mathColor() );
00520     }
00521     else if ( customColor() ) {
00522         style.setColor( color() );
00523     }
00524     else {
00525         style.setColor( style.color() );
00526     }
00527 }
00528 
00529 void TokenStyleElement::setStyleBackground( StyleAttributes& style )
00530 {
00531     if ( customMathBackground() ) {
00532         style.setBackground( mathBackground() );
00533     }
00534     else {
00535         style.setBackground( style.background() );
00536     }
00537 }
00538 
00539 void TokenStyleElement::resetStyle( StyleAttributes& style )
00540 {
00541     style.resetSize();
00542     style.resetCharStyle();
00543     style.resetCharFamily();
00544     style.resetColor();
00545     style.resetBackground();
00546     style.resetFontFamily();
00547     style.resetFontWeight();
00548     style.resetFontStyle();
00549 }
00550 
00551 double TokenStyleElement::sizeFactor( const ContextStyle& context, double factor )
00552 {
00553     double basesize = context.layoutUnitPtToPt( context.getBaseSize() );
00554     switch ( m_mathSizeType ) {
00555     case AbsoluteSize:
00556         return m_mathSize / basesize;
00557     case RelativeSize:
00558         return m_mathSize;
00559     case PixelSize:
00560         // 3.2.2 says v-unit instead of h-unit, that's why we use Y and not X
00561         return context.pixelYToPt( m_mathSize ) / basesize;
00562     case NoSize:
00563         switch ( m_fontSizeType ) {
00564         case AbsoluteSize:
00565             return m_fontSize / basesize;
00566         case RelativeSize:
00567             return m_fontSize;
00568         case PixelSize:
00569             return context.pixelYToPt( m_fontSize ) / basesize;
00570         default:
00571             return factor;
00572         }
00573     default:
00574         break;
00575     }
00576     kdWarning( DEBUGID ) << k_funcinfo << " Unknown SizeType\n";
00577     return factor;
00578 }
00579 
00583 QString TokenStyleElement::getHtmlColor( const QString& colorStr ){
00584 
00585     QString colorname = colorStr.lower();
00586 
00587     if ( colorname ==  "black" ) 
00588         return "#000000";
00589     if ( colorname == "silver" )
00590         return "#C0C0C0";
00591     if ( colorname == "gray" )
00592         return "#808080";
00593     if ( colorname == "white" )
00594         return "#FFFFFF";
00595     if ( colorname == "maroon" )
00596         return "#800000";
00597     if ( colorname == "red" )
00598         return "#FF0000";
00599     if ( colorname == "purple" )
00600         return "#800080";
00601     if ( colorname == "fuchsia" )
00602         return "#FF00FF";
00603     if ( colorname == "green" )
00604         return "#008000";
00605     if ( colorname == "lime" )
00606         return "#00FF00";
00607     if ( colorname == "olive" )
00608         return "#808000";
00609     if ( colorname == "yellow" )
00610         return "#FFFF00";
00611     if ( colorname == "navy" )
00612         return "#000080";
00613     if ( colorname == "blue")
00614         return "#0000FF";
00615     if ( colorname == "teal" )
00616         return "#008080";
00617     if ( colorname == "aqua" )
00618         return "#00FFFF";
00619     kdWarning( DEBUGID ) << "Invalid HTML color: " << colorname << endl;
00620     return "#FFFFFF"; // ### Arbitrary selection of default color
00621 }
00622 
00623 
00624 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys