/* This file is part of the KDE project Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include <tqpainter.h> #include "basicelement.h" #include "tokenstyleelement.h" KFORMULA_NAMESPACE_BEGIN TokenStyleElement::TokenStyleElement( BasicElement* parent ) : SequenceElement( parent ), m_mathSizeType ( NoSize ), m_charStyle( anyChar ), m_charFamily( anyFamily ), m_mathColor( "#000000" ), m_mathBackground( "#FFFFFF" ), m_fontSizeType( NoSize ), m_customMathVariant( false ), m_customMathColor( false ), m_customMathBackground( false ), m_customFontWeight( false ), m_customFontStyle( false ), m_customFontFamily( false ), m_customColor( false ) { } void TokenStyleElement::calcSizes( const ContextStyle& context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes& style ) { setStyleSize( context, style ); setStyleVariant( style ); setStyleColor( style ); setStyleBackground( style ); inherited::calcSizes( context, tstyle, istyle, style ); resetStyle( style ); } void TokenStyleElement::draw( TQPainter& painter, const LuPixelRect& r, const ContextStyle& context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes& style, const LuPixelPoint& parentOrigin ) { setStyleSize( context, style ); setStyleVariant( style ); setStyleColor( style ); setStyleBackground( style ); if ( style.background() != TQt::color0 ) { painter.fillRect( context.layoutUnitToPixelX( parentOrigin.x() + getX() ), context.layoutUnitToPixelY( parentOrigin.y() + getY() ), context.layoutUnitToPixelX( getWidth() ), context.layoutUnitToPixelY( getHeight() ), style.background() ); } inherited::draw( painter, r, context, tstyle, istyle, style, parentOrigin ); resetStyle( style ); } bool TokenStyleElement::readAttributesFromMathMLDom( const TQDomElement& element ) { if ( !BasicElement::readAttributesFromMathMLDom( element ) ) { return false; } // MathML Section 3.2.2 TQString variantStr = element.attribute( "mathvariant" ); if ( !variantStr.isNull() ) { if ( variantStr == "normal" ) { setCharStyle( normalChar ); setCharFamily( normalFamily ); } else if ( variantStr == "bold" ) { setCharStyle( boldChar ); setCharFamily( normalFamily ); } else if ( variantStr == "italic" ) { setCharStyle( italicChar ); setCharFamily( normalFamily ); } else if ( variantStr == "bold-italic" ) { setCharStyle( boldItalicChar ); setCharFamily( normalFamily ); } else if ( variantStr == "double-struck" ) { setCharStyle( normalChar ); setCharFamily( doubleStruckFamily ); } else if ( variantStr == "bold-fraktur" ) { setCharStyle( boldChar ); setCharFamily( frakturFamily ); } else if ( variantStr == "script" ) { setCharStyle( normalChar ); setCharFamily( scriptFamily ); } else if ( variantStr == "bold-script" ) { setCharStyle( boldChar ); setCharFamily( scriptFamily ); } else if ( variantStr == "fraktur" ) { setCharStyle( boldChar ); setCharFamily( frakturFamily ); } else if ( variantStr == "sans-serif" ) { setCharStyle( normalChar ); setCharFamily( sansSerifFamily ); } else if ( variantStr == "bold-sans-serif" ) { setCharStyle( boldChar ); setCharFamily( sansSerifFamily ); } else if ( variantStr == "sans-serif-italic" ) { setCharStyle( italicChar ); setCharFamily( sansSerifFamily ); } else if ( variantStr == "sans-serif-bold-italic" ) { setCharStyle( boldItalicChar ); setCharFamily( sansSerifFamily ); } else if ( variantStr == "monospace" ) { setCharStyle( normalChar ); setCharFamily( monospaceFamily ); } } TQString sizeStr = element.attribute( "mathsize" ); if ( !sizeStr.isNull() ) { if ( sizeStr == "small" ) { setRelativeSize( 0.8 ); // ### Arbitrary size } else if ( sizeStr == "normal" ) { setRelativeSize( 1.0 ); } else if ( sizeStr == "big" ) { setRelativeSize( 1.2 ); // ### Arbitrary size } else { double s = getSize( sizeStr, &m_mathSizeType ); switch ( m_mathSizeType ) { case AbsoluteSize: setAbsoluteSize( s ); break; case RelativeSize: setRelativeSize( s ); break; case PixelSize: setPixelSize( s ); break; default: break; } } } TQString colorStr = element.attribute( "mathcolor" ); if ( !colorStr.isNull() ) { if ( colorStr[0] != '#' ) { setMathColor( TQColor( getHtmlColor( colorStr ) ) ); } else { setMathColor( TQColor( colorStr ) ); } } TQString backgroundStr = element.attribute( "mathbackground" ); if ( !backgroundStr.isNull() ) { if ( backgroundStr[0] != '#' ) { setMathBackground( TQColor( getHtmlColor( backgroundStr ) ) ); } else { setMathBackground( TQColor( backgroundStr ) ); } } // Deprecated attributes. See Section 3.2.2.1 sizeStr = element.attribute( "fontsize" ); if ( ! sizeStr.isNull() ) { if ( sizeStr == "small" ) { setRelativeSize( 0.8, true ); // ### Arbitrary size } else if ( sizeStr == "normal" ) { setRelativeSize( 1.0, true ); } else if ( sizeStr == "big" ) { setRelativeSize( 1.2, true ); // ### Arbitrary size } else { double s = getSize( sizeStr, &m_fontSizeType ); switch ( m_fontSizeType ) { case AbsoluteSize: setAbsoluteSize( s, true ); break; case RelativeSize: setRelativeSize( s, true ); break; case PixelSize: setPixelSize( s, true ); break; default: break; } } } TQString styleStr = element.attribute( "fontstyle" ); if ( ! styleStr.isNull() ) { if ( styleStr.lower() == "italic" ) { setFontStyle( true ); } else { setFontStyle( false ); } } TQString weightStr = element.attribute( "fontweight" ); if ( ! weightStr.isNull() ) { if ( weightStr.lower() == "bold" ) { setFontWeight( true ); } else { setFontWeight( false ); } } TQString familyStr = element.attribute( "fontfamily" ); if ( ! familyStr.isNull() ) { setFontFamily( familyStr ); } colorStr = element.attribute( "color" ); if ( ! colorStr.isNull() ) { if ( colorStr[0] != '#' ) { setColor( TQColor( getHtmlColor( colorStr ) ) ); } else { setColor( TQColor( colorStr ) ); } } return true; } void TokenStyleElement::writeMathMLAttributes( TQDomElement& element ) const { // mathvariant attribute if ( customMathVariant() ) { if ( charFamily() == normalFamily ) { if ( charStyle() == normalChar ) { element.setAttribute( "mathvariant", "normal" ); } else if ( charStyle() == boldChar ) { element.setAttribute( "mathvariant", "bold" ); } else if ( charStyle() == italicChar ) { element.setAttribute( "mathvariant", "italic" ); } else if ( charStyle() == boldItalicChar ) { element.setAttribute( "mathvariant", "bold-italic" ); } else { // anyChar or unknown, it's always an error kdWarning( DEBUGID ) << "Mathvariant: unknown style for normal family\n"; } } else if ( charFamily() == doubleStruckFamily ) { if ( charStyle() == normalChar ) { element.setAttribute( "mathvariant", "double-struck" ); } else { // Shouldn't happen, it's a bug kdWarning( DEBUGID ) << "Mathvariant: unknown style for double-struck family\n"; } } else if ( charFamily() == frakturFamily ) { if ( charStyle() == normalChar ) { element.setAttribute( "mathvariant", "fraktur" ); } else if ( charStyle() == boldChar ) { element.setAttribute( "mathvariant", "bold-fraktur" ); } else { kdWarning( DEBUGID ) << "Mathvariant: unknown style for fraktur family\n"; } } else if ( charFamily() == scriptFamily ) { if ( charStyle() == normalChar ) { element.setAttribute( "mathvariant", "script" ); } else if ( charStyle() == boldChar ) { element.setAttribute( "mathvariant", "bold-script" ); } else { // Shouldn't happen, it's a bug kdWarning( DEBUGID ) << "Mathvariant: unknown style for script family\n"; } } else if ( charFamily() == sansSerifFamily ) { if ( charStyle() == normalChar ) { element.setAttribute( "mathvariant", "sans-serif" ); } else if ( charStyle() == boldChar ) { element.setAttribute( "mathvariant", "bold-sans-serif" ); } else if ( charStyle() == italicChar ) { element.setAttribute( "mathvariant", "sans-serif-italic" ); } else if ( charStyle() == boldItalicChar ) { element.setAttribute( "mathvariant", "sans-serif-bold-italic" ); } else { kdWarning( DEBUGID ) << "Mathvariant: unknown style for sans serif family\n"; } } else if ( charFamily() == monospaceFamily ) { if ( charStyle() == normalChar ) { element.setAttribute( "mathvariant", "monospace" ); } else { kdWarning( DEBUGID ) << "Mathvariant: unknown style for monospace family\n"; } } else { kdWarning( DEBUGID ) << "Mathvariant: unknown family\n"; } } // mathsize attribute switch ( m_mathSizeType ) { case AbsoluteSize: element.setAttribute( "mathsize", TQString( "%1pt" ).arg( m_mathSize ) ); break; case RelativeSize: element.setAttribute( "mathsize", TQString( "%1%" ).arg( m_mathSize * 100.0 ) ); break; case PixelSize: element.setAttribute( "mathsize", TQString( "%1px" ).arg( m_mathSize ) ); break; default: break; } // mathcolor attribute if ( customMathColor() ) { element.setAttribute( "mathcolor", mathColor().name() ); } // mathbackground attribute if ( customMathBackground() ) { element.setAttribute( "mathbackground", mathBackground().name() ); } // Deprecated MathML 1.01 Attributes // fontsize attribute switch ( m_fontSizeType ) { case AbsoluteSize: element.setAttribute( "fontsize", TQString( "%1pt" ).arg( m_fontSize ) ); break; case RelativeSize: element.setAttribute( "fontsize", TQString( "%1%" ).arg( m_fontSize * 100.0 ) ); break; case PixelSize: element.setAttribute( "fontsize", TQString( "%3px" ).arg( m_fontSize ) ); break; default: break; } // fontweight attribute if ( customFontWeight() ) { element.setAttribute( "fontweight", fontWeight() ? "bold" : "normal" ); } // fontstyle attribute if ( customFontStyle() ) { element.setAttribute( "fontstyle", fontStyle() ? "italic" : "normal" ); } // fontfamily attribute if ( customFontFamily() ) { element.setAttribute( "fontfamily", fontFamily() ); } // color attribute if ( customColor() ) { element.setAttribute( "color", color().name() ); } } void TokenStyleElement::setAbsoluteSize( double s, bool fontsize ) { kdDebug( DEBUGID) << "Setting absolute size: " << s << endl; if ( fontsize ) { m_fontSizeType = AbsoluteSize; m_fontSize = s; } else { m_mathSizeType = AbsoluteSize; m_mathSize = s; } } void TokenStyleElement::setRelativeSize( double f, bool fontsize ) { kdDebug( DEBUGID) << "Setting relative size: " << f << endl; if ( fontsize ) { m_fontSizeType = RelativeSize; m_fontSize = f; } else { m_mathSizeType = RelativeSize; m_mathSize = f; } } void TokenStyleElement::setPixelSize( double px, bool fontsize ) { kdDebug( DEBUGID) << "Setting pixel size: " << px << endl; if ( fontsize ) { m_fontSizeType = PixelSize; m_fontSize = px; } else { m_mathSizeType = PixelSize; m_mathSize = px; } } void TokenStyleElement::setStyleSize( const ContextStyle& context, StyleAttributes& style ) { style.setSizeFactor( sizeFactor( context, style.sizeFactor() ) ); } void TokenStyleElement::setStyleVariant( StyleAttributes& style ) { if ( customMathVariant() || style.customMathVariant() ) { style.setCustomMathVariant ( true ); style.setCustomFontWeight( false ); style.setCustomFontStyle( false ); style.setCustomFont( false ); if ( customMathVariant() ) { style.setCharFamily ( charFamily() ); style.setCharStyle( charStyle() ); } else { style.setCharFamily( style.charFamily() ); style.setCharStyle( style.charStyle() ); } } else { style.setCustomMathVariant( false ); if ( customFontFamily() ) { style.setCustomFont( true ); style.setFont( TQFont(fontFamily()) ); } bool fontweight = false; if ( customFontWeight() || style.customFontWeight() ) { style.setCustomFontWeight( true ); if ( customFontWeight() ) { fontweight = fontWeight(); } else { fontweight = style.fontWeight(); } style.setFontWeight( fontweight ); } else { style.setCustomFontWeight( false ); } bool fontstyle = false; if ( style.customFontStyle() ) { style.setCustomFontStyle( true ); fontstyle = style.fontStyle(); style.setFontStyle( fontstyle ); } else { style.setCustomFontStyle( false ); } if ( customFontStyle() ) { fontstyle = fontStyle(); } if ( fontweight && fontstyle ) { style.setCharStyle( boldItalicChar ); } else if ( fontweight && ! fontstyle ) { style.setCharStyle( boldChar ); } else if ( ! fontweight && fontstyle ) { style.setCharStyle( italicChar ); } else { style.setCharStyle( normalChar ); } } } void TokenStyleElement::setStyleColor( StyleAttributes& style ) { if ( customMathColor() ) { style.setColor( mathColor() ); } else if ( customColor() ) { style.setColor( color() ); } else { style.setColor( style.color() ); } } void TokenStyleElement::setStyleBackground( StyleAttributes& style ) { if ( customMathBackground() ) { style.setBackground( mathBackground() ); } else { style.setBackground( style.background() ); } } void TokenStyleElement::resetStyle( StyleAttributes& style ) { style.resetSize(); style.resetCharStyle(); style.resetCharFamily(); style.resetColor(); style.resetBackground(); style.resetFontFamily(); style.resetFontWeight(); style.resetFontStyle(); } double TokenStyleElement::sizeFactor( const ContextStyle& context, double factor ) { double basesize = context.layoutUnitPtToPt( context.getBaseSize() ); switch ( m_mathSizeType ) { case AbsoluteSize: return m_mathSize / basesize; case RelativeSize: return m_mathSize; case PixelSize: // 3.2.2 says v-unit instead of h-unit, that's why we use Y and not X return context.pixelYToPt( m_mathSize ) / basesize; case NoSize: switch ( m_fontSizeType ) { case AbsoluteSize: return m_fontSize / basesize; case RelativeSize: return m_fontSize; case PixelSize: return context.pixelYToPt( m_fontSize ) / basesize; default: return factor; } default: break; } kdWarning( DEBUGID ) << k_funcinfo << " Unknown SizeType\n"; return factor; } /** * Return RGB string from HTML Colors. See HTML Spec, section 6.5 */ TQString TokenStyleElement::getHtmlColor( const TQString& colorStr ){ TQString colorname = colorStr.lower(); if ( colorname == "black" ) return "#000000"; if ( colorname == "silver" ) return "#C0C0C0"; if ( colorname == "gray" ) return "#808080"; if ( colorname == "white" ) return "#FFFFFF"; if ( colorname == "maroon" ) return "#800000"; if ( colorname == "red" ) return "#FF0000"; if ( colorname == "purple" ) return "#800080"; if ( colorname == "fuchsia" ) return "#FF00FF"; if ( colorname == "green" ) return "#008000"; if ( colorname == "lime" ) return "#00FF00"; if ( colorname == "olive" ) return "#808000"; if ( colorname == "yellow" ) return "#FFFF00"; if ( colorname == "navy" ) return "#000080"; if ( colorname == "blue") return "#0000FF"; if ( colorname == "teal" ) return "#008080"; if ( colorname == "aqua" ) return "#00FFFF"; kdWarning( DEBUGID ) << "Invalid HTML color: " << colorname << endl; return "#FFFFFF"; // ### Arbitrary selection of default color } KFORMULA_NAMESPACE_END