]> git.lyx.org Git - lyx.git/blob - src/lyxlength.C
If I ever see another licence blurb again, it'll be too soon...
[lyx.git] / src / lyxlength.C
1 /**
2  * \file lyxlength.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Matthias Ettrich
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author Dekel Tsur
12  *
13  * Full author contact details are available in file CREDITS.
14  */
15
16 #include <config.h>
17
18 #include "lyxlength.h"
19 #include "lengthcommon.h"
20 #include "lyxrc.h"
21
22 #include "support/lstrings.h"
23
24 #include "Lsstream.h"
25
26 #include <cstdlib>
27
28 using std::abs;
29
30 LyXLength::LyXLength()
31         : val_(0), unit_(LyXLength::UNIT_NONE)
32 {}
33
34
35 LyXLength::LyXLength(double v, LyXLength::UNIT u)
36         : val_(v), unit_(u)
37 {}
38
39
40 LyXLength::LyXLength(string const & data)
41         : val_(0), unit_(LyXLength::PT)
42 {
43         LyXLength tmp;
44
45         if (!isValidLength(data, &tmp))
46                 return; // should raise an exception
47
48         val_  = tmp.val_;
49         unit_ = tmp.unit_;
50 }
51
52
53 string const LyXLength::asString() const
54 {
55         ostringstream buffer;
56         buffer << val_ << unit_name[unit_]; // setw?
57         return STRCONV(buffer.str());
58 }
59
60
61 string const LyXLength::asLatexString() const
62 {
63         ostringstream buffer;
64         switch (unit_) {
65         case PTW:
66             buffer << abs(static_cast<int>(val_/100)) << '.'
67                    << abs(static_cast<int>(val_)%100) << "\\textwidth";
68             break;
69         case PCW:
70             buffer << abs(static_cast<int>(val_/100)) << '.'
71                    << abs(static_cast<int>(val_)%100) << "\\columnwidth";
72             break;
73         case PPW:
74             buffer << abs(static_cast<int>(val_/100)) << '.'
75                    << abs(static_cast<int>(val_)%100) << "\\paperwidth";
76             break;
77         case PLW:
78             buffer << abs(static_cast<int>(val_/100)) << '.'
79                    << abs(static_cast<int>(val_)%100) << "\\linewidth";
80             break;
81         case PPH:
82             buffer << abs(static_cast<int>(val_/100)) << '.'
83                    << abs(static_cast<int>(val_)%100) << "\\paperheight";
84             break;
85         case PTH:
86             buffer << abs(static_cast<int>(val_/100)) << '.'
87                    << abs(static_cast<int>(val_)%100) << "\\textheight";
88             break;
89         default:
90             buffer << val_ << unit_name[unit_]; // setw?
91             break;
92         }
93         return STRCONV(buffer.str());
94 }
95
96
97 double LyXLength::value() const
98 {
99         return val_;
100 }
101
102
103 LyXLength::UNIT LyXLength::unit() const
104 {
105         return unit_;
106 }
107
108
109 void LyXLength::value(double v)
110 {
111         val_ = v;
112 }
113
114
115 void LyXLength::unit(LyXLength::UNIT u)
116 {
117         unit_ = u;
118 }
119
120
121 bool LyXLength::zero() const
122 {
123         return val_ == 0.0;
124 }
125
126
127 bool LyXLength::empty() const
128 {
129         return unit_ == LyXLength::UNIT_NONE;
130 }
131
132
133 int LyXLength::inPixels(int text_width, int em_width_base) const
134 {
135         // Zoom factor specified by user in percent
136         double const zoom = lyxrc.zoom / 100.0; // [percent]
137
138         // DPI setting for monitor: pixels/inch
139         double const dpi = lyxrc.dpi; // screen resolution [pixels/inch]
140
141         double const em_width = (em_width_base > 0)
142                 ? em_width_base
143                 : 10*(dpi/72.27)*zoom;
144         // A different estimate for em_width is
145         // font_metrics::width('M', LyXFont(LyXFont::ALL_SANE))
146         // but this estimate might not be more accurate as the screen font
147         // is different then the latex font.
148
149         // Pixel values are scaled so that the ratio
150         // between lengths and font sizes on the screen
151         // is the same as on paper.
152
153 #ifdef WITH_WARNINGS
154 #warning if you don't care than either call this function differently or let it return negative values and call abs() explicitly when needed (Andre')
155 #endif
156
157         double result = 0.0;
158
159         switch (unit_) {
160         case LyXLength::SP:
161                 // Scaled point: sp = 1/65536 pt
162                 result = zoom * dpi * val_
163                         / (72.27 * 65536); // 4736286.7
164                 break;
165         case LyXLength::PT:
166                 // Point: 1 pt = 1/72.27 inch
167                 result = zoom * dpi * val_
168                         / 72.27; // 72.27
169                 break;
170         case LyXLength::BP:
171                 // Big point: 1 bp = 1/72 inch
172                 result = zoom * dpi * val_
173                         / 72; // 72
174                 break;
175         case LyXLength::DD:
176                 // Didot: 1157dd = 1238 pt?
177                 result = zoom * dpi * val_
178                         / (72.27 / (0.376 * 2.845)); // 67.559735
179                 break;
180         case LyXLength::MM:
181                 // Millimeter: 1 mm = 1/25.4 inch
182                 result = zoom * dpi * val_
183                         / 25.4; // 25.4
184                 break;
185         case LyXLength::PC:
186                 // Pica: 1 pc = 12 pt
187                 result = zoom * dpi * val_
188                         / (72.27 / 12); // 6.0225
189                 break;
190         case LyXLength::CC:
191                 // Cicero: 1 cc = 12 dd
192                 result = zoom * dpi * val_
193                         / (72.27 / (12 * 0.376 * 2.845)); // 5.6299779
194                 break;
195         case LyXLength::CM:
196                 // Centimeter: 1 cm = 1/2.54 inch
197                 result = zoom * dpi * val_
198                         / 2.54; // 2.54
199                 break;
200         case LyXLength::IN:
201                 // Inch
202                 result = zoom * dpi * val_;
203                 break;
204         case LyXLength::EX:
205                 // Ex: The height of an "x"
206                 // 0.4305 is the ration between 1ex and 1em in cmr10
207                 result = val_ * em_width * 0.4305;
208                 break;
209         case LyXLength::EM:
210                 // Em: The width of an "m"
211                 result = val_ * em_width;
212                 break;
213         case LyXLength::MU:
214                 // math unit = 1/18em
215                 result = val_ * em_width / 18;
216                 break;
217         case LyXLength::PCW: // Always % of workarea
218         case LyXLength::PTW:
219         case LyXLength::PLW:
220                 result = val_ * text_width / 100;
221                 break;
222         case LyXLength::PPW:
223                 // paperwidth/textwidth is 1.7 for A4 paper with default margins
224                 result = val_ * text_width * 1.7 / 100;
225                 break;
226         case LyXLength::PTH:
227                 result = val_ * text_width * 1.787 / 100;
228                 break;
229         case LyXLength::PPH:
230                 result = val_ * text_width * 2.2 / 100;
231                 break;
232         case LyXLength::UNIT_NONE:
233                 result = 0;  // this cannot happen
234                 break;
235         }
236         return static_cast<int>(result + ((result >= 0) ? 0.5 : -0.5));
237 }
238
239
240 int LyXLength::inBP() const
241 {
242         // return any LyXLength value as a one with
243         // the PostScript point, called bp (big points)
244         double result = 0.0;
245         switch (unit_) {
246         case LyXLength::CM:
247                 // 1bp = 0.2835cm
248                 result = val_ * 28.346;
249                 break;
250         case LyXLength::MM:
251                 // 1bp = 0.02835mm
252                 result = val_ * 2.8346;
253                 break;
254         case LyXLength::IN:
255                 // 1pt = 1/72in
256                 result = val_ * 72.0;
257                 break;
258         default:
259                 // no other than bp possible
260                 result = val_;
261                 break;
262         }
263         return static_cast<int>(result + 0.5);
264 }
265
266
267 bool operator==(LyXLength const & l1, LyXLength const & l2)
268 {
269         return l1.value() == l2.value() && l1.unit() == l2.unit();
270 }
271
272
273 bool operator!=(LyXLength const & l1, LyXLength const & l2)
274 {
275         return !(l1 == l2);
276 }