summaryrefslogtreecommitdiffstats
path: root/lib/kformula/tokenstyleelement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kformula/tokenstyleelement.cpp')
-rw-r--r--lib/kformula/tokenstyleelement.cpp624
1 files changed, 624 insertions, 0 deletions
diff --git a/lib/kformula/tokenstyleelement.cpp b/lib/kformula/tokenstyleelement.cpp
new file mode 100644
index 00000000..fcce16e7
--- /dev/null
+++ b/lib/kformula/tokenstyleelement.cpp
@@ -0,0 +1,624 @@
+/* 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