diff options
Diffstat (limited to 'lib/kformula/spaceelement.cpp')
-rw-r--r-- | lib/kformula/spaceelement.cpp | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/lib/kformula/spaceelement.cpp b/lib/kformula/spaceelement.cpp new file mode 100644 index 00000000..7d372360 --- /dev/null +++ b/lib/kformula/spaceelement.cpp @@ -0,0 +1,431 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Andrea Rizzi <[email protected]> + Ulrich Kuettler <[email protected]> + Copyright (C) 2006 Alfredo Beaumont Sainz <[email protected]> + + 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 <tqfontmetrics.h> +#include <tqpainter.h> + +#include <kdebug.h> +#include <kprinter.h> + +#include "contextstyle.h" +#include "elementvisitor.h" +#include "spaceelement.h" + + +KFORMULA_NAMESPACE_BEGIN + + +SpaceElement::SpaceElement( SpaceWidth space, bool tab, BasicElement* parent ) + : BasicElement( parent ), + m_tab( tab ), + m_widthType( NoSize ), + m_heightType( NoSize ), + m_depthType( NoSize ), + m_lineBreak( NoBreakType ) +{ + // Backwards compatibility with KFO format + switch ( space ) { + case NEGTHIN: + m_widthType = NegativeThinMathSpace; + break; + case THIN: + m_widthType = ThinMathSpace; + break; + case MEDIUM: + m_widthType = MediumMathSpace; + break; + case THICK: + m_widthType = ThickMathSpace; + break; + case QUAD: + m_widthType = VeryVeryThickMathSpace; + break; + } +} + + +SpaceElement::SpaceElement( const SpaceElement& other ) + : BasicElement( other ), + m_widthType( other.m_widthType ), + m_width( other.m_width ), + m_heightType( other.m_heightType ), + m_height( other.m_height ), + m_depthType( other.m_depthType ), + m_depth( other.m_depth ), + m_lineBreak( other.m_lineBreak ) +{ +} + + +bool SpaceElement::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +void SpaceElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle /*istyle*/, + StyleAttributes& style ) +{ + double factor = style.sizeFactor(); + luPt mySize = context.getAdjustedSize( tstyle, factor ); + TQFont font = context.getDefaultFont(); + font.setPointSize( mySize ); + + TQFontMetrics fm( font ); + TQChar w = 'M'; + LuPixelRect hbound = fm.boundingRect( w ); + TQChar h = 'x'; + LuPixelRect vbound = fm.boundingRect( h ); + + double width = style.getSpace( m_widthType, m_width ); + if ( m_widthType == AbsoluteSize ) { + width = m_width / context.layoutUnitPtToPt( context.getBaseSize() ); + } + else if ( m_widthType == PixelSize ) { + width = context.pixelYToPt( m_width ) / context.layoutUnitPtToPt( context.getBaseSize() ); + } + double height = style.getSpace( m_heightType, m_height ); + if ( m_heightType == AbsoluteSize ) { + height = m_height / context.layoutUnitPtToPt( context.getBaseSize() ); + } + else if ( m_heightType == PixelSize ) { + height = context.pixelYToPt( m_height ) / context.layoutUnitPtToPt( context.getBaseSize() ); + } + double depth = style.getSpace( m_depthType, m_depth ); + if ( m_depthType == AbsoluteSize ) { + depth = m_depth / context.layoutUnitPtToPt( context.getBaseSize() ); + } + else if ( m_depthType == PixelSize ) { + depth = context.pixelYToPt( m_depth ) / context.layoutUnitPtToPt( context.getBaseSize() ); + } + + setWidth( hbound.width() * width ); + setHeight( vbound.height() * height + vbound.height() * depth ); + setBaseline( vbound.height() * height ); + + if ( m_tab ) { + getParent()->registerTab( this ); + } +} + +void SpaceElement::draw( TQPainter& painter, const LuPixelRect& /*r*/, + const ContextStyle& context, + ContextStyle::TextStyle /*tstyle*/, + ContextStyle::IndexStyle /*istyle*/, + StyleAttributes& /*style*/, + const LuPixelPoint& parentOrigin ) +{ + LuPixelPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); + // there is such a thing as negative space! + //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) + // return; + + if ( context.edit() ) { + painter.setPen( context.getEmptyColor() ); + painter.drawLine( context.layoutUnitToPixelX( myPos.x() ), + context.layoutUnitToPixelY( myPos.y()+getHeight() ), + context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ), + context.layoutUnitToPixelY( myPos.y()+getHeight() ) ); + painter.drawLine( context.layoutUnitToPixelX( myPos.x() ), + context.layoutUnitToPixelY( myPos.y()+getHeight() ), + context.layoutUnitToPixelX( myPos.x() ), + context.layoutUnitToPixelY( myPos.y()+getHeight()-getHeight()/5 ) ); + painter.drawLine( context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ), + context.layoutUnitToPixelY( myPos.y()+getHeight() ), + context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ), + context.layoutUnitToPixelY( myPos.y()+getHeight()-getHeight()/5 ) ); + } +} + + +void SpaceElement::writeDom(TQDomElement element) +{ + BasicElement::writeDom(element); + switch ( m_widthType ) { + case NegativeVeryVeryThinMathSpace: + case NegativeVeryThinMathSpace: + case NegativeThinMathSpace: + case NegativeMediumMathSpace: + case NegativeThickMathSpace: + case NegativeVeryThickMathSpace: + case NegativeVeryVeryThickMathSpace: + element.setAttribute( "WIDTH", "negthin" ); + break; + case VeryVeryThinMathSpace: + case VeryThinMathSpace: + case ThinMathSpace: + element.setAttribute( "WIDTH", "thin" ); + break; + case MediumMathSpace: + element.setAttribute( "WIDTH", "medium" ); + break; + case ThickMathSpace: + element.setAttribute( "WIDTH", "thick" ); + break; + case VeryThickMathSpace: + case VeryVeryThickMathSpace: + element.setAttribute( "WIDTH", "quad" ); + break; + case AbsoluteSize: + case RelativeSize: + case PixelSize: + if ( m_width < 0 ) { + element.setAttribute( "WIDTH", "negthin" ); + } + else { + element.setAttribute( "WIDTH", "thin" ); + } + default: + break; + } + if ( m_tab ) { + element.setAttribute( "TAB", "true" ); + } +} + +bool SpaceElement::readAttributesFromDom( TQDomElement element ) +{ + if ( !BasicElement::readAttributesFromDom( element ) ) { + return false; + } + TQString widthStr = element.attribute( "WIDTH" ); + if( !widthStr.isNull() ) { + if ( widthStr.lower() == "quad" ) { + m_widthType = VeryVeryThickMathSpace; + } + else if ( widthStr.lower() == "thick" ) { + m_widthType = ThickMathSpace; + } + else if ( widthStr.lower() == "medium" ) { + m_widthType = MediumMathSpace; + } + else if ( widthStr.lower() == "negthin" ) { + m_widthType = NegativeThinMathSpace; + } + else { + m_widthType = ThinMathSpace; + } + } + else { + return false; + } + TQString tabStr = element.attribute( "TAB" ); + m_tab = !tabStr.isNull(); + return true; +} + +bool SpaceElement::readContentFromDom(TQDomNode& node) +{ + return BasicElement::readContentFromDom( node ); +} + +bool SpaceElement::readAttributesFromMathMLDom(const TQDomElement& element) +{ + if ( ! BasicElement::readAttributesFromMathMLDom( element ) ) { + return false; + } + + TQString widthStr = element.attribute( "width" ).stripWhiteSpace().lower(); + if ( ! widthStr.isNull() ) { + m_width = getSize( widthStr, &m_widthType ); + if ( m_widthType == NoSize ) { + m_widthType = getSpace( widthStr ); + } + } + TQString heightStr = element.attribute( "height" ).stripWhiteSpace().lower(); + if ( ! heightStr.isNull() ) { + m_height = getSize( heightStr, &m_heightType ); + } + TQString depthStr = element.attribute( "depth" ).stripWhiteSpace().lower(); + if ( ! depthStr.isNull() ) { + m_depth = getSize( depthStr, &m_depthType ); + } + TQString linebreakStr = element.attribute( "linebreak" ).stripWhiteSpace().lower(); + if ( ! linebreakStr.isNull() ) { + if ( linebreakStr == "auto" ) { + m_lineBreak = AutoBreak; + } + else if ( linebreakStr == "newline" ) { + m_lineBreak = NewLineBreak; + } + else if ( linebreakStr == "indentingnewline" ) { + m_lineBreak = IndentingNewLineBreak; + } + else if ( linebreakStr == "nobreak" ) { + m_lineBreak = NoBreak; + } + else if ( linebreakStr == "goodbreak" ) { + m_lineBreak = GoodBreak; + } + else if ( linebreakStr == "badbreak" ) { + m_lineBreak = BadBreak; + } + } + return true; +} + +void SpaceElement::writeMathMLAttributes( TQDomElement& element ) const +{ + switch ( m_widthType ) { + case AbsoluteSize: + element.setAttribute( "width", TQString( "%1pt" ).arg( m_width ) ); + break; + case RelativeSize: + element.setAttribute( "width", TQString( "%1%" ).arg( m_width * 100.0 ) ); + break; + case PixelSize: + element.setAttribute( "width", TQString( "%1px" ).arg( m_width ) ); + break; + case NegativeVeryVeryThinMathSpace: + element.setAttribute( "width", "negativeveryverythinmathspace" ); + break; + case NegativeVeryThinMathSpace: + element.setAttribute( "width", "negativeverythinmathspace" ); + break; + case NegativeThinMathSpace: + element.setAttribute( "width", "negativethinmathspace" ); + break; + case NegativeMediumMathSpace: + element.setAttribute( "width", "negativemediummathspace" ); + break; + case NegativeThickMathSpace: + element.setAttribute( "width", "negativethickmathspace" ); + break; + case NegativeVeryThickMathSpace: + element.setAttribute( "width", "negativeverythickmathspace" ); + break; + case NegativeVeryVeryThickMathSpace: + element.setAttribute( "width", "negativeveryverythickmathspace" ); + break; + case VeryVeryThinMathSpace: + element.setAttribute( "width", "veryverythinmathspace" ); + break; + case VeryThinMathSpace: + element.setAttribute( "width", "verythinmathspace" ); + break; + case ThinMathSpace: + element.setAttribute( "width", "thinmathspace" ); + break; + case MediumMathSpace: + element.setAttribute( "width", "mediummathspace" ); + break; + case ThickMathSpace: + element.setAttribute( "width", "thickmathspace" ); + break; + case VeryThickMathSpace: + element.setAttribute( "width", "verythickmathspace" ); + break; + case VeryVeryThickMathSpace: + element.setAttribute( "width", "veryverythickmathspace" ); + break; + default: + break; + } + switch ( m_heightType ) { + case AbsoluteSize: + element.setAttribute( "height", TQString( "%1pt" ).arg( m_height ) ); + break; + case RelativeSize: + element.setAttribute( "height", TQString( "%1%" ).arg( m_height * 100.0 ) ); + break; + case PixelSize: + element.setAttribute( "height", TQString( "%1px" ).arg( m_height ) ); + break; + default: + break; + } + switch ( m_depthType ) { + case AbsoluteSize: + element.setAttribute( "depth", TQString( "%1pt" ).arg( m_depth ) ); + break; + case RelativeSize: + element.setAttribute( "depth", TQString( "%1%" ).arg( m_depth * 100.0 ) ); + break; + case PixelSize: + element.setAttribute( "depth", TQString( "%1px" ).arg( m_depth ) ); + break; + default: + break; + } + switch ( m_lineBreak ) { + case AutoBreak: + element.setAttribute( "linebreak", "auto" ); + break; + case NewLineBreak: + element.setAttribute( "linebreak", "newline" ); + break; + case IndentingNewLineBreak: + element.setAttribute( "linebreak", "indentingnewline" ); + break; + case NoBreak: + element.setAttribute( "linebreak", "nobreak" ); + break; + case GoodBreak: + element.setAttribute( "linebreak", "goodbreak" ); + break; + case BadBreak: + element.setAttribute( "linebreak", "badbreak" ); + break; + default: + break; + } +} + +TQString SpaceElement::toLatex() +{ + switch ( m_widthType ) { + case NegativeVeryVeryThinMathSpace: + case NegativeVeryThinMathSpace: + case NegativeThinMathSpace: + case NegativeMediumMathSpace: + case NegativeThickMathSpace: + case NegativeVeryThickMathSpace: + case NegativeVeryVeryThickMathSpace: + return "\\!"; + case VeryVeryThinMathSpace: + case VeryThinMathSpace: + case ThinMathSpace: + return "\\,"; + case MediumMathSpace: + return "\\>"; + case ThickMathSpace: + return "\\;"; + case VeryThickMathSpace: + case VeryVeryThickMathSpace: + return "\\quad "; + case AbsoluteSize: + case RelativeSize: + case PixelSize: + if ( m_width < 0 ) { + return "\\!"; + } + else { + return "\\,"; + } + default: + break; + } + return ""; +} + +KFORMULA_NAMESPACE_END |