Warning, file /office/calligra/libs/odf/KoUnit.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright (C) 2001 David Faure <faure@kde.org> 0003 Copyright (C) 2004, Nicolas GOUTTE <goutte@kde.org> 0004 Copyright 2012 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoUnit.h" 0023 0024 #include <cmath> 0025 0026 #include <QTransform> 0027 0028 #include <klocalizedstring.h> 0029 #include <OdfDebug.h> 0030 #include <QtGlobal> 0031 0032 0033 // ensure the same order as in KoUnit::Unit 0034 static const char* const unitNameList[KoUnit::TypeCount] = 0035 { 0036 "mm", 0037 "pt", 0038 "in", 0039 "cm", 0040 "dm", 0041 "pi", 0042 "cc", 0043 "px" 0044 }; 0045 0046 QString KoUnit::unitDescription(KoUnit::Type type) 0047 { 0048 switch (type) { 0049 case KoUnit::Millimeter: 0050 return i18n("Millimeters (mm)"); 0051 case KoUnit::Centimeter: 0052 return i18n("Centimeters (cm)"); 0053 case KoUnit::Decimeter: 0054 return i18n("Decimeters (dm)"); 0055 case KoUnit::Inch: 0056 return i18n("Inches (in)"); 0057 case KoUnit::Pica: 0058 return i18n("Pica (pi)"); 0059 case KoUnit::Cicero: 0060 return i18n("Cicero (cc)"); 0061 case KoUnit::Point: 0062 return i18n("Points (pt)"); 0063 case KoUnit::Pixel: 0064 return i18n("Pixels (px)"); 0065 default: 0066 return i18n("Unsupported unit"); 0067 } 0068 } 0069 0070 // grouped by units which are similar 0071 static const KoUnit::Type typesInUi[KoUnit::TypeCount] = 0072 { 0073 KoUnit::Millimeter, 0074 KoUnit::Centimeter, 0075 KoUnit::Decimeter, 0076 KoUnit::Inch, 0077 KoUnit::Pica, 0078 KoUnit::Cicero, 0079 KoUnit::Point, 0080 KoUnit::Pixel, 0081 }; 0082 0083 QStringList KoUnit::listOfUnitNameForUi(ListOptions listOptions) 0084 { 0085 QStringList lst; 0086 for (int i = 0; i < KoUnit::TypeCount; ++i) { 0087 const Type type = typesInUi[i]; 0088 if ((type != Pixel) || ((listOptions & HideMask) == ListAll)) 0089 lst.append(unitDescription(type)); 0090 } 0091 return lst; 0092 } 0093 0094 KoUnit KoUnit::fromListForUi(int index, ListOptions listOptions, qreal factor) 0095 { 0096 KoUnit::Type type = KoUnit::Point; 0097 0098 if ((0 <= index) && (index < KoUnit::TypeCount)) { 0099 // iterate through all enums and skip the Pixel enum if needed 0100 for (int i = 0; i < KoUnit::TypeCount; ++i) { 0101 if ((listOptions&HidePixel) && (typesInUi[i] == Pixel)) { 0102 ++index; 0103 continue; 0104 } 0105 if (i == index) { 0106 type = typesInUi[i]; 0107 break; 0108 } 0109 } 0110 } 0111 0112 return KoUnit(type, factor); 0113 } 0114 0115 int KoUnit::indexInListForUi(ListOptions listOptions) const 0116 { 0117 if ((listOptions&HidePixel) && (m_type == Pixel)) { 0118 return -1; 0119 } 0120 0121 int result = -1; 0122 0123 int skipped = 0; 0124 for (int i = 0; i < KoUnit::TypeCount; ++i) { 0125 if ((listOptions&HidePixel) && (typesInUi[i] == Pixel)) { 0126 ++skipped; 0127 continue; 0128 } 0129 if (typesInUi[i] == m_type) { 0130 result = i - skipped; 0131 break; 0132 } 0133 } 0134 0135 return result; 0136 } 0137 0138 qreal KoUnit::toUserValue(qreal ptValue) const 0139 { 0140 switch (m_type) { 0141 case Millimeter: 0142 return toMillimeter(ptValue); 0143 case Centimeter: 0144 return toCentimeter(ptValue); 0145 case Decimeter: 0146 return toDecimeter(ptValue); 0147 case Inch: 0148 return toInch(ptValue); 0149 case Pica: 0150 return toPica(ptValue); 0151 case Cicero: 0152 return toCicero(ptValue); 0153 case Pixel: 0154 return ptValue * m_pixelConversion; 0155 case Point: 0156 default: 0157 return toPoint(ptValue); 0158 } 0159 } 0160 0161 qreal KoUnit::ptToUnit(const qreal ptValue, const KoUnit &unit) 0162 { 0163 switch (unit.m_type) { 0164 case Millimeter: 0165 return POINT_TO_MM(ptValue); 0166 case Centimeter: 0167 return POINT_TO_CM(ptValue); 0168 case Decimeter: 0169 return POINT_TO_DM(ptValue); 0170 case Inch: 0171 return POINT_TO_INCH(ptValue); 0172 case Pica: 0173 return POINT_TO_PI(ptValue); 0174 case Cicero: 0175 return POINT_TO_CC(ptValue); 0176 case Pixel: 0177 return ptValue * unit.m_pixelConversion; 0178 case Point: 0179 default: 0180 return ptValue; 0181 } 0182 } 0183 0184 QString KoUnit::toUserStringValue(qreal ptValue) const 0185 { 0186 return QLocale().toString(toUserValue(ptValue)); 0187 } 0188 0189 qreal KoUnit::fromUserValue(qreal value) const 0190 { 0191 switch (m_type) { 0192 case Millimeter: 0193 return MM_TO_POINT(value); 0194 case Centimeter: 0195 return CM_TO_POINT(value); 0196 case Decimeter: 0197 return DM_TO_POINT(value); 0198 case Inch: 0199 return INCH_TO_POINT(value); 0200 case Pica: 0201 return PI_TO_POINT(value); 0202 case Cicero: 0203 return CC_TO_POINT(value); 0204 case Pixel: 0205 return value / m_pixelConversion; 0206 case Point: 0207 default: 0208 return value; 0209 } 0210 } 0211 0212 qreal KoUnit::fromUserValue(const QString &value, bool *ok) const 0213 { 0214 return fromUserValue(QLocale().toDouble(value, ok)); 0215 } 0216 0217 qreal KoUnit::parseValue(const QString& _value, qreal defaultVal) 0218 { 0219 if (_value.isEmpty()) 0220 return defaultVal; 0221 0222 QString value(_value.simplified()); 0223 value.remove(QLatin1Char(' ')); 0224 0225 int firstLetter = -1; 0226 for (int i = 0; i < value.length(); ++i) { 0227 if (value.at(i).isLetter()) { 0228 if (value.at(i) == QLatin1Char('e')) 0229 continue; 0230 firstLetter = i; 0231 break; 0232 } 0233 } 0234 0235 if (firstLetter == -1) 0236 return value.toDouble(); 0237 0238 const QString symbol = value.mid(firstLetter); 0239 value.truncate(firstLetter); 0240 const qreal val = value.toDouble(); 0241 0242 if (symbol == QLatin1String("pt")) 0243 return val; 0244 0245 bool ok; 0246 KoUnit u = KoUnit::fromSymbol(symbol, &ok); 0247 if (ok) 0248 return u.fromUserValue(val); 0249 0250 if (symbol == QLatin1String("m")) 0251 return DM_TO_POINT(val * 10.0); 0252 else if (symbol == QLatin1String("km")) 0253 return DM_TO_POINT(val * 10000.0); 0254 warnOdf << "KoUnit::parseValue: Unit " << symbol << " is not supported, please report."; 0255 0256 // TODO : add support for mi/ft ? 0257 return defaultVal; 0258 } 0259 0260 KoUnit KoUnit::fromSymbol(const QString &symbol, bool *ok) 0261 { 0262 Type result = Point; 0263 0264 if (symbol == QLatin1String("inch") /*compat*/) { 0265 result = Inch; 0266 if (ok) 0267 *ok = true; 0268 } else { 0269 if (ok) 0270 *ok = false; 0271 0272 for (int i = 0; i < TypeCount; ++i) { 0273 if (symbol == QLatin1String(unitNameList[i])) { 0274 result = static_cast<Type>(i); 0275 if (ok) 0276 *ok = true; 0277 } 0278 } 0279 } 0280 0281 return KoUnit(result); 0282 } 0283 0284 qreal KoUnit::convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor) 0285 { 0286 qreal pt; 0287 switch (fromUnit.type()) { 0288 case Millimeter: 0289 pt = MM_TO_POINT(value); 0290 break; 0291 case Centimeter: 0292 pt = CM_TO_POINT(value); 0293 break; 0294 case Decimeter: 0295 pt = DM_TO_POINT(value); 0296 break; 0297 case Inch: 0298 pt = INCH_TO_POINT(value); 0299 break; 0300 case Pica: 0301 pt = PI_TO_POINT(value); 0302 break; 0303 case Cicero: 0304 pt = CC_TO_POINT(value); 0305 break; 0306 case Pixel: 0307 pt = value / factor; 0308 break; 0309 case Point: 0310 default: 0311 pt = value; 0312 } 0313 0314 switch (toUnit.type()) { 0315 case Millimeter: 0316 return POINT_TO_MM(pt); 0317 case Centimeter: 0318 return POINT_TO_CM(pt); 0319 case Decimeter: 0320 return POINT_TO_DM(pt); 0321 case Inch: 0322 return POINT_TO_INCH(pt); 0323 case Pica: 0324 return POINT_TO_PI(pt); 0325 case Cicero: 0326 return POINT_TO_CC(pt); 0327 case Pixel: 0328 return pt * factor; 0329 case Point: 0330 default: 0331 return pt; 0332 } 0333 0334 } 0335 0336 QString KoUnit::symbol() const 0337 { 0338 return QLatin1String(unitNameList[m_type]); 0339 } 0340 0341 qreal KoUnit::parseAngle(const QString& _value, qreal defaultVal) 0342 { 0343 if (_value.isEmpty()) 0344 return defaultVal; 0345 0346 QString value(_value.simplified()); 0347 value.remove(QLatin1Char(' ')); 0348 0349 int firstLetter = -1; 0350 for (int i = 0; i < value.length(); ++i) { 0351 if (value.at(i).isLetter()) { 0352 if (value.at(i) == QLatin1Char('e')) 0353 continue; 0354 firstLetter = i; 0355 break; 0356 } 0357 } 0358 0359 if (firstLetter == -1) 0360 return value.toDouble(); 0361 0362 const QString type = value.mid(firstLetter); 0363 value.truncate(firstLetter); 0364 const qreal val = value.toDouble(); 0365 0366 if (type == QLatin1String("deg")) 0367 return val; 0368 else if (type == QLatin1String("rad")) 0369 return val * 180 / M_PI; 0370 else if (type == QLatin1String("grad")) 0371 return val * 0.9; 0372 0373 return defaultVal; 0374 } 0375 0376 qreal KoUnit::approxTransformScale(const QTransform &t) 0377 { 0378 return std::sqrt(qAbs(t.determinant())); 0379 } 0380 0381 void KoUnit::adjustByPixelTransform(const QTransform &t) 0382 { 0383 m_pixelConversion *= approxTransformScale(t); 0384 } 0385 0386 #ifndef QT_NO_DEBUG_STREAM 0387 QDebug operator<<(QDebug debug, const KoUnit &unit) 0388 { 0389 #ifndef NDEBUG 0390 debug.nospace() << unit.symbol(); 0391 #else 0392 Q_UNUSED(unit); 0393 #endif 0394 return debug.space(); 0395 0396 } 0397 #endif