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