00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "AttributeManager.h"
00021 #include "BasicElement.h"
00022 #include "ElementFactory.h"
00023 #include <KoUnit.h>
00024 #include <KoViewConverter.h>
00025 #include <KoPostscriptPaintDevice.h>
00026 #include <QFontMetricsF>
00027 #include <QColor>
00028 #include <kdebug.h>
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #define POINT_TO_MM(px) ((px)*0.352777167)
00039 #define MM_TO_POINT(mm) ((mm)*2.83465058)
00040 #define POINT_TO_CM(px) ((px)*0.0352777167)
00041 #define CM_TO_POINT(cm) ((cm)*28.3465058)
00042 #define POINT_TO_DM(px) ((px)*0.00352777167)
00043 #define DM_TO_POINT(dm) ((dm)*283.465058)
00044 #define POINT_TO_INCH(px) ((px)*0.01388888888889)
00045 #define INCH_TO_POINT(inch) ((inch)*72.0)
00046 #define MM_TO_INCH(mm) ((mm)*0.039370147)
00047 #define INCH_TO_MM(inch) ((inch)*25.399956)
00048 #define POINT_TO_PI(px)((px)*0.083333333)
00049 #define POINT_TO_CC(px)((px)*0.077880997)
00050 #define PI_TO_POINT(pi)((pi)*12)
00051 #define CC_TO_POINT(cc)((cc)*12.840103)
00052
00053 AttributeManager::AttributeManager()
00054 {
00055 m_viewConverter = 0;
00056 }
00057
00058 AttributeManager::~AttributeManager()
00059 {}
00060
00061 QString AttributeManager::findValue( const QString& attribute, const BasicElement* element ) const
00062 {
00063
00064 QString value = element->attribute( attribute );
00065 if( !value.isEmpty() ) {
00066
00067 return value;
00068 }
00069
00070 BasicElement* tmpParent = element->parentElement();
00071 while( tmpParent )
00072 {
00073 value = tmpParent->inheritsAttribute( attribute );
00074 if( !value.isEmpty() ) {
00075
00076 return value;
00077 }
00078 else {
00079 tmpParent = tmpParent->parentElement();
00080 }
00081 }
00082
00083
00084
00085 return element->attributesDefaultValue( attribute );
00086 }
00087
00088 bool AttributeManager::boolOf( const QString& attribute,
00089 const BasicElement* element ) const
00090 {
00091 return findValue( attribute, element ) == "true";
00092 }
00093
00094 double AttributeManager::doubleOf( const QString& attribute,
00095 const BasicElement* element ) const
00096 {
00097
00098 return lengthToPixels(parseUnit( findValue( attribute, element ), element ), element, attribute);
00099 }
00100
00101 QList<double> AttributeManager::doubleListOf( const QString& attribute,
00102 const BasicElement* element ) const
00103 {
00104 QList<double> doubleList;
00105 QStringList tmp = findValue( attribute, element ).split( ' ' );
00106 foreach( const QString &doubleValue, tmp )
00107 doubleList << lengthToPixels( parseUnit( doubleValue, element ), element, attribute);
00108
00109 return doubleList;
00110 }
00111
00112 QString AttributeManager::stringOf( const QString& attribute, const BasicElement* element ) const
00113 {
00114 return findValue( attribute, element );
00115 }
00116
00117 QColor AttributeManager::colorOf( const QString& attribute, const BasicElement* element ) const
00118 {
00119 QString tmpColor = findValue( attribute, element );
00120 if( attribute == "mathbackground" && tmpColor.isEmpty() )
00121 return Qt::transparent;
00122
00123 return QColor( tmpColor );
00124 }
00125
00126 Align AttributeManager::alignOf( const QString& attribute, const BasicElement* element ) const
00127 {
00128 return parseAlign( findValue( attribute, element ) );
00129 }
00130
00131 QList<Align> AttributeManager::alignListOf( const QString& attribute,
00132 const BasicElement* element ) const
00133 {
00134 QList<Align> alignList;
00135 QStringList tmpList = findValue( attribute, element ).split( ' ' );
00136
00137 foreach( const QString &tmp, tmpList )
00138 alignList << parseAlign( tmp );
00139
00140 return alignList;
00141 }
00142
00143 Qt::PenStyle AttributeManager::penStyleOf( const QString& attribute,
00144 const BasicElement* element ) const
00145 {
00146 return parsePenStyle( findValue( attribute, element ) );
00147 }
00148
00149 QList<Qt::PenStyle> AttributeManager::penStyleListOf( const QString& attribute,
00150 const BasicElement* element ) const
00151 {
00152 QList<Qt::PenStyle> penStyleList;
00153 QStringList tmpList = findValue( attribute, element ).split( ' ' );
00154
00155 foreach( const QString &tmp, tmpList )
00156 penStyleList << parsePenStyle( tmp );
00157
00158 return penStyleList;
00159 }
00160
00161 int AttributeManager::scriptLevel( const BasicElement* parent, int index ) const
00162 {
00163 ElementType parentType = parent->elementType();
00164 int current_scaleLevel = parent->scaleLevel();
00165
00167 switch(parentType) {
00168 case Fraction:
00169 if( parent->displayStyle() == false )
00170 return current_scaleLevel+1;
00171 else
00172 return current_scaleLevel;
00173 case Style: {
00174 QString tmp = parent->attribute( "scriptlevel" );
00175 if( tmp.startsWith( '+' ) )
00176 return current_scaleLevel + tmp.remove(0,1).toInt();
00177 if( tmp.startsWith( '-' ) )
00178 return current_scaleLevel - tmp.remove(0,1).toInt();
00179 return tmp.toInt();
00180 }
00181 case MultiScript:
00182 return current_scaleLevel + 1;
00183 case Table:
00184 return current_scaleLevel + 1;
00185 default:
00186 break;
00187 }
00188 if( index == 0) return current_scaleLevel;
00190 switch(parentType) {
00191 case SubScript:
00192 case SupScript:
00193 case SubSupScript:
00194 return current_scaleLevel + 1;
00195 case Under:
00196 if( boolOf("accentunder", parent) )
00197 return current_scaleLevel + 1;
00198 else
00199 return current_scaleLevel;
00200 case Over:
00201 if( boolOf("accent", parent) )
00202 return current_scaleLevel + 1;
00203 else
00204 return current_scaleLevel;
00205 case UnderOver:
00206 if( (index == 1 && boolOf("accentunder", parent)) || (index == 2 && boolOf("accent", parent)) )
00207 return current_scaleLevel + 1;
00208 else
00209 return current_scaleLevel;
00210 case Root:
00211
00212 return current_scaleLevel + 1;
00213 default:
00214 return current_scaleLevel;
00215 }
00216 }
00217
00218 double AttributeManager::lineThickness( const BasicElement* element ) const
00219 {
00220 QFontMetricsF fm(font(element));
00221 return fm.height() * 0.06 ;
00222 }
00223
00224 double AttributeManager::layoutSpacing( const BasicElement* element ) const
00225 {
00226 QFontMetricsF fm(font(element));
00227
00228 return fm.height() * 0.05 ;
00229 }
00230
00231 double AttributeManager::lengthToPixels( Length length, const BasicElement* element, const QString &attribute) const
00232 {
00233 if(length.value == 0)
00234 return 0;
00235
00236 switch(length.unit) {
00237 case Length::Em: {
00238 QFontMetricsF fm(font(element));
00239 return fm.height() * length.value;
00240 }
00241 case Length::Ex: {
00242 QFontMetricsF fm(font(element));
00243 return fm.xHeight() * length.value;
00244 }
00245 case Length::Percentage:
00246 return lengthToPixels( parseUnit( element->attributesDefaultValue(attribute), element),element, attribute) * length.value / 100.0;
00247 case Length::Px:
00248 return length.value;
00249 case Length::In:
00250 return INCH_TO_POINT(length.value);
00251 case Length::Cm:
00252 return CM_TO_POINT(length.value);
00253 case Length::Mm:
00254 return MM_TO_POINT(length.value);
00255 case Length::Pt:
00256 return length.value;
00257 case Length::Pc:
00258 return PI_TO_POINT(length.value);
00259 case Length::None:
00260 default:
00261 return length.value;
00262 }
00263 }
00264
00265 Length AttributeManager::parseUnit( const QString& value,
00266 const BasicElement* element ) const
00267 {
00268 Q_UNUSED(element)
00269 Length length;
00270
00271 if (value.isEmpty())
00272 return length;
00273 QRegExp re("(-?[\\d\\.]*) *(px|em|ex|in|cm|pc|mm|pt|%)?", Qt::CaseInsensitive);
00274 if (re.indexIn(value) == -1)
00275 return length;
00276 QString real = re.cap(1);
00277 QString unit = re.cap(2).toLower();
00278
00279 bool ok;
00280 qreal number = real.toDouble(&ok);
00281 if (!ok)
00282 return length;
00283
00284 length.value = number;
00285 if(!unit.isEmpty()) {
00286 if (unit == "em") {
00287 length.unit = Length::Mm;
00288 length.type = Length::Relative;
00289 }
00290 else if (unit == "ex") {
00291 length.unit = Length::Ex;
00292 length.type = Length::Relative;
00293 }
00294 else if (unit == "px") {
00295 length.unit = Length::Px;
00296 length.type = Length::Pixel;
00297 }
00298 else if (unit == "in") {
00299 length.unit = Length::In;
00300 length.type = Length::Absolute;
00301 }
00302 else if (unit == "cm") {
00303 length.unit = Length::Cm;
00304 length.type = Length::Absolute;
00305 }
00306 else if (unit == "mm") {
00307 length.unit = Length::Mm;
00308 length.type = Length::Absolute;
00309 }
00310 else if (unit == "pt") {
00311 length.unit = Length::Pt;
00312 length.type = Length::Relative;
00313 }
00314 else if (unit == "pc") {
00315 length.unit = Length::Pc;
00316 length.type = Length::Relative;
00317 }
00318 else if (unit == "%") {
00319 length.unit = Length::Percentage;
00320 length.type = Length::Relative;
00321 }
00322 else {
00323 length.unit = Length::None;
00324 length.type = Length::NoType;
00325 }
00326 }
00327
00328 return length;
00329 }
00330
00331 Align AttributeManager::parseAlign( const QString& value ) const
00332 {
00333 if( value == "right" )
00334 return Right;
00335 else if( value == "left" )
00336 return Left;
00337 else if( value == "center" )
00338 return Center;
00339 else if( value == "top" )
00340 return Top;
00341 else if( value == "bottom" )
00342 return Bottom;
00343 else if( value == "baseline" )
00344 return BaseLine;
00345 else if( value == "axis" )
00346 return Axis;
00347 else
00348 return InvalidAlign;
00349 }
00350
00351 Qt::PenStyle AttributeManager::parsePenStyle( const QString& value ) const
00352 {
00353 if( value == "solid" )
00354 return Qt::SolidLine;
00355 else if( value == "dashed" )
00356 return Qt::DashLine;
00357 else
00358 return Qt::NoPen;
00359 }
00360
00361 QFont AttributeManager::font( const BasicElement* element ) const
00362 {
00363
00364
00365
00366
00367
00368
00369
00370 QFont font;
00371 Length unit = parseUnit( findValue( "fontsize", element ), element );
00372 if ( unit.type == Length::Absolute ) {
00373 font.setPointSizeF( lengthToPixels( unit, element, "fontsize" ) );
00374 } else if ( unit.type == Length::Relative ) {
00375 font.setPointSizeF( lengthToPixels( unit, element, "fontsize" ) * element->scaleFactor() );
00376 } else if ( unit.type == Length::Pixel ) {
00377 font.setPixelSize( lengthToPixels( unit, element, "fontsize" ) * element->scaleFactor() );
00378 }
00379 return font;
00380 }
00381
00382 void AttributeManager::setViewConverter( KoViewConverter* converter )
00383 {
00384 m_viewConverter = converter;
00385 }
00386
00387 double AttributeManager::maxHeightOfChildren( const BasicElement* element ) const
00388 {
00389 double maxHeight = 0.0;
00390 foreach( BasicElement* tmp, element->childElements() )
00391 maxHeight = qMax( maxHeight, tmp->height() );
00392
00393 return maxHeight;
00394 }
00395
00396 double AttributeManager::maxWidthOfChildren( const BasicElement* element ) const
00397 {
00398 double maxWidth = 0.0;
00399 foreach( BasicElement* tmp, element->childElements() )
00400 maxWidth = qMax( maxWidth, tmp->width() );
00401
00402 return maxWidth;
00403 }
00404 double AttributeManager::parseMathSpace( const QString& value, const BasicElement * element ) const
00405 {
00406 QFontMetricsF fm(font(element));
00407 qreal conversionEmToPixels = fm.xHeight();
00408
00409 if( value == "negativeveryverythinmathspace" )
00410 return -1*conversionEmToPixels*0.055556;
00411 else if( value == "negativeverythinmathspace" )
00412 return -1*conversionEmToPixels*0.111111;
00413 else if( value == "negativethinmathspace" )
00414 return -1*conversionEmToPixels*0.166667;
00415 else if( value == "negativemediummathspace" )
00416 return -1*conversionEmToPixels*0.222222;
00417 else if( value == "negativethickmathspace" )
00418 return -1*conversionEmToPixels*0.277778;
00419 else if( value == "negativeverythickmathspace" )
00420 return -1*conversionEmToPixels*0.333333;
00421 else if( value == "negativeveryverythickmathspace" )
00422 return -1*conversionEmToPixels*0.388889;
00423 else if( value == "veryverythinmathspace" )
00424 return conversionEmToPixels*0.055556;
00425 else if( value == "verythinmathspace" )
00426 return conversionEmToPixels*0.111111;
00427 else if( value == "thinmathspace" )
00428 return conversionEmToPixels*0.166667;
00429 else if( value == "mediummathspace" )
00430 return conversionEmToPixels*0.222222;
00431 else if( value == "thickmathspace" )
00432 return conversionEmToPixels*0.277778;
00433 else if( value == "verythickmathspace" )
00434 return conversionEmToPixels*0.333333;
00435 else if( value == "veryverythickmathspace" )
00436 return conversionEmToPixels*0.388889;
00437 else
00438 return 0;
00439 }
00440