diff options
Diffstat (limited to 'lib/kformula/paddedelement.cc')
-rw-r--r-- | lib/kformula/paddedelement.cc | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/lib/kformula/paddedelement.cc b/lib/kformula/paddedelement.cc new file mode 100644 index 00000000..f48d4503 --- /dev/null +++ b/lib/kformula/paddedelement.cc @@ -0,0 +1,296 @@ +/* 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 "elementtype.h" +#include "paddedelement.h" + +KFORMULA_NAMESPACE_BEGIN + +PaddedElement::PaddedElement( BasicElement* parent ) : SequenceElement( parent ), + m_widthType( NoSize ), + m_lspaceType( NoSize ), + m_heightType( NoSize ), + m_depthType( NoSize ), + m_widthRelative( false ), + m_lspaceRelative( false ), + m_heightRelative( false ), + m_depthRelative( false ) +{ +} + +/** + * Calculates our width and height and + * our children's parentPosition. + */ +void PaddedElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style ) +{ + double factor = style.sizeFactor(); + + luPixel width = 0; + luPixel height = 0; + luPixel depth = 0; + + if ( !isEmpty() ) { + // First, get content height and width + for ( iterator it = begin(); it != end(); ++it ) { + luPixel spaceBefore = 0; + if ( it == begin() ) { + spaceBefore = context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) ); + } + it->calcSizes( context, tstyle, istyle, style ); + width += it->getWidth() + spaceBefore; + luPixel baseline = it->getBaseline(); + if ( baseline > -1 ) { + height = QMAX( height, baseline ); + depth = QMAX( depth, it->getHeight() - baseline ); + } + else { + luPixel bl = it->getHeight()/2 + context.axisHeight( tstyle, factor ); + height = QMAX( height, bl ); + depth = QMAX( depth, it->getHeight() - bl ); + } + } + } + else { + width = context.getEmptyRectWidth( factor ); + height = context.getEmptyRectHeight( factor ); + depth = 0; + } + + luPixel left = calcSize( context, m_lspaceType, m_lspaceRelative, m_lspace, width, height, 0 ); + luPixel right = calcSize( context, m_widthType, m_widthRelative, m_width, width, height, width ) + left; + luPixel down = calcSize( context, m_depthType, m_depthRelative, m_depth, width, height, depth ); + luPixel up = calcSize( context, m_heightType, m_heightRelative, m_height, width, height, height ); + + // Check borders + if ( right < 0 ) right = 0; + if ( up + down < 0 ) up = down = 0; + + if ( ! isEmpty() ) { + width = left; + // Let's do all normal elements that have a base line. + for ( iterator it = begin(); it != end(); ++it ) { + luPixel spaceBefore = 0; + if ( it == begin() ) { + spaceBefore = context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) ); + } + it->calcSizes( context, tstyle, istyle, style ); + it->setX( width + spaceBefore ); + width += it->getWidth() + spaceBefore; + } + + setWidth( right ); + setHeight( up + down ); + setBaseline( up ); + setChildrenPositions(); + } + else { + setWidth( right ); + setHeight( up + down ); + setBaseline( up ); + } +} + +bool PaddedElement::readAttributesFromMathMLDom(const QDomElement& element) +{ + if ( ! BasicElement::readAttributesFromMathMLDom( element ) ) { + return false; + } + + QString widthStr = element.attribute( "width" ).stripWhiteSpace().lower(); + if ( ! widthStr.isNull() ) { + m_width = readSizeAttribute( widthStr, &m_widthType, &m_widthRelative ); + } + QString lspaceStr = element.attribute( "lspace" ).stripWhiteSpace().lower(); + if ( ! lspaceStr.isNull() ) { + m_lspace = readSizeAttribute( lspaceStr, &m_lspaceType, &m_lspaceRelative ); + } + QString heightStr = element.attribute( "height" ).stripWhiteSpace().lower(); + if ( ! heightStr.isNull() ) { + m_height = readSizeAttribute( heightStr, &m_heightType, &m_heightRelative ); + } + QString depthStr = element.attribute( "depth" ).stripWhiteSpace().lower(); + if ( ! depthStr.isNull() ) { + m_depth = readSizeAttribute( depthStr, &m_depthType, &m_depthRelative ); + } + + return true; +} + +void PaddedElement::writeMathMLAttributes( QDomElement& element ) const +{ + writeSizeAttribute( element, "width", m_widthType, m_width, m_widthRelative ); + writeSizeAttribute( element, "lspace", m_lspaceType, m_lspace, m_lspaceRelative ); + writeSizeAttribute( element, "height", m_heightType, m_height, m_heightRelative ); + writeSizeAttribute( element, "depth", m_depthType, m_depth, m_depthRelative ); +} + +double PaddedElement::readSizeAttribute( const QString& str, SizeType* st, bool* relative ) +{ + if ( st == 0 ){ + return -1; + } + if ( str[0] == '+' || str[0] == '-' ) { + *relative = true; + } + int index = str.find( "width" ); + if ( index != -1 ) { + int index2 = str.find( "%" ); + if ( index2 != -1 ) { + return str2size( str.left( index2 ).stripWhiteSpace(), st, WidthRelativeSize ) / 100.0; + } + return str2size( str.left( index ).stripWhiteSpace(), st, WidthRelativeSize ); + } + index = str.find( "height" ); + if ( index != -1 ) { + int index2 = str.find( "%" ); + if ( index2 != -1 ) { + return str2size( str.left( index2 ).stripWhiteSpace(), st, HeightRelativeSize ) / 100.0; + } + return str2size( str.left( index ).stripWhiteSpace(), st, HeightRelativeSize ); + } + index = str.find( "%" ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, RelativeSize ) / 100.0; + } + index = str.find( "pt", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ); + } + index = str.find( "mm", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 72.0 / 20.54; + } + index = str.find( "cm", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 72.0 / 2.54; + } + index = str.find( "in", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 72.0; + } + index = str.find( "em", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, RelativeSize ); + } + index = str.find( "ex", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, RelativeSize ); + } + index = str.find( "pc", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 12.0; + } + index = str.find( "px", 0, false ); + if ( index != -1 ) { + return str2size( str.left( index ).stripWhiteSpace(), st, PixelSize ); + } + // If there's no unit, assume 'pt' + return str2size( str, st, AbsoluteSize ); +} + +double PaddedElement::str2size( const QString& str, SizeType *st, SizeType type ) +{ + bool ok; + double size = str.toDouble( &ok ); + if ( ok ) { + if ( st ) { + *st = type; + } + return size; + } + if ( st ) { + *st = NoSize; + } + return -1; +} + +void PaddedElement::writeSizeAttribute( QDomElement element, const QString& str, + SizeType st, bool relative, double s ) const +{ + QString prefix; + if ( relative ) { + s < 0 ? prefix = "-" : prefix = "+" ; + } + switch ( st ) { + case WidthRelativeSize: + element.setAttribute( str, prefix + QString( "%1 width" ).arg( s ) ); + break; + case HeightRelativeSize: + element.setAttribute( str, prefix + QString( "%1 height" ).arg( s ) ); + case AbsoluteSize: + element.setAttribute( str, prefix + QString( "%1pt" ).arg( s ) ); + break; + case RelativeSize: + element.setAttribute( str, prefix + QString( "%1%" ).arg( s * 100.0 ) ); + break; + case PixelSize: + element.setAttribute( str, prefix + QString( "%1px" ).arg( s ) ); + break; + default: + break; + } +} + +luPixel PaddedElement::calcSize( const ContextStyle& context, SizeType type, + bool relative, double length, luPixel width, + luPixel height, luPixel defvalue ) +{ + luPixel value = defvalue; + switch ( type ) { + case AbsoluteSize: + if ( relative ) + value += context.ptToLayoutUnitPt ( length ); + else + value = context.ptToLayoutUnitPt( length ); + break; + case RelativeSize: + if ( relative ) + value += length * value; + else + value *= length; + break; + case WidthRelativeSize: + if ( relative ) + value += length * width; + else + value = length * width; + break; + case HeightRelativeSize: + if ( relative ) + value += length * height; + else + value = length * height; + break; + case PixelSize: + if ( relative ) + value += context.pixelToLayoutUnitX( length ); + else + value = context.pixelToLayoutUnitX( length ); + break; + default: + break; + } + return value; +} + +KFORMULA_NAMESPACE_END |