File indexing completed on 2024-05-12 04:35:06
0001 /* This file is part of the TikZKit project. 0002 * 0003 * Copyright (C) 2013-2014 Dominik Haumann <dhaumann@kde.org> 0004 * 0005 * This library is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU Library General Public License as published 0007 * by the Free Software Foundation, either version 2 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, see 0017 * <http://www.gnu.org/licenses/>. 0018 */ 0019 #ifndef TIKZ_VALUE_H 0020 #define TIKZ_VALUE_H 0021 0022 #include "tikz_export.h" 0023 #include "tikz.h" 0024 0025 #include <cmath> 0026 #include <QDebug> 0027 0028 namespace tikz 0029 { 0030 0031 namespace internal { 0032 // see: http://tex.stackexchange.com/questions/8260 0033 static constexpr qreal units[4][4] = { 0034 // pt , mm , cm , in 0035 0036 // conversion from pt 0037 {1.0 , 2540.0/7227.0, 254.0/7227.0, 100.0/7227.0}, 0038 // conversion from mm 0039 {7227.0/2540.0 , 1.0 , 0.1 , 5.0/127.0}, 0040 // conversion from cm 0041 {7227.0/254.0 , 10.0 , 1.0 , 50.0/127.0}, 0042 // conversion from in 0043 {7227.0/100.0 , 127.0/5.0 , 127.0/50.0 , 1.0} 0044 }; 0045 } 0046 0047 /** 0048 * The Value class provides a unit-aware value. 0049 * 0050 * The Value is defined by a real number and its unit. 0051 * By using the Value class whenever metric values are required, 0052 * it is recommended to use Value as it avoids unit conversion errors. 0053 */ 0054 class TIKZKITCORE_EXPORT Value 0055 { 0056 // 0057 // static functions 0058 // 0059 public: 0060 /** 0061 * 'ultra thin' line width according to the PGF/TikZ standard. 0062 */ 0063 static inline constexpr Value ultraThin() noexcept { 0064 return Value(0.1, Unit::Point); 0065 } 0066 0067 /** 0068 * 'very thin' line width according to the PGF/TikZ standard. 0069 */ 0070 static inline constexpr Value veryThin() noexcept { 0071 return Value(0.2, Unit::Point); 0072 } 0073 0074 /** 0075 * 'thin' line width according to the PGF/TikZ standard. 0076 */ 0077 static inline constexpr Value thin() noexcept { 0078 return Value(0.4, Unit::Point); 0079 } 0080 0081 /** 0082 * 'semithick' line width according to the PGF/TikZ standard. 0083 */ 0084 static inline constexpr Value semiThick() noexcept { 0085 return Value(0.6, Unit::Point); 0086 } 0087 0088 /** 0089 * 'thick' line width according to the PGF/TikZ standard. 0090 */ 0091 static inline constexpr Value thick() noexcept { 0092 return Value(0.8, Unit::Point); 0093 } 0094 0095 /** 0096 * 'very thick' line width according to the PGF/TikZ standard. 0097 */ 0098 static inline constexpr Value veryThick() noexcept { 0099 return Value(1.2, Unit::Point); 0100 } 0101 0102 /** 0103 * 'ultra thick' line width according to the PGF/TikZ standard. 0104 */ 0105 static inline constexpr Value ultraThick() noexcept { 0106 return Value(1.6, Unit::Point); 0107 } 0108 0109 /** 0110 * Invalid size, set to NaN. 0111 * @see isValid() 0112 */ 0113 static inline constexpr Value invalid() noexcept { 0114 return Value(std::sqrt(-1)); 0115 } 0116 0117 public: 0118 /** 0119 * Constructor with value and type. 0120 */ 0121 constexpr Value(qreal value = 0.0, Unit unit = Unit::Point) 0122 : m_value(value) 0123 , m_unit(unit) 0124 { 0125 } 0126 0127 /** 0128 * Check whether this value is a finite value, i.e. other than NaN or infinity. 0129 */ 0130 inline bool isValid() const noexcept 0131 { 0132 return std::isfinite(m_value); 0133 } 0134 0135 /** 0136 * Get the Unit. 0137 */ 0138 inline constexpr Unit unit() const noexcept 0139 { 0140 return m_unit; 0141 } 0142 0143 /** 0144 * Explicit conversion to value. 0145 */ 0146 inline constexpr qreal value() const noexcept 0147 { 0148 return m_value; 0149 } 0150 0151 /** 0152 * Explicit conversion to Point. 0153 */ 0154 inline constexpr qreal toPoint() const noexcept 0155 { 0156 return convertTo(tikz::Unit::Point).m_value; 0157 } 0158 0159 /** 0160 * 0161 */ 0162 inline constexpr Value convertTo(Unit unit) const noexcept 0163 { 0164 return Value(m_value * internal::units[static_cast<int>(m_unit)][static_cast<int>(unit)], unit); 0165 } 0166 0167 /** 0168 * Convert this number to a string. 0169 */ 0170 QString toString() const; 0171 0172 /** 0173 * Convert @p str to a Value. 0174 */ 0175 static Value fromString(const QString & str); 0176 0177 // 0178 // operators for qreal values 0179 // 0180 public: 0181 // /** 0182 // * Implicit cast to value. 0183 // * @warning the returned value \e always is of type Unit::Point! 0184 // */ 0185 // inline constexpr operator qreal () const noexcept 0186 // { 0187 // return convertTo(Unit::Point).value(); 0188 // } 0189 0190 /** 0191 * Adds @p value to this Value and returns a reference to this Value. 0192 * @warning This operation is independent of the unit. 0193 */ 0194 inline Value & operator+=(qreal value) noexcept 0195 { 0196 Q_ASSERT(isValid()); 0197 m_value += value; 0198 return *this; 0199 } 0200 0201 /** 0202 * Subtracts @p value from this Value and returns a reference to this Value. 0203 * @warning This operation is independent of the unit. 0204 */ 0205 inline Value & operator-=(qreal value) noexcept 0206 { 0207 Q_ASSERT(isValid()); 0208 m_value -= value; 0209 return *this; 0210 } 0211 0212 /** 0213 * Multiplies this Value with @p factor and returns a reference to this Value. 0214 * @warning This operation is independent of the unit. 0215 */ 0216 inline Value & operator*=(qreal factor) noexcept 0217 { 0218 Q_ASSERT(isValid()); 0219 m_value *= factor; 0220 return *this; 0221 } 0222 0223 /** 0224 * Divides this Value by @p divisor and returns a reference to this Value. 0225 * @warning This operation is independent of the unit. 0226 */ 0227 inline Value & operator/=(qreal divisor) noexcept 0228 { 0229 Q_ASSERT(isValid()); 0230 m_value /= divisor; 0231 return *this; 0232 } 0233 0234 // 0235 // operators for two Value 0236 // 0237 public: 0238 /** 0239 * Plus operator for two Value%s. 0240 * Returns a new Value object with the same unit increased by @p value. 0241 * If @p value's unit is different, @p value is first converted to a 0242 * compatible Unit before adding the value. 0243 */ 0244 inline Value operator+(const Value & value) const noexcept 0245 { 0246 Q_ASSERT(isValid()); 0247 Q_ASSERT(value.isValid()); 0248 return Value(m_value + value.convertTo(m_unit).value(), m_unit); 0249 } 0250 0251 /** 0252 * Minus operator for two Value%s. 0253 * Returns a new Value object with the same unit decreased by @p value. 0254 * If @p value's unit is different, @p value is first converted to a 0255 * compatible Unit before adding the value. 0256 */ 0257 inline Value operator-(const Value & value) const noexcept 0258 { 0259 Q_ASSERT(isValid()); 0260 Q_ASSERT(value.isValid()); 0261 return Value(m_value - value.convertTo(m_unit).value(), m_unit); 0262 } 0263 0264 /** 0265 * += operator for two Value%s. 0266 * Returns a reference to this object increased by @p value. 0267 * If @p value's unit is different, @p value is first converted to a 0268 * compatible Unit before adding the value. 0269 */ 0270 inline Value & operator+=(const Value & value) 0271 { 0272 Q_ASSERT(isValid()); 0273 Q_ASSERT(value.isValid()); 0274 return operator+=(value.convertTo(m_unit).value()); 0275 } 0276 0277 /** 0278 * -= operator for two Value%s. 0279 * Returns a reference to this object decreased by @p value. 0280 * If @p value's unit is different, @p value is first converted to a 0281 * compatible Unit before adding the value. 0282 */ 0283 inline Value & operator-=(const Value & value) 0284 { 0285 Q_ASSERT(isValid()); 0286 Q_ASSERT(value.isValid()); 0287 return operator-=(value.convertTo(m_unit).value()); 0288 } 0289 0290 /** 0291 * QDebug support. 0292 */ 0293 inline friend QDebug operator<<(QDebug s, const tikz::Value & value) 0294 { 0295 s.nospace() << value.toString(); 0296 return s.space(); 0297 } 0298 0299 operator QVariant() const 0300 { 0301 return QVariant::fromValue(*this); 0302 } 0303 0304 private: 0305 /** 0306 * The value. 0307 */ 0308 qreal m_value = 0; 0309 0310 /** 0311 * The unit of this value. 0312 */ 0313 Unit m_unit = Unit::Point; 0314 }; 0315 0316 /** 0317 * Equality operator. 0318 * Return @e true, if the Value @p lhs equals the Value @p rhs. 0319 * @note The comparison is unit-aware. 0320 */ 0321 inline bool operator==(const Value & lhs, const Value & rhs) noexcept 0322 { 0323 return (!lhs.isValid() && !rhs.isValid()) 0324 || qFuzzyIsNull(lhs.value() - rhs.convertTo(lhs.unit()).value()); 0325 } 0326 0327 /** 0328 * Inequality operator. 0329 * Return @e true, if the Value @p lhs does not equal the Value @p rhs. 0330 * @note The comparison is unit-aware. 0331 */ 0332 inline bool operator!=(const Value & lhs, const Value & rhs) noexcept 0333 { 0334 return ! (lhs == rhs); 0335 } 0336 0337 /** 0338 * Returns a Value that is formed by multiplying @p value with @p factor. 0339 * @warning This operation is independent of the unit. 0340 */ 0341 inline Value operator*(const Value & value, qreal factor) noexcept 0342 { 0343 return Value(value.value() * factor, value.unit()); 0344 } 0345 0346 /** 0347 * Returns a Value that is formed by multiplying @p value with @p factor. 0348 * @warning This operation is independent of the unit. 0349 */ 0350 inline Value operator*(qreal factor, const Value & value) noexcept 0351 { 0352 return value * factor; 0353 } 0354 0355 /** 0356 * Returns a Value that is formed by dividing @p value by @p divisor. 0357 * @warning This operation is independent of the unit. 0358 */ 0359 inline Value operator/(const Value & value, qreal divisor) 0360 { 0361 Q_ASSERT(divisor != 0); 0362 return Value(value.value() / divisor, value.unit()); 0363 } 0364 0365 /** 0366 * Returns @e true if @p value is greater than @p valInPoints. 0367 * @warning @valInPoints is interpreted in Points. 0368 */ 0369 inline constexpr bool operator>(const Value & value, qreal valInPoints) noexcept 0370 { 0371 return value.toPoint() > valInPoints; 0372 } 0373 0374 /** 0375 * Returns @e true if @p value is greater than @p valInPoints. 0376 * @warning @valInPoints is interpreted in Points. 0377 */ 0378 inline constexpr bool operator>(qreal valInPoints, const Value & value) noexcept 0379 { 0380 return valInPoints > value.toPoint(); 0381 } 0382 0383 /** 0384 * Returns true if @p value in Point is greater than or equal to @p valInPoints. 0385 * @warning @valInPoints is interpreted in Points. 0386 */ 0387 inline constexpr bool operator>=(const Value & value, qreal valInPoints) noexcept 0388 { 0389 return value.toPoint() >= valInPoints; 0390 } 0391 0392 /** 0393 * Returns true if @p value in Point is less than @p valInPoints. 0394 * @warning @valInPoints is interpreted in Points. 0395 */ 0396 inline constexpr bool operator<(const Value & value, qreal valInPoints) noexcept 0397 { 0398 return value.toPoint() < valInPoints; 0399 } 0400 0401 /** 0402 * Returns true if @p value in Point is less than or equal to @p valInPoints. 0403 * @warning @valInPoints is interpreted in Points. 0404 */ 0405 inline constexpr bool operator<=(const Value & value, qreal valInPoints) noexcept 0406 { 0407 return value.toPoint() <= valInPoints; 0408 } 0409 0410 /** 0411 * Returns true if Value @p lhs is greater than Valule @p rhs. 0412 * @note This comparison is unit-aware. 0413 */ 0414 inline bool operator>(const Value & lhs, const Value & rhs) noexcept 0415 { 0416 Q_ASSERT(lhs.isValid()); 0417 Q_ASSERT(rhs.isValid()); 0418 return lhs.value() > rhs.convertTo(lhs.unit()).value(); 0419 } 0420 0421 /** 0422 * Returns true if Value @p lhs is greater than or equal to Valule @p rhs. 0423 * @note This comparison is unit-aware. 0424 */ 0425 inline bool operator>=(const Value & lhs, const Value & rhs) noexcept 0426 { 0427 Q_ASSERT(lhs.isValid()); 0428 Q_ASSERT(rhs.isValid()); 0429 return lhs.value() >= rhs.convertTo(lhs.unit()).value(); 0430 } 0431 0432 /** 0433 * Returns true if Value @p lhs is less than Valule @p rhs. 0434 * @note This comparison is unit-aware. 0435 */ 0436 inline bool operator<(const Value & lhs, const Value & rhs) noexcept 0437 { 0438 Q_ASSERT(lhs.isValid()); 0439 Q_ASSERT(rhs.isValid()); 0440 return lhs.value() < rhs.convertTo(lhs.unit()).value(); 0441 } 0442 0443 /** 0444 * Returns true if Value @p lhs is less than or equal to Valule @p rhs. 0445 * @note This comparison is unit-aware. 0446 */ 0447 inline bool operator<=(const Value & lhs, const Value & rhs) noexcept 0448 { 0449 Q_ASSERT(lhs.isValid()); 0450 Q_ASSERT(rhs.isValid()); 0451 return lhs.value() <= rhs.convertTo(lhs.unit()).value(); 0452 } 0453 0454 /** 0455 * Convert @p value from unit @p from to unit @p to. 0456 */ 0457 inline constexpr qreal convertTo(qreal value, Unit from, Unit to) 0458 { 0459 return value * internal::units[static_cast<int>(from)][static_cast<int>(to)]; 0460 } 0461 0462 // 0463 // pt to * 0464 // 0465 inline constexpr qreal pt2mm(qreal value) 0466 { 0467 return convertTo(value, Unit::Point, Unit::Millimeter); 0468 } 0469 0470 inline constexpr qreal pt2cm(qreal value) 0471 { 0472 return convertTo(value, Unit::Point, Unit::Centimeter); 0473 } 0474 0475 inline constexpr qreal pt2in(qreal value) 0476 { 0477 return convertTo(value, Unit::Point, Unit::Inch); 0478 } 0479 0480 // 0481 // cm to * 0482 // 0483 inline constexpr qreal cm2pt(qreal value) 0484 { 0485 return convertTo(value, Unit::Centimeter, Unit::Point); 0486 } 0487 0488 inline constexpr qreal cm2mm(qreal value) 0489 { 0490 return convertTo(value, Unit::Centimeter, Unit::Millimeter); 0491 } 0492 0493 inline constexpr qreal cm2in(qreal value) 0494 { 0495 return convertTo(value, Unit::Centimeter, Unit::Inch); 0496 } 0497 0498 // 0499 // mm to * 0500 // 0501 inline constexpr qreal mm2pt(qreal value) 0502 { 0503 return convertTo(value, Unit::Millimeter, Unit::Point); 0504 } 0505 0506 inline constexpr qreal mm2cm(qreal value) 0507 { 0508 return convertTo(value, Unit::Millimeter, Unit::Centimeter); 0509 } 0510 0511 inline constexpr qreal mm2in(qreal value) 0512 { 0513 return convertTo(value, Unit::Millimeter, Unit::Inch); 0514 } 0515 0516 // 0517 // in to * 0518 // 0519 inline constexpr qreal in2pt(qreal value) 0520 { 0521 return convertTo(value, Unit::Inch, Unit::Point); 0522 } 0523 0524 inline constexpr qreal in2cm(qreal value) 0525 { 0526 return convertTo(value, Unit::Inch, Unit::Centimeter); 0527 } 0528 0529 inline constexpr qreal in2mm(qreal value) 0530 { 0531 return convertTo(value, Unit::Inch, Unit::Millimeter); 0532 } 0533 0534 } 0535 0536 inline constexpr tikz::Value operator""_pt(long double value) 0537 { 0538 return tikz::Value(value, tikz::Unit::Point); 0539 } 0540 0541 inline constexpr tikz::Value operator""_mm(long double value) 0542 { 0543 return tikz::Value(value, tikz::Unit::Millimeter); 0544 } 0545 0546 inline constexpr tikz::Value operator""_cm(long double value) 0547 { 0548 return tikz::Value(value, tikz::Unit::Centimeter); 0549 } 0550 0551 inline constexpr tikz::Value operator""_in(long double value) 0552 { 0553 return tikz::Value(value, tikz::Unit::Inch); 0554 } 0555 0556 namespace QTest 0557 { 0558 // forward declaration of template in qtestcase.h 0559 template<typename T> char* toString(const T&); 0560 0561 template<> 0562 TIKZKITCORE_EXPORT char *toString(const tikz::Value & value); 0563 } 0564 0565 /** 0566 * Declare as movable, since the members of Value are primitive types. 0567 */ 0568 Q_DECLARE_TYPEINFO(tikz::Value, Q_MOVABLE_TYPE); 0569 Q_DECLARE_METATYPE(tikz::Value) 0570 0571 #endif // TIKZ_VALUE_H 0572 0573 // kate: indent-width 4; replace-tabs on;