File indexing completed on 2024-05-12 15:57:04

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
0003    SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
0004    SPDX-FileCopyrightText: 2004 Nicolas GOUTTE <goutte@kde.org>
0005    SPDX-FileCopyrightText: 2010 Thomas Zander <zander@kde.org>
0006    SPDX-FileCopyrightText: 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
0007 
0008    SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #ifndef KOUNIT_H
0012 #define KOUNIT_H
0013 
0014 // Calligra
0015 #include "kritaglobal_export.h"
0016 // Qt
0017 #include <QString>
0018 #include <QDebug>
0019 #include <QMetaType>
0020 // std
0021 #include <math.h> // for floor
0022 
0023 class QStringList;
0024 
0025 // 1 inch ^= 72 pt
0026 // 1 inch ^= 25.399956 mm (-pedantic ;p)
0027 // 1 pt = 1/12 pi
0028 // 1 pt ^= 0.0077880997 cc
0029 // 1 cc = 12 dd
0030 
0031 constexpr qreal POINT_TO_MM(qreal px) {return (px)*0.352777167;}
0032 constexpr qreal MM_TO_POINT(qreal mm) {return mm*2.83465058;}
0033 constexpr qreal POINT_TO_CM(qreal px) {return (px)*0.0352777167;}
0034 constexpr qreal CM_TO_POINT(qreal cm) {return (cm)*28.3465058;}
0035 constexpr qreal POINT_TO_DM(qreal px) {return (px)*0.00352777167;}
0036 constexpr qreal DM_TO_POINT(qreal dm) {return (dm)*283.465058;}
0037 constexpr qreal POINT_TO_INCH(qreal px) {return (px)*0.01388888888889;}
0038 constexpr qreal INCH_TO_POINT(qreal inch) {return (inch)*72.0;}
0039 constexpr qreal MM_TO_INCH(qreal mm) {return (mm)*0.039370147;}
0040 constexpr qreal INCH_TO_MM(qreal inch) {return (inch)*25.399956;}
0041 constexpr qreal POINT_TO_PI(qreal px) {return (px)*0.083333333;}
0042 constexpr qreal POINT_TO_CC(qreal px) {return (px)*0.077880997;}
0043 constexpr qreal PI_TO_POINT(qreal pi) {return (pi)*12;}
0044 constexpr qreal CC_TO_POINT(qreal cc) {return (cc)*12.840103;}
0045 
0046 
0047 static const qreal PT_ROUNDING {1000.0};
0048 //static const qreal PX_ROUNDING {1000.0}; // pixel value is not to be rounded
0049 
0050 static const qreal CM_ROUNDING {10000.0};
0051 static const qreal DM_ROUNDING {10000.0};
0052 static const qreal MM_ROUNDING {10000.0};
0053 
0054 static const qreal IN_ROUNDING {100000.0};
0055 
0056 static const qreal PI_ROUNDING {100000.0}; // pico
0057 static const qreal CC_ROUNDING {100000.0}; // cicero
0058 
0059 
0060 /**
0061  * %Calligra stores everything in pt (using "qreal") internally.
0062  * When displaying a value to the user, the value is converted to the user's unit
0063  * of choice, and rounded to a reasonable precision to avoid 0.999999
0064  *
0065  * For implementing the selection of a unit type in the UI use the *ForUi() methods.
0066  * They ensure the same order of the unit types in all places, with the order not
0067  * bound to the order in the enum (so ABI-compatible extension is possible) and
0068  * with the order and scope of listed types controlled by the @c ListOptions parameter.
0069  */
0070 class KRITAGLOBAL_EXPORT KoUnit
0071 {
0072 public:
0073     /** Length units supported by Calligra. */
0074     enum Type {
0075         Millimeter = 0,
0076         Point,  ///< Postscript point, 1/72th of an Inco
0077         Inch,
0078         Centimeter,
0079         Decimeter,
0080         Pica,
0081         Cicero,
0082         Pixel,
0083         TypeCount ///< @internal
0084     };
0085 
0086     /// Used to control the scope of the unit types listed in the UI
0087     enum ListOption {
0088         ListAll = 0,
0089         HidePixel = 1,
0090         HideMask = HidePixel
0091     };
0092      Q_DECLARE_FLAGS(ListOptions, ListOption)
0093 
0094     /** Returns a KoUnit instance with the type at the @p index of the UI list with the given @p listOptions. */
0095     static KoUnit fromListForUi(int index, ListOptions listOptions = ListAll, qreal factor = 1.0);
0096 
0097     /// Convert a unit symbol string into a KoUnit
0098     /// @param symbol symbol to convert
0099     /// @param ok if set, it will be true if the unit was known, false if unknown
0100     static KoUnit fromSymbol(const QString &symbol, bool *ok = 0);
0101 
0102     /** Construction requires initialization. The factor is for variable factor units like pixel */
0103     explicit KoUnit(Type unit = Point, qreal factor = 1.0) {
0104         m_type = unit;
0105         m_pixelConversion = factor;
0106     }
0107 
0108     KoUnit& operator=(Type unit) {
0109         m_type = unit; m_pixelConversion = 1.0; return *this;
0110     }
0111 
0112     bool operator!=(const KoUnit &other) const {
0113         return !operator==(other);
0114     }
0115 
0116     bool operator==(const KoUnit &other) const {
0117         return m_type == other.m_type &&
0118             (m_type != Pixel ||
0119              qFuzzyCompare(m_pixelConversion, other.m_pixelConversion));
0120     }
0121 
0122     KoUnit::Type type() const {
0123         return m_type;
0124     }
0125 
0126     void setFactor(qreal factor) {
0127         m_pixelConversion = factor;
0128     }
0129 
0130 
0131     /**
0132      * convert the given value directly from one unit to another
0133      */
0134     static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor = 1.0);
0135 
0136     /**
0137      * Convert the value @p ptValue to the unit and round it.
0138      * This method is meant to be used to display a value in a dialog.
0139      * \return the converted and rounded value
0140      */
0141 
0142     qreal toUserValueRounded(const qreal value) const;
0143     /**
0144      * Convert the value @p ptValue to the unit (without rounding)
0145      * This method is meant to be used in complex calculations.
0146      * \return the converted value
0147      */
0148     qreal toUserValuePrecise(const qreal ptValue) const;
0149 
0150     /**
0151      * Convert the value @p ptValue with or with rounding as indicated by @p rounding.
0152      * This method is a proxy to toUserValuePrecise and toUserValueRounded.
0153      * \return the value @p ptValue converted to unit
0154      */
0155     qreal toUserValue(qreal ptValue, bool rounding = true) const;
0156 
0157 
0158 
0159     /// This method is the one to use to display a value in a dialog
0160     /// @return the value @p ptValue converted the unit and rounded, ready to be displayed
0161     QString toUserStringValue(qreal ptValue) const;
0162 
0163     /// This method is the one to use to read a value from a dialog
0164     /// @return the value converted to points for internal use
0165     qreal fromUserValue(qreal value) const;
0166 
0167     /// This method is the one to use to read a value from a dialog
0168     /// @param value value entered by the user
0169     /// @param ok if set, the pointed bool is set to true if the value could be
0170     /// converted to a qreal, and to false otherwise.
0171     /// @return the value converted to points for internal use
0172     qreal fromUserValue(const QString &value, bool *ok = 0) const;
0173 
0174     /// Get the description string of the given unit
0175     static QString unitDescription(KoUnit::Type type);
0176 
0177     /// Get the symbol string of the unit
0178     QString symbol() const;
0179 
0180     /// Returns the list of unit types for the UI, controlled with the given @p listOptions.
0181     static QStringList listOfUnitNameForUi(ListOptions listOptions = ListAll);
0182 
0183     /// Get the index of this unit in the list of unit types for the UI,
0184     /// if it is controlled with the given @p listOptions.
0185     int indexInListForUi(ListOptions listOptions = ListAll) const;
0186 
0187     /// parse common %Calligra and Odf values, like "10cm", "5mm" to pt
0188     static qreal parseValue(const QString &value, qreal defaultVal = 0.0);
0189 
0190     /// parse an angle to its value in degrees
0191     static qreal parseAngle(const QString &value, qreal defaultVal = 0.0);
0192 
0193     QString toString() const {
0194         return symbol();
0195     }
0196 
0197     /**
0198      * Get an approximate scale of a unit vector that was converted by
0199      * the transformation.
0200      *
0201      * Please note that exact values are guaranteed only for
0202      * combinations of Translate, Rotation and Uniform Scale
0203      * matrices. For combinations having shears and perspective the
0204      * value will be average for the point near CS origin.
0205      */
0206     static qreal approxTransformScale(const QTransform &t);
0207 
0208     /**
0209      * Adjust the unit by pixel transformation applied to the
0210      * describing object. It multiplies the pixel coefficient by the
0211      * average scale of the matrix.
0212      */
0213     void adjustByPixelTransform(const QTransform &t);
0214 
0215 private:
0216     Type m_type;
0217     qreal m_pixelConversion;
0218 };
0219 
0220 #ifndef QT_NO_DEBUG_STREAM
0221 KRITAGLOBAL_EXPORT QDebug operator<<(QDebug, const KoUnit &);
0222 #endif
0223 
0224 Q_DECLARE_METATYPE(KoUnit)
0225 Q_DECLARE_OPERATORS_FOR_FLAGS(KoUnit::ListOptions)
0226 
0227 #endif