1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 begin : Jan 2005
9 copyright : (C) 2005 by Craig Bradney
10 email : cbradney@zip.com.au
11 ***************************************************************************/
12
13 /***************************************************************************
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 ***************************************************************************/
21
22 #include <cmath>
23 #include <QLocale>
24 #include <QString>
25 #include <QObject>
26 #include "localemgr.h"
27 #include "scribuscore.h"
28 #include "units.h"
29
30 /*!
31 * @brief Returns the ratio to points for the selected unit of measure. Ratios are for: PT, MM, IN, P, CM, C. DEG and PCT return 1.0 as they will never convert
32 */
unitGetRatioFromIndex(const int index)33 double unitGetRatioFromIndex(const int index)
34 {
35 //PT, MM, IN, P, CM, C (Cicero)
36 //NOTE: Calling functions that divide by this value will crash on divide by 0. They shouldn't be getting
37 // a zero value if they are accessing here with a correct index.
38 if (index<UNITMIN || index>UNITMAX)
39 return 0;
40 // PT, MM, IN, P, CM, C, °, %
41 double ratio[] = { 1.0, 25.4 / 72.0, 1.0 / 72.0, 1.0, 2.54 / 72.0, 25.4 / 72.0 / 4.512, 1.0, 1.0 };
42 return ratio[index];
43 }
44
unitGetBaseFromIndex(const int index)45 int SCRIBUS_API unitGetBaseFromIndex(const int index)
46 {
47 if (index == SC_P)
48 return 12;
49 return 10;
50 }
51
52 /*!
53 * @brief Strip the text from a value and return the double value for the unit
54 */
unitValueFromString(const QString & value)55 double unitValueFromString(const QString& value)
56 {
57 QString lowerValue = value.toLower();
58 QString dbl = "0.0";
59 if (lowerValue.indexOf("pt") != -1)
60 {
61 dbl = lowerValue.remove("pt");
62 }
63 else if (lowerValue.indexOf("mm") != -1)
64 {
65 dbl = lowerValue.remove("mm");
66 }
67 else if (lowerValue.indexOf("in") != -1)
68 {
69 dbl = lowerValue.remove("in");
70 }
71 else if (lowerValue.indexOf("p") != -1)
72 {
73 dbl = lowerValue.remove("p");
74 }
75 else if (lowerValue.indexOf("cm") != -1)
76 {
77 dbl = lowerValue.remove("cm");
78 }
79 else if (lowerValue.indexOf("°") != -1)
80 {
81 dbl = lowerValue.remove("°");
82 }
83 else if (lowerValue.indexOf("%") != -1)
84 {
85 dbl = lowerValue.remove("%");
86 }
87 else
88 dbl = "0.0";
89
90 dbl = dbl.trimmed();
91 return dbl.toDouble();
92 }
93
94 /*!
95 * @brief Strip the text from a value and return the Unit index for the value
96 */
unitIndexFromString(const QString & value)97 scUnit unitIndexFromString(const QString& value)
98 {
99 QString lowerValue = value.toLower();
100 scUnit retVal;
101 if (lowerValue.indexOf("pt") != -1)
102 {
103 retVal = SC_PT;
104 }
105 else if (lowerValue.indexOf("mm") != -1)
106 {
107 retVal = SC_MM;
108 }
109 else if (lowerValue.indexOf("in") != -1)
110 {
111 retVal = SC_IN;
112 }
113 else if (lowerValue.indexOf("p") != -1)
114 {
115 retVal = SC_P;
116 }
117 else if (lowerValue.indexOf("cm") != -1)
118 {
119 retVal = SC_CM;
120 }
121 else if (lowerValue.indexOf("c") != -1)
122 {
123 retVal = SC_C;
124 }
125 else if (lowerValue.indexOf("°") != -1)
126 {
127 retVal = SC_DEGREES;
128 }
129 else if (lowerValue.indexOf("%") != -1)
130 {
131 retVal = SC_PERCENT;
132 }
133 else
134 retVal = SC_PT;
135 return retVal;
136 }
137
138 /*!
139 * @brief Returns the suffix used in GUI widgets
140 */
unitGetSuffixFromIndex(const int index)141 QString unitGetSuffixFromIndex(const int index)
142 {
143 if (index == SC_P)
144 return QString();
145 return QString(" %1").arg(unitGetStrFromIndex(index));
146 }
147
148 /*!
149 * @brief Returns a general suffix for each of the units
150 */
unitGetStrFromIndex(const int index)151 QString unitGetStrFromIndex(const int index)
152 {
153 if (index < UNITMIN || index > UNITMAX)
154 return QString();
155 QString suffix[] = {
156 QObject::tr("pt"),
157 QObject::tr("mm"),
158 QObject::tr("in"),
159 QObject::tr("p"),
160 QObject::tr("cm"),
161 QObject::tr("c"),
162 QObject::tr("\302\260", "degrees, unicode 0xB0"), //degree
163 QObject::tr("%")
164 };
165 return suffix[index];
166 }
167
168 /*!
169 * @brief Returns a general untranslated suffix for each of the units
170 */
unitGetUntranslatedStrFromIndex(const int index)171 QString unitGetUntranslatedStrFromIndex(const int index)
172 {
173 if (index < UNITMIN || index > UNITMAX)
174 return QString();
175 QString suffix[] = { "pt", "mm", "in", "p", "cm", "c", "\xB0", "%" };
176 return suffix[index];
177 }
178 /*!
179 * @brief Returns the decimals for the units
180 */
unitGetDecimalsFromIndex(const int index)181 int unitGetDecimalsFromIndex(const int index)
182 {
183 if (index < UNITMIN || index > UNITMAX)
184 return 0;
185 // PT, MM, IN, P, CM, C, °, %
186 int decimalPoints[] = {100, 1000, 10000, 100, 10000, 10000, 100, 100};
187 return decimalPoints[index];
188 }
189
190 /*!
191 * @brief Returns the precision for the units
192 */
unitGetPrecisionFromIndex(const int index)193 int unitGetPrecisionFromIndex(const int index)
194 {
195 if (index < UNITMIN || index > UNITMAX)
196 return 0;
197 // PT,MM,IN, P,CM, C, °, %
198 int precision[] = {2, 3, 4, 2, 4, 4, 2, 2};
199 return precision[index];
200 }
201
202 /*!
203 * @brief Returns a QStringList of the units for use in QComboBoxes etc
204 */
unitGetTextUnitList()205 QStringList unitGetTextUnitList()
206 {
207 QStringList suffixList;
208 suffixList.append( QObject::tr( "Points (pt)" ) );
209 suffixList.append( QObject::tr( "Millimeters (mm)" ) );
210 suffixList.append( QObject::tr( "Inches (in)" ) );
211 suffixList.append( QObject::tr( "Picas (p)" ) );
212 suffixList.append( QObject::tr( "Centimeters (cm)" ) );
213 suffixList.append( QObject::tr( "Cicero (c)" ) );
214 //Here for completeness, don't use!
215 //suffixList.append( QObject::tr( "°" ) );
216 //suffixList.append( QObject::tr( "%" ) );
217 return QStringList(suffixList);
218 }
219
220 /*!
221 * @brief Returns the maximum index of the units we have now
222 */
unitGetMaxIndex()223 int unitGetMaxIndex()
224 {
225 return UNITMAX;
226 }
227
228 /*!
229 * @brief Returns the pts value from the mm value supplied
230 */
mm2pts(double mm)231 double mm2pts(double mm)
232 {
233 return mm / unitGetRatioFromIndex(SC_MM);
234 }
235
236 /*!
237 * @brief Returns the pts value from the in value supplied
238 */
in2pts(double in)239 double in2pts(double in)
240 {
241 return in / unitGetRatioFromIndex(SC_IN);
242 }
243
244 /*!
245 * @brief Returns the pts value from the pica value supplied
246 */
p2pts(double p)247 double p2pts(double p)
248 {
249 return p / unitGetRatioFromIndex(SC_P);
250 }
251
252 /*!
253 * @brief Returns the pts value from the cm value supplied
254 */
cm2pts(double cm)255 double cm2pts(double cm)
256 {
257 return cm / unitGetRatioFromIndex(SC_CM);
258 }
259
260 /*!
261 * @brief Returns the pts value from the cm value supplied
262 */
c2pts(double c)263 double c2pts(double c)
264 {
265 return c / unitGetRatioFromIndex(SC_C);
266 }
267
268 /*!
269 * @brief Returns the mm value from the pt value supplied
270 */
pts2mm(double pts)271 double pts2mm(double pts)
272 {
273 return pts * unitGetRatioFromIndex(SC_MM);
274 }
275
276 /*!
277 * @brief Returns the in value from the pt value supplied
278 */
pts2in(double pts)279 double pts2in(double pts)
280 {
281 return pts * unitGetRatioFromIndex(SC_IN);
282 }
283
284 /*!
285 * @brief Returns the pica value from the pt value supplied
286 */
pts2p(double pts)287 double pts2p(double pts)
288 {
289 return pts * unitGetRatioFromIndex(SC_P);
290 }
291
292 /*!
293 * @brief Returns the cm value from the pt value supplied
294 */
pts2cm(double pts)295 double pts2cm(double pts)
296 {
297 return pts * unitGetRatioFromIndex(SC_CM);
298 }
299
300 /*!
301 * @brief Returns the c value from the pt value supplied
302 */
pts2c(double pts)303 double pts2c(double pts)
304 {
305 return pts * unitGetRatioFromIndex(SC_C);
306 }
307
308 /*!
309 * @brief Returns the value from the pt value supplied based on unit index
310 */
pts2value(double unitValue,int unit)311 double pts2value(double unitValue, int unit)
312 {
313 double ret = 0.0;
314 switch (unit)
315 {
316 case SC_PT:
317 case SC_P:
318 case SC_DEG:
319 case SC_PCT:
320 ret = unitValue; //don't multiply by 1
321 break;
322 default:
323 ret = unitValue * unitGetRatioFromIndex(unit);
324 break;
325 }
326 return ret;
327 }
328
329 /*!
330 * @brief Returns the pt value from the value supplied based on unit index
331 */
value2pts(double unitValue,int unit)332 double value2pts(double unitValue, int unit)
333 {
334 double ret = 0.0;
335 switch (unit)
336 {
337 case SC_PT:
338 case SC_P:
339 case SC_DEG:
340 case SC_PCT:
341 ret = unitValue; // don't divide by 1
342 break;
343 default:
344 ret = unitValue / unitGetRatioFromIndex(unit);
345 break;
346 }
347 return ret;
348 }
349
350 /*!
351 * @brief Returns the secondary unit value from the value supplied based on primary unit
352 */
value2value(double unitValue,int primaryUnit,int secondaryUnit)353 double value2value(double unitValue, int primaryUnit, int secondaryUnit)
354 {
355 if (primaryUnit==secondaryUnit)
356 return unitValue;
357
358 //Can make this not convert to points at a later stage, for now, the function exists and works.
359 double pts = primaryUnit == 0 ? unitValue : unitValue / unitGetRatioFromIndex(primaryUnit);
360 double ret = secondaryUnit == 0 ? pts : pts * unitGetRatioFromIndex(secondaryUnit);
361 return ret;
362 }
363
value2String(double unitValue,int unitIndex,bool round2Precision,bool appendSuffix)364 QString value2String(double unitValue, int unitIndex, bool round2Precision, bool appendSuffix)
365 {
366 QString s;
367
368 if (unitIndex == SC_PICAS)
369 {
370 int i = (static_cast<int>(unitValue))/12;
371 double d = fabs(fmod(unitValue, 12));
372 QString prefix((i == 0 && unitValue < 0.0) ? "-" : "");
373 s=QString("%1%2%3%4").arg(prefix).arg(i).arg(unitGetStrFromIndex(unitIndex)).arg(d);
374 }
375 else
376 {
377 if (round2Precision)
378 s=LocaleManager::instance().userPreferredLocale().toString(pts2value(unitValue, unitIndex), 'f', unitGetPrecisionFromIndex(unitIndex));
379 else
380 s=LocaleManager::instance().userPreferredLocale().toString(pts2value(unitValue, unitIndex));
381 if (appendSuffix)
382 s += " " + unitGetStrFromIndex(unitIndex);
383 }
384 return s;
385 }
386
387 /*!
388 * @brief Sets up iteration value 1 for vruler, hruler and tabruler
389 */
unitRulerGetIter1FromIndex(const int index)390 double unitRulerGetIter1FromIndex(const int index)
391 {
392 if (!unitValidForDocUnit(index))
393 return 0;
394 // PT, MM, IN, P, CM, C, °, %
395 double iter[] = {10.0, 720.0 / 25.4, 18.0, 12.0, 72.0 / 25.4, 72.0 / 25.4 * 4.512, 10.0, 10.0};
396 return iter[index];
397 }
398
399 /*!
400 * @brief Sets up iteration value 2 for vruler, hruler and tabruler
401 */
unitRulerGetIter2FromIndex(const int index)402 double unitRulerGetIter2FromIndex(const int index)
403 {
404 if (!unitValidForDocUnit(index))
405 return 0;
406 // PT, MM, IN, P, CM, C, °, %
407 double iter[] = {100.0, 7200.0 / 25.4, 72.0, 120.0, 720.0 / 25.4, 720.0 / 25.4 * 4.512, 100.0, 100.0};
408 return iter[index];
409 }
410
unitValidForDocUnit(const int index)411 bool unitValidForDocUnit(const int index)
412 {
413 if (index < UNITMIN || index > UNITMAX)
414 return false;
415 if (index == SC_DEGREES || index == SC_PERCENT)
416 return false;
417 return true;
418 }
419