Krita Source Code Documentation
Loading...
Searching...
No Matches
KoUnit.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2001 David Faure <faure@kde.org>
3 SPDX-FileCopyrightText: 2004 Nicolas GOUTTE <goutte@kde.org>
4 SPDX-FileCopyrightText: 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "KoUnit.h"
10
11#include <cmath>
12
13#include <QTransform>
14
15#include <klocalizedstring.h>
16#include <QtGlobal>
17
18
19// ensure the same order as in KoUnit::Unit
20static const char* const unitNameList[KoUnit::TypeCount] =
21{
22 "mm",
23 "pt",
24 "in",
25 "cm",
26 "dm",
27 "pi",
28 "cc",
29 "px"
30};
31
33{
34 switch (type) {
36 return i18n("Millimeters (mm)");
38 return i18n("Centimeters (cm)");
40 return i18n("Decimeters (dm)");
41 case KoUnit::Inch:
42 return i18n("Inches (in)");
43 case KoUnit::Pica:
44 return i18n("Pica (pi)");
45 case KoUnit::Cicero:
46 return i18n("Cicero (cc)");
47 case KoUnit::Point:
48 return i18n("Points (pt)");
49 case KoUnit::Pixel:
50 return i18n("Pixels (px)");
51 default:
52 return i18n("Unsupported unit");
53 }
54}
55
56// grouped by units which are similar
68
70{
71 QStringList lst;
72 for (int i = 0; i < KoUnit::TypeCount; ++i) {
73 const Type type = typesInUi[i];
74 if ((type != Pixel) || ((listOptions & HideMask) == ListAll))
75 lst.append(unitDescription(type));
76 }
77 return lst;
78}
79
80KoUnit KoUnit::fromListForUi(int index, ListOptions listOptions, qreal factor)
81{
83
84 if ((0 <= index) && (index < KoUnit::TypeCount)) {
85 // iterate through all enums and skip the Pixel enum if needed
86 for (int i = 0; i < KoUnit::TypeCount; ++i) {
87 if ((listOptions&HidePixel) && (typesInUi[i] == Pixel)) {
88 ++index;
89 continue;
90 }
91 if (i == index) {
92 type = typesInUi[i];
93 break;
94 }
95 }
96 }
97
98 return KoUnit(type, factor);
99}
100
101int KoUnit::indexInListForUi(ListOptions listOptions) const
102{
103 if ((listOptions&HidePixel) && (m_type == Pixel)) {
104 return -1;
105 }
106
107 int result = -1;
108
109 int skipped = 0;
110 for (int i = 0; i < KoUnit::TypeCount; ++i) {
111 if ((listOptions&HidePixel) && (typesInUi[i] == Pixel)) {
112 ++skipped;
113 continue;
114 }
115 if (typesInUi[i] == m_type) {
116 result = i - skipped;
117 break;
118 }
119 }
120
121 return result;
122}
123
124
125
126qreal KoUnit::toUserValueRounded(const qreal value) const
127{
128 qreal userValue = toUserValuePrecise(value);
129 qreal rounding = 1.0;
130
131 switch (m_type) {
132 case Pixel:
133 return userValue; // no rounding for Pixel value
134 case Millimeter:
135 rounding = MM_ROUNDING;
136 break;
137 case Centimeter:
138 rounding = CM_ROUNDING;
139 break;
140 case Decimeter:
141 rounding = DM_ROUNDING;
142 break;
143 case Inch:
144 rounding = IN_ROUNDING;
145 break;
146 case Pica:
147 rounding = PI_ROUNDING;
148 break;
149 case Cicero:
150 rounding = CC_ROUNDING;
151 break;
152 case Point:
153 default:
154 rounding = PT_ROUNDING;
155 }
156
157
158 return floor(userValue * rounding) / rounding;
159}
160
161qreal KoUnit::toUserValuePrecise(const qreal ptValue) const
162{
163 switch (m_type) {
164 case Millimeter:
165 return POINT_TO_MM(ptValue);
166 case Centimeter:
167 return POINT_TO_CM(ptValue);
168 case Decimeter:
169 return POINT_TO_DM(ptValue);
170 case Inch:
171 return POINT_TO_INCH(ptValue);
172 case Pica:
173 return POINT_TO_PI(ptValue);
174 case Cicero:
175 return POINT_TO_CC(ptValue);
176 case Pixel:
177 return ptValue * m_pixelConversion;
178 case Point:
179 default:
180 return ptValue;
181 }
182}
183
184
185
186qreal KoUnit::toUserValue(qreal ptValue, bool rounding) const
187{
188 if (rounding) {
189 return toUserValueRounded(ptValue);
190 }
191 else {
192 return toUserValuePrecise(ptValue);
193 }
194}
195
196QString KoUnit::toUserStringValue(qreal ptValue) const
197{
198 return QLocale().toString(toUserValue(ptValue));
199}
200
201qreal KoUnit::fromUserValue(qreal value) const
202{
203 switch (m_type) {
204 case Millimeter:
205 return MM_TO_POINT(value);
206 case Centimeter:
207 return CM_TO_POINT(value);
208 case Decimeter:
209 return DM_TO_POINT(value);
210 case Inch:
211 return INCH_TO_POINT(value);
212 case Pica:
213 return PI_TO_POINT(value);
214 case Cicero:
215 return CC_TO_POINT(value);
216 case Pixel:
217 return value / m_pixelConversion;
218 case Point:
219 default:
220 return value;
221 }
222}
223
224qreal KoUnit::fromUserValue(const QString &value, bool *ok) const
225{
226 return fromUserValue(QLocale().toDouble(value, ok));
227}
228
229qreal KoUnit::parseValue(const QString& _value, qreal defaultVal)
230{
231 if (_value.isEmpty())
232 return defaultVal;
233
234 QString value(_value.simplified());
235 value.remove(QLatin1Char(' '));
236
237 int firstLetter = -1;
238 for (int i = 0; i < value.length(); ++i) {
239 if (value.at(i).isLetter()) {
240 if (value.at(i) == QLatin1Char('e'))
241 continue;
242 firstLetter = i;
243 break;
244 }
245 }
246
247 if (firstLetter == -1)
248 return value.toDouble();
249
250 const QString symbol = value.mid(firstLetter);
251 value.truncate(firstLetter);
252 const qreal val = value.toDouble();
253
254 if (symbol == QLatin1String("pt"))
255 return val;
256
257 bool ok;
259 if (ok)
260 return u.fromUserValue(val);
261
262 if (symbol == QLatin1String("m"))
263 return DM_TO_POINT(val * 10.0);
264 else if (symbol == QLatin1String("km"))
265 return DM_TO_POINT(val * 10000.0);
266
267 // TODO : add support for mi/ft ?
268 return defaultVal;
269}
270
271KoUnit KoUnit::fromSymbol(const QString &symbol, bool *ok)
272{
273 Type result = Point;
274
275 if (symbol == QLatin1String("inch") /*compat*/) {
276 result = Inch;
277 if (ok)
278 *ok = true;
279 } else {
280 if (ok)
281 *ok = false;
282
283 for (int i = 0; i < TypeCount; ++i) {
284 if (symbol == QLatin1String(unitNameList[i])) {
285 result = static_cast<Type>(i);
286 if (ok)
287 *ok = true;
288 }
289 }
290 }
291
292 return KoUnit(result);
293}
294
295qreal KoUnit::convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor)
296{
297 qreal pt;
298 switch (fromUnit.type()) {
299 case Millimeter:
300 pt = MM_TO_POINT(value);
301 break;
302 case Centimeter:
303 pt = CM_TO_POINT(value);
304 break;
305 case Decimeter:
306 pt = DM_TO_POINT(value);
307 break;
308 case Inch:
309 pt = INCH_TO_POINT(value);
310 break;
311 case Pica:
312 pt = PI_TO_POINT(value);
313 break;
314 case Cicero:
315 pt = CC_TO_POINT(value);
316 break;
317 case Pixel:
318 pt = value / factor;
319 break;
320 case Point:
321 default:
322 pt = value;
323 }
324
325 switch (toUnit.type()) {
326 case Millimeter:
327 return POINT_TO_MM(pt);
328 case Centimeter:
329 return POINT_TO_CM(pt);
330 case Decimeter:
331 return POINT_TO_DM(pt);
332 case Inch:
333 return POINT_TO_INCH(pt);
334 case Pica:
335 return POINT_TO_PI(pt);
336 case Cicero:
337 return POINT_TO_CC(pt);
338 case Pixel:
339 return pt * factor;
340 case Point:
341 default:
342 return pt;
343 }
344
345}
346
347QString KoUnit::symbol() const
348{
349 return QLatin1String(unitNameList[m_type]);
350}
351
352qreal KoUnit::parseAngle(const QString& _value, qreal defaultVal)
353{
354 if (_value.isEmpty())
355 return defaultVal;
356
357 QString value(_value.simplified());
358 value.remove(QLatin1Char(' '));
359
360 int firstLetter = -1;
361 for (int i = 0; i < value.length(); ++i) {
362 if (value.at(i).isLetter()) {
363 if (value.at(i) == QLatin1Char('e'))
364 continue;
365 firstLetter = i;
366 break;
367 }
368 }
369
370 if (firstLetter == -1)
371 return value.toDouble();
372
373 const QString type = value.mid(firstLetter);
374 value.truncate(firstLetter);
375 const qreal val = value.toDouble();
376
377 if (type == QLatin1String("deg"))
378 return val;
379 else if (type == QLatin1String("rad"))
380 return val * 180 / M_PI;
381 else if (type == QLatin1String("grad"))
382 return val * 0.9;
383
384 return defaultVal;
385}
386
387qreal KoUnit::approxTransformScale(const QTransform &t)
388{
389 return std::sqrt(qAbs(t.determinant()));
390}
391
392void KoUnit::adjustByPixelTransform(const QTransform &t)
393{
395}
396
397#ifndef QT_NO_DEBUG_STREAM
398QDebug operator<<(QDebug debug, const KoUnit &unit)
399{
400#ifndef NDEBUG
401 debug.nospace() << unit.symbol();
402#else
403 Q_UNUSED(unit);
404#endif
405 return debug.space();
406
407}
408#endif
float value(const T *src, size_t ch)
qreal u
static const KoUnit::Type typesInUi[KoUnit::TypeCount]
Definition KoUnit.cpp:57
QDebug operator<<(QDebug debug, const KoUnit &unit)
Definition KoUnit.cpp:398
static const char *const unitNameList[KoUnit::TypeCount]
Definition KoUnit.cpp:20
constexpr qreal POINT_TO_CM(qreal px)
Definition KoUnit.h:33
constexpr qreal POINT_TO_DM(qreal px)
Definition KoUnit.h:35
constexpr qreal CC_TO_POINT(qreal cc)
Definition KoUnit.h:44
constexpr qreal POINT_TO_MM(qreal px)
Definition KoUnit.h:31
constexpr qreal POINT_TO_INCH(qreal px)
Definition KoUnit.h:37
constexpr qreal CM_TO_POINT(qreal cm)
Definition KoUnit.h:34
static const qreal IN_ROUNDING
Definition KoUnit.h:54
static const qreal PT_ROUNDING
Definition KoUnit.h:47
constexpr qreal INCH_TO_POINT(qreal inch)
Definition KoUnit.h:38
static const qreal MM_ROUNDING
Definition KoUnit.h:52
constexpr qreal POINT_TO_PI(qreal px)
Definition KoUnit.h:41
static const qreal CM_ROUNDING
Definition KoUnit.h:50
static const qreal DM_ROUNDING
Definition KoUnit.h:51
constexpr qreal PI_TO_POINT(qreal pi)
Definition KoUnit.h:43
constexpr qreal POINT_TO_CC(qreal px)
Definition KoUnit.h:42
constexpr qreal MM_TO_POINT(qreal mm)
Definition KoUnit.h:32
static const qreal CC_ROUNDING
Definition KoUnit.h:57
static const qreal PI_ROUNDING
Definition KoUnit.h:56
constexpr qreal DM_TO_POINT(qreal dm)
Definition KoUnit.h:36
static qreal parseAngle(const QString &value, qreal defaultVal=0.0)
parse an angle to its value in degrees
Definition KoUnit.cpp:352
QString toUserStringValue(qreal ptValue) const
Definition KoUnit.cpp:196
qreal m_pixelConversion
Definition KoUnit.h:213
static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor=1.0)
Definition KoUnit.cpp:295
static QString unitDescription(KoUnit::Type type)
Get the description string of the given unit.
Definition KoUnit.cpp:32
Type m_type
Definition KoUnit.h:212
static qreal parseValue(const QString &value, qreal defaultVal=0.0)
parse common Krita and Odf values, like "10cm", "5mm" to pt
Definition KoUnit.cpp:229
qreal fromUserValue(qreal value) const
Definition KoUnit.cpp:201
static qreal approxTransformScale(const QTransform &t)
Definition KoUnit.cpp:387
@ HideMask
Definition KoUnit.h:90
@ HidePixel
Definition KoUnit.h:89
@ ListAll
Definition KoUnit.h:88
KoUnit::Type type() const
Definition KoUnit.h:118
qreal toUserValuePrecise(const qreal ptValue) const
Definition KoUnit.cpp:161
static KoUnit fromSymbol(const QString &symbol, bool *ok=0)
Definition KoUnit.cpp:271
static KoUnit fromListForUi(int index, ListOptions listOptions=ListAll, qreal factor=1.0)
Definition KoUnit.cpp:80
qreal toUserValueRounded(const qreal value) const
Definition KoUnit.cpp:126
QString symbol() const
Get the symbol string of the unit.
Definition KoUnit.cpp:347
KoUnit(Type unit=Point, qreal factor=1.0)
Definition KoUnit.h:103
@ Point
Postscript point, 1/72th of an Inco.
Definition KoUnit.h:76
@ Centimeter
Definition KoUnit.h:78
@ Decimeter
Definition KoUnit.h:79
@ Pica
Definition KoUnit.h:80
@ Millimeter
Definition KoUnit.h:75
@ Inch
Definition KoUnit.h:77
@ Pixel
Definition KoUnit.h:82
@ Cicero
Definition KoUnit.h:81
@ TypeCount
Definition KoUnit.h:83
void adjustByPixelTransform(const QTransform &t)
Definition KoUnit.cpp:392
static QStringList listOfUnitNameForUi(ListOptions listOptions=ListAll)
Returns the list of unit types for the UI, controlled with the given listOptions.
Definition KoUnit.cpp:69
qreal toUserValue(qreal ptValue, bool rounding=true) const
Definition KoUnit.cpp:186
int indexInListForUi(ListOptions listOptions=ListAll) const
Definition KoUnit.cpp:101
#define M_PI
Definition kis_global.h:111
double toDouble(const quint8 *data, int channelpos)