]> git.lyx.org Git - lyx.git/blob - src/lyxlength.C
Continue to improve GtkLengthEntry
[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 <sstream>
23 #include <iomanip>
24
25
26 using std::ostringstream;
27 using std::string;
28
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 os;
56         os << val_ << unit_name[unit_]; // setw?
57         return os.str();
58 }
59
60
61 string const LyXLength::asLatexString() const
62 {
63         ostringstream os;
64         switch (unit_) {
65         case PTW:
66                 os << val_ / 100.0 << "\\textwidth";
67                 break;
68         case PCW:
69                 os << val_ / 100.0 << "\\columnwidth";
70                 break;
71         case PPW:
72                 os << val_ / 100.0 << "\\paperwidth";
73                 break;
74         case PLW:
75                 os << val_ / 100.0 << "\\linewidth";
76                 break;
77         case PPH:
78                 os << val_ / 100.0 << "\\paperheight";
79                 break;
80         case PTH:
81                 os << val_ / 100.0 << "\\textheight";
82                 break;
83         default:
84                 os << val_ << unit_name[unit_];
85           break;
86         }
87         return os.str();
88 }
89
90
91 double LyXLength::value() const
92 {
93         return val_;
94 }
95
96
97 LyXLength::UNIT LyXLength::unit() const
98 {
99         return unit_;
100 }
101
102
103 void LyXLength::value(double v)
104 {
105         val_ = v;
106 }
107
108
109 void LyXLength::unit(LyXLength::UNIT u)
110 {
111         unit_ = u;
112 }
113
114
115 bool LyXLength::zero() const
116 {
117         return val_ == 0.0;
118 }
119
120
121 bool LyXLength::empty() const
122 {
123         return unit_ == LyXLength::UNIT_NONE;
124 }
125
126
127 int LyXLength::inPixels(int text_width, int em_width_base) const
128 {
129         // Zoom factor specified by user in percent
130         double const zoom = lyxrc.zoom / 100.0; // [percent]
131
132         // DPI setting for monitor: pixels/inch
133         double const dpi = lyxrc.dpi; // screen resolution [pixels/inch]
134
135         double const em_width = (em_width_base > 0)
136                 ? em_width_base
137                 : 10*(dpi/72.27)*zoom;
138         // A different estimate for em_width is
139         // font_metrics::width('M', LyXFont(LyXFont::ALL_SANE))
140         // but this estimate might not be more accurate as the screen font
141         // is different then the latex font.
142
143         // Pixel values are scaled so that the ratio
144         // between lengths and font sizes on the screen
145         // is the same as on paper.
146
147         double result = 0.0;
148
149         switch (unit_) {
150         case LyXLength::SP:
151                 // Scaled point: sp = 1/65536 pt
152                 result = zoom * dpi * val_
153                         / (72.27 * 65536); // 4736286.7
154                 break;
155         case LyXLength::PT:
156                 // Point: 1 pt = 1/72.27 inch
157                 result = zoom * dpi * val_
158                         / 72.27; // 72.27
159                 break;
160         case LyXLength::BP:
161                 // Big point: 1 bp = 1/72 inch
162                 result = zoom * dpi * val_
163                         / 72; // 72
164                 break;
165         case LyXLength::DD:
166                 // Didot: 1157dd = 1238 pt?
167                 result = zoom * dpi * val_
168                         / (72.27 / (0.376 * 2.845)); // 67.559735
169                 break;
170         case LyXLength::MM:
171                 // Millimeter: 1 mm = 1/25.4 inch
172                 result = zoom * dpi * val_
173                         / 25.4; // 25.4
174                 break;
175         case LyXLength::PC:
176                 // Pica: 1 pc = 12 pt
177                 result = zoom * dpi * val_
178                         / (72.27 / 12); // 6.0225
179                 break;
180         case LyXLength::CC:
181                 // Cicero: 1 cc = 12 dd
182                 result = zoom * dpi * val_
183                         / (72.27 / (12 * 0.376 * 2.845)); // 5.6299779
184                 break;
185         case LyXLength::CM:
186                 // Centimeter: 1 cm = 1/2.54 inch
187                 result = zoom * dpi * val_
188                         / 2.54; // 2.54
189                 break;
190         case LyXLength::IN:
191                 // Inch
192                 result = zoom * dpi * val_;
193                 break;
194         case LyXLength::EX:
195                 // Ex: The height of an "x"
196                 // 0.4305 is the ration between 1ex and 1em in cmr10
197                 result = val_ * em_width * 0.4305;
198                 break;
199         case LyXLength::EM:
200                 // Em: The width of an "m"
201                 result = val_ * em_width;
202                 break;
203         case LyXLength::MU:
204                 // math unit = 1/18em
205                 result = val_ * em_width / 18;
206                 break;
207         case LyXLength::PCW: // Always % of workarea
208         case LyXLength::PTW:
209         case LyXLength::PLW:
210                 result = val_ * text_width / 100;
211                 break;
212         case LyXLength::PPW:
213                 // paperwidth/textwidth is 1.7 for A4 paper with default margins
214                 result = val_ * text_width * 1.7 / 100;
215                 break;
216         case LyXLength::PTH:
217                 result = val_ * text_width * 1.787 / 100;
218                 break;
219         case LyXLength::PPH:
220                 result = val_ * text_width * 2.2 / 100;
221                 break;
222         case LyXLength::UNIT_NONE:
223                 result = 0;  // this cannot happen
224                 break;
225         }
226         return static_cast<int>(result + ((result >= 0) ? 0.5 : -0.5));
227 }
228
229
230 int LyXLength::inBP() const
231 {
232         // return any LyXLength value as a one with
233         // the PostScript point, called bp (big points)
234         double result = 0.0;
235         switch (unit_) {
236         case LyXLength::CM:
237                 // 1bp = 0.2835cm
238                 result = val_ * 28.346;
239                 break;
240         case LyXLength::MM:
241                 // 1bp = 0.02835mm
242                 result = val_ * 2.8346;
243                 break;
244         case LyXLength::IN:
245                 // 1pt = 1/72in
246                 result = val_ * 72.0;
247                 break;
248         default:
249                 // no other than bp possible
250                 result = val_;
251                 break;
252         }
253         return static_cast<int>(result + 0.5);
254 }
255
256
257 bool operator==(LyXLength const & l1, LyXLength const & l2)
258 {
259         return l1.value() == l2.value() && l1.unit() == l2.unit();
260 }
261
262
263 bool operator!=(LyXLength const & l1, LyXLength const & l2)
264 {
265         return !(l1 == l2);
266 }