1 /* This file is part of the KDE project
2    Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4    Copyright (C) 2004, Nicolas GOUTTE <goutte@kde.org>
5    Copyright (C) 2010 Thomas Zander <zander@kde.org>
6    Copyright 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
7 
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Library General Public
10    License as published by the Free Software Foundation; either
11    version 2 of the License, or (at your option) any later version.
12 
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17 
18    You should have received a copy of the GNU Library General Public License
19    along with this library; see the file COPYING.LIB.  If not, write to
20    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22 */
23 
24 #ifndef KOUNIT_H
25 #define KOUNIT_H
26 
27 // Calligra
28 #include "kritaodf_export.h"
29 // Qt
30 #include <QString>
31 #include <QDebug>
32 #include <QMetaType>
33 // std
34 #include <math.h> // for floor
35 
36 class QStringList;
37 
38 // 1 inch ^= 72 pt
39 // 1 inch ^= 25.399956 mm (-pedantic ;p)
40 // 1 pt = 1/12 pi
41 // 1 pt ^= 0.0077880997 cc
42 // 1 cc = 12 dd
43 
POINT_TO_MM(qreal px)44 constexpr qreal POINT_TO_MM(qreal px) {return (px)*0.352777167;}
MM_TO_POINT(qreal mm)45 constexpr qreal MM_TO_POINT(qreal mm) {return mm*2.83465058;}
POINT_TO_CM(qreal px)46 constexpr qreal POINT_TO_CM(qreal px) {return (px)*0.0352777167;}
CM_TO_POINT(qreal cm)47 constexpr qreal CM_TO_POINT(qreal cm) {return (cm)*28.3465058;}
POINT_TO_DM(qreal px)48 constexpr qreal POINT_TO_DM(qreal px) {return (px)*0.00352777167;}
DM_TO_POINT(qreal dm)49 constexpr qreal DM_TO_POINT(qreal dm) {return (dm)*283.465058;}
POINT_TO_INCH(qreal px)50 constexpr qreal POINT_TO_INCH(qreal px) {return (px)*0.01388888888889;}
INCH_TO_POINT(qreal inch)51 constexpr qreal INCH_TO_POINT(qreal inch) {return (inch)*72.0;}
MM_TO_INCH(qreal mm)52 constexpr qreal MM_TO_INCH(qreal mm) {return (mm)*0.039370147;}
INCH_TO_MM(qreal inch)53 constexpr qreal INCH_TO_MM(qreal inch) {return (inch)*25.399956;}
POINT_TO_PI(qreal px)54 constexpr qreal POINT_TO_PI(qreal px) {return (px)*0.083333333;}
POINT_TO_CC(qreal px)55 constexpr qreal POINT_TO_CC(qreal px) {return (px)*0.077880997;}
PI_TO_POINT(qreal pi)56 constexpr qreal PI_TO_POINT(qreal pi) {return (pi)*12;}
CC_TO_POINT(qreal cc)57 constexpr qreal CC_TO_POINT(qreal cc) {return (cc)*12.840103;}
58 
59 
60 static const qreal PT_ROUNDING {1000.0};
61 //static const qreal PX_ROUNDING {1000.0}; // pixel value is not to be rounded
62 
63 static const qreal CM_ROUNDING {10000.0};
64 static const qreal DM_ROUNDING {10000.0};
65 static const qreal MM_ROUNDING {10000.0};
66 
67 static const qreal IN_ROUNDING {100000.0};
68 
69 static const qreal PI_ROUNDING {100000.0}; // pico
70 static const qreal CC_ROUNDING {100000.0}; // cicero
71 
72 
73 /**
74  * %Calligra stores everything in pt (using "qreal") internally.
75  * When displaying a value to the user, the value is converted to the user's unit
76  * of choice, and rounded to a reasonable precision to avoid 0.999999
77  *
78  * For implementing the selection of a unit type in the UI use the *ForUi() methods.
79  * They ensure the same order of the unit types in all places, with the order not
80  * bound to the order in the enum (so ABI-compatible extension is possible) and
81  * with the order and scope of listed types controlled by the @c ListOptions parameter.
82  */
83 class KRITAODF_EXPORT KoUnit
84 {
85 public:
86     /** Length units supported by Calligra. */
87     enum Type {
88         Millimeter = 0,
89         Point,  ///< Postscript point, 1/72th of an Inco
90         Inch,
91         Centimeter,
92         Decimeter,
93         Pica,
94         Cicero,
95         Pixel,
96         TypeCount ///< @internal
97     };
98 
99     /// Used to control the scope of the unit types listed in the UI
100     enum ListOption {
101         ListAll = 0,
102         HidePixel = 1,
103         HideMask = HidePixel
104     };
105      Q_DECLARE_FLAGS(ListOptions, ListOption)
106 
107     /** Returns a KoUnit instance with the type at the @p index of the UI list with the given @p listOptions. */
108     static KoUnit fromListForUi(int index, ListOptions listOptions = ListAll, qreal factor = 1.0);
109 
110     /// Convert a unit symbol string into a KoUnit
111     /// @param symbol symbol to convert
112     /// @param ok if set, it will be true if the unit was known, false if unknown
113     static KoUnit fromSymbol(const QString &symbol, bool *ok = 0);
114 
115     /** Construction requires initialization. The factor is for variable factor units like pixel */
116     explicit KoUnit(Type unit = Point, qreal factor = 1.0) {
117         m_type = unit;
118         m_pixelConversion = factor;
119     }
120 
121     KoUnit& operator=(Type unit) {
122         m_type = unit; m_pixelConversion = 1.0; return *this;
123     }
124 
125     bool operator!=(const KoUnit &other) const {
126         return !operator==(other);
127     }
128 
129     bool operator==(const KoUnit &other) const {
130         return m_type == other.m_type &&
131             (m_type != Pixel ||
132              qFuzzyCompare(m_pixelConversion, other.m_pixelConversion));
133     }
134 
type()135     KoUnit::Type type() const {
136         return m_type;
137     }
138 
setFactor(qreal factor)139     void setFactor(qreal factor) {
140         m_pixelConversion = factor;
141     }
142 
143 
144     /**
145      * convert the given value directly from one unit to another
146      */
147     static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor = 1.0);
148 
149     /**
150      * Convert the value @p ptValue to the unit and round it.
151      * This method is meant to be used to display a value in a dialog.
152      * \return the converted and rounded value
153      */
154 
155     qreal toUserValueRounded(const qreal value) const;
156     /**
157      * Convert the value @p ptValue to the unit (without rounding)
158      * This method is meant to be used in complex calculations.
159      * \return the converted value
160      */
161     qreal toUserValuePrecise(const qreal ptValue) const;
162 
163     /**
164      * Convert the value @p ptValue with or with rounding as indicated by @p rounding.
165      * This method is a proxy to toUserValuePrecise and toUserValueRounded.
166      * \return the value @p ptValue converted to unit
167      */
168     qreal toUserValue(qreal ptValue, bool rounding = true) const;
169 
170 
171 
172     /// This method is the one to use to display a value in a dialog
173     /// @return the value @p ptValue converted the unit and rounded, ready to be displayed
174     QString toUserStringValue(qreal ptValue) const;
175 
176     /// This method is the one to use to read a value from a dialog
177     /// @return the value converted to points for internal use
178     qreal fromUserValue(qreal value) const;
179 
180     /// This method is the one to use to read a value from a dialog
181     /// @param value value entered by the user
182     /// @param ok if set, the pointed bool is set to true if the value could be
183     /// converted to a qreal, and to false otherwise.
184     /// @return the value converted to points for internal use
185     qreal fromUserValue(const QString &value, bool *ok = 0) const;
186 
187     /// Get the description string of the given unit
188     static QString unitDescription(KoUnit::Type type);
189 
190     /// Get the symbol string of the unit
191     QString symbol() const;
192 
193     /// Returns the list of unit types for the UI, controlled with the given @p listOptions.
194     static QStringList listOfUnitNameForUi(ListOptions listOptions = ListAll);
195 
196     /// Get the index of this unit in the list of unit types for the UI,
197     /// if it is controlled with the given @p listOptions.
198     int indexInListForUi(ListOptions listOptions = ListAll) const;
199 
200     /// parse common %Calligra and Odf values, like "10cm", "5mm" to pt
201     static qreal parseValue(const QString &value, qreal defaultVal = 0.0);
202 
203     /// parse an angle to its value in degrees
204     static qreal parseAngle(const QString &value, qreal defaultVal = 0.0);
205 
toString()206     QString toString() const {
207         return symbol();
208     }
209 
210     /**
211      * Get an approximate scale of a unit vector that was converted by
212      * the transformation.
213      *
214      * Please note that exact values are guaranteed only for
215      * combinations of Translate, Rotation and Uniform Scale
216      * matrices. For combinations having shears and perspective the
217      * value will be average for the point near CS origin.
218      */
219     static qreal approxTransformScale(const QTransform &t);
220 
221     /**
222      * Adjust the unit by pixel transformation applied to the
223      * describing object. It multiplies the pixel coefficient by the
224      * average scale of the matrix.
225      */
226     void adjustByPixelTransform(const QTransform &t);
227 
228 private:
229     Type m_type;
230     qreal m_pixelConversion;
231 };
232 
233 #ifndef QT_NO_DEBUG_STREAM
234 KRITAODF_EXPORT QDebug operator<<(QDebug, const KoUnit &);
235 #endif
236 
237 Q_DECLARE_METATYPE(KoUnit)
238 Q_DECLARE_OPERATORS_FOR_FLAGS(KoUnit::ListOptions)
239 
240 #endif
241