lib

paddedelement.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 "elementtype.h"
00021 #include "paddedelement.h"
00022 
00023 KFORMULA_NAMESPACE_BEGIN
00024 
00025 PaddedElement::PaddedElement( BasicElement* parent ) : SequenceElement( parent ),
00026                                                        m_widthType( NoSize ),
00027                                                        m_lspaceType( NoSize ),
00028                                                        m_heightType( NoSize ),
00029                                                        m_depthType( NoSize ),
00030                                                        m_widthRelative( false ),
00031                                                        m_lspaceRelative( false ),
00032                                                        m_heightRelative( false ),
00033                                                        m_depthRelative( false )
00034 {
00035 }
00036 
00041 void PaddedElement::calcSizes( const ContextStyle& context,
00042                                ContextStyle::TextStyle tstyle,
00043                                ContextStyle::IndexStyle istyle,
00044                                StyleAttributes& style )
00045 {
00046     double factor = style.sizeFactor();
00047 
00048     luPixel width = 0;
00049     luPixel height = 0;
00050     luPixel depth = 0;
00051 
00052     if ( !isEmpty() ) {
00053         // First, get content height and width
00054         for ( iterator it = begin(); it != end(); ++it ) {
00055             luPixel spaceBefore = 0;
00056             if ( it == begin() ) {
00057                 spaceBefore = context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) );
00058             }
00059             it->calcSizes( context, tstyle, istyle, style );
00060             width += it->getWidth() + spaceBefore;
00061             luPixel baseline = it->getBaseline();
00062             if ( baseline > -1 ) {
00063                 height = QMAX( height, baseline );
00064                 depth = QMAX( depth, it->getHeight() - baseline );
00065             }
00066             else {
00067                 luPixel bl = it->getHeight()/2 + context.axisHeight( tstyle, factor );
00068                 height = QMAX( height, bl );
00069                 depth = QMAX( depth, it->getHeight() - bl );
00070             }
00071         }
00072     }
00073     else {
00074         width = context.getEmptyRectWidth( factor );
00075         height = context.getEmptyRectHeight( factor );
00076         depth = 0;
00077     }
00078 
00079     luPixel left = calcSize( context, m_lspaceType, m_lspaceRelative, m_lspace, width, height, 0 );
00080     luPixel right = calcSize( context, m_widthType, m_widthRelative, m_width, width, height, width ) + left;
00081     luPixel down = calcSize( context, m_depthType, m_depthRelative, m_depth, width, height, depth );
00082     luPixel up = calcSize( context, m_heightType, m_heightRelative, m_height, width, height, height );
00083 
00084     // Check borders
00085     if ( right < 0 ) right = 0;
00086     if ( up + down < 0 ) up = down = 0;
00087     
00088     if ( ! isEmpty() ) {
00089         width = left;
00090         // Let's do all normal elements that have a base line.
00091         for ( iterator it = begin(); it != end(); ++it ) {
00092             luPixel spaceBefore = 0;
00093             if ( it == begin() ) {
00094                 spaceBefore = context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) );
00095             }
00096             it->calcSizes( context, tstyle, istyle, style );
00097             it->setX( width + spaceBefore );
00098             width += it->getWidth() + spaceBefore;
00099         }
00100 
00101         setWidth( right );
00102         setHeight( up + down );
00103         setBaseline( up );
00104         setChildrenPositions();
00105     }
00106     else {
00107         setWidth( right );
00108         setHeight( up + down );
00109         setBaseline( up );
00110     }
00111 }
00112 
00113 bool PaddedElement::readAttributesFromMathMLDom(const QDomElement& element)
00114 {
00115     if ( ! BasicElement::readAttributesFromMathMLDom( element ) ) {
00116         return false;
00117     }
00118 
00119     QString widthStr = element.attribute( "width" ).stripWhiteSpace().lower();
00120     if ( ! widthStr.isNull() ) {
00121         m_width = readSizeAttribute( widthStr, &m_widthType, &m_widthRelative );
00122     }
00123     QString lspaceStr = element.attribute( "lspace" ).stripWhiteSpace().lower();
00124     if ( ! lspaceStr.isNull() ) {
00125         m_lspace = readSizeAttribute( lspaceStr, &m_lspaceType, &m_lspaceRelative );
00126     }
00127     QString heightStr = element.attribute( "height" ).stripWhiteSpace().lower();
00128     if ( ! heightStr.isNull() ) {
00129         m_height = readSizeAttribute( heightStr, &m_heightType, &m_heightRelative );
00130     }
00131     QString depthStr = element.attribute( "depth" ).stripWhiteSpace().lower();
00132     if ( ! depthStr.isNull() ) {
00133         m_depth = readSizeAttribute( depthStr, &m_depthType, &m_depthRelative );
00134     }
00135 
00136     return true;
00137 }
00138 
00139 void PaddedElement::writeMathMLAttributes( QDomElement& element ) const
00140 {
00141     writeSizeAttribute( element, "width", m_widthType, m_width, m_widthRelative );
00142     writeSizeAttribute( element, "lspace", m_lspaceType, m_lspace, m_lspaceRelative );
00143     writeSizeAttribute( element, "height", m_heightType, m_height, m_heightRelative );
00144     writeSizeAttribute( element, "depth", m_depthType, m_depth, m_depthRelative );
00145 }
00146 
00147 double PaddedElement::readSizeAttribute( const QString& str, SizeType* st, bool* relative )
00148 {
00149     if ( st == 0 ){
00150         return -1;
00151     }
00152     if ( str[0] == '+' || str[0] == '-' ) {
00153         *relative = true;
00154     }
00155     int index = str.find( "width" );
00156     if ( index != -1 ) {
00157         int index2 = str.find( "%" );
00158         if ( index2 != -1 ) {
00159             return str2size( str.left( index2 ).stripWhiteSpace(), st, WidthRelativeSize ) / 100.0;
00160         }
00161         return str2size( str.left( index ).stripWhiteSpace(), st, WidthRelativeSize );
00162     }
00163     index = str.find( "height" );
00164     if ( index != -1 ) {
00165         int index2 = str.find( "%" );
00166         if ( index2 != -1 ) {
00167             return str2size( str.left( index2 ).stripWhiteSpace(), st, HeightRelativeSize ) / 100.0;
00168         }
00169         return str2size( str.left( index ).stripWhiteSpace(), st, HeightRelativeSize );
00170     }
00171     index = str.find( "%" );
00172     if ( index != -1 ) {
00173         return str2size( str.left( index ).stripWhiteSpace(), st, RelativeSize ) / 100.0;
00174     }
00175     index = str.find( "pt", 0, false );
00176     if ( index != -1 ) {
00177         return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize );
00178     }
00179     index = str.find( "mm", 0, false );
00180     if ( index != -1 ) {
00181         return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 72.0 / 20.54;
00182     }
00183     index = str.find( "cm", 0, false );
00184     if ( index != -1 ) {
00185         return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 72.0 / 2.54;
00186     }
00187     index = str.find( "in", 0, false );
00188     if ( index != -1 ) {
00189         return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 72.0;
00190     }
00191     index = str.find( "em", 0, false );
00192     if ( index != -1 ) {
00193         return str2size( str.left( index ).stripWhiteSpace(), st, RelativeSize );
00194     }
00195     index = str.find( "ex", 0, false );
00196     if ( index != -1 ) {
00197         return str2size( str.left( index ).stripWhiteSpace(), st, RelativeSize );
00198     }
00199     index = str.find( "pc", 0, false );
00200     if ( index != -1 ) {
00201         return str2size( str.left( index ).stripWhiteSpace(), st, AbsoluteSize ) * 12.0;
00202     }
00203     index = str.find( "px", 0, false );
00204     if ( index != -1 ) {
00205         return str2size( str.left( index ).stripWhiteSpace(), st, PixelSize );
00206     }
00207     // If there's no unit, assume 'pt'
00208     return str2size( str, st, AbsoluteSize );
00209 }
00210 
00211 double PaddedElement::str2size( const QString& str, SizeType *st, SizeType type )
00212 {
00213     bool ok;
00214     double size = str.toDouble( &ok );
00215     if ( ok ) {
00216         if ( st ) {
00217             *st = type;
00218         }
00219         return size;
00220     }
00221     if ( st ) {
00222         *st = NoSize;
00223     }
00224     return -1;
00225 }
00226 
00227 void PaddedElement::writeSizeAttribute( QDomElement element, const QString& str,
00228                                         SizeType st, bool relative, double s ) const
00229 {
00230     QString prefix;
00231     if ( relative ) {
00232         s < 0 ? prefix = "-" : prefix = "+" ;
00233     }
00234     switch ( st ) {
00235     case WidthRelativeSize:
00236         element.setAttribute( str, prefix + QString( "%1 width" ).arg( s ) );
00237         break;
00238     case HeightRelativeSize:
00239         element.setAttribute( str, prefix + QString( "%1 height" ).arg( s ) );
00240     case AbsoluteSize:
00241         element.setAttribute( str, prefix + QString( "%1pt" ).arg( s ) );
00242         break;
00243     case RelativeSize:
00244         element.setAttribute( str, prefix + QString( "%1%" ).arg( s * 100.0 ) );
00245         break;
00246     case PixelSize:
00247         element.setAttribute( str, prefix + QString( "%1px" ).arg( s ) );
00248         break;
00249     default:
00250         break;
00251     }
00252 }
00253 
00254 luPixel PaddedElement::calcSize( const ContextStyle& context, SizeType type, 
00255                                  bool relative, double length, luPixel width,
00256                                  luPixel height, luPixel defvalue )
00257 {
00258     luPixel value = defvalue;
00259     switch ( type ) {
00260     case AbsoluteSize:
00261         if ( relative )
00262             value += context.ptToLayoutUnitPt ( length );
00263         else
00264             value = context.ptToLayoutUnitPt( length );
00265         break;
00266     case RelativeSize:
00267         if ( relative )
00268             value += length * value;
00269         else
00270             value *= length;
00271         break;
00272     case WidthRelativeSize:
00273         if ( relative )
00274             value += length * width;
00275         else
00276             value = length * width;
00277         break;
00278     case HeightRelativeSize:
00279         if ( relative )
00280             value += length * height;
00281         else
00282             value = length * height;
00283         break;
00284     case PixelSize:
00285         if ( relative )
00286             value += context.pixelToLayoutUnitX( length );
00287         else
00288             value = context.pixelToLayoutUnitX( length );
00289         break;
00290     default:
00291         break;
00292     }
00293     return value;
00294 }
00295 
00296 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys