]> git.lyx.org Git - lyx.git/blob - src/Length.cpp
cleanup and reorder initialisation code of GuiView and GuiToolbars. Move some things...
[lyx.git] / src / Length.cpp
1 /**
2  * \file Length.cpp
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 "Length.h"
19 #include "LyXRC.h"
20
21 #include "support/docstream.h"
22
23 #include <sstream>
24 #include <iomanip>
25
26
27 namespace lyx {
28
29 using std::ostringstream;
30 using std::string;
31
32
33 /////////////////////////////////////////////////////////////////////
34 //
35 // Length
36 //
37 /////////////////////////////////////////////////////////////////////
38
39 Length::Length()
40         : val_(0), unit_(Length::UNIT_NONE)
41 {}
42
43
44 Length::Length(double v, Length::UNIT u)
45         : val_(v), unit_(u)
46 {}
47
48
49 Length::Length(string const & data)
50         : val_(0), unit_(Length::PT)
51 {
52         Length tmp;
53
54         if (!isValidLength(data, &tmp))
55                 return; // should raise an exception
56
57         val_  = tmp.val_;
58         unit_ = tmp.unit_;
59 }
60
61
62 void Length::swap(Length & rhs)
63 {
64         std::swap(val_, rhs.val_);
65         std::swap(unit_, rhs.unit_);
66 }
67
68
69 string const Length::asString() const
70 {
71         ostringstream os;
72         os << val_ << unit_name[unit_]; // setw?
73         return os.str();
74 }
75
76
77 docstring const Length::asDocstring() const
78 {
79         odocstringstream os;
80         os << val_ << unit_name[unit_]; // setw?
81         return os.str();
82 }
83
84
85 string const Length::asLatexString() const
86 {
87         ostringstream os;
88         switch (unit_) {
89         case PTW:
90                 os << val_ / 100.0 << "\\textwidth";
91                 break;
92         case PCW:
93                 os << val_ / 100.0 << "\\columnwidth";
94                 break;
95         case PPW:
96                 os << val_ / 100.0 << "\\paperwidth";
97                 break;
98         case PLW:
99                 os << val_ / 100.0 << "\\linewidth";
100                 break;
101         case PPH:
102                 os << val_ / 100.0 << "\\paperheight";
103                 break;
104         case PTH:
105                 os << val_ / 100.0 << "\\textheight";
106                 break;
107         default:
108                 os << val_ << unit_name[unit_];
109           break;
110         }
111         return os.str();
112 }
113
114
115 double Length::value() const
116 {
117         return val_;
118 }
119
120
121 Length::UNIT Length::unit() const
122 {
123         return unit_;
124 }
125
126
127 void Length::value(double v)
128 {
129         val_ = v;
130 }
131
132
133 void Length::unit(Length::UNIT u)
134 {
135         unit_ = u;
136 }
137
138
139 bool Length::zero() const
140 {
141         return val_ == 0.0;
142 }
143
144
145 bool Length::empty() const
146 {
147         return unit_ == Length::UNIT_NONE;
148 }
149
150
151 int Length::inPixels(int text_width, int em_width_base) const
152 {
153         // Zoom factor specified by user in percent
154         double const zoom = lyxrc.zoom / 100.0; // [percent]
155
156         // DPI setting for monitor: pixels/inch
157         double const dpi = lyxrc.dpi; // screen resolution [pixels/inch]
158
159         double const em_width = (em_width_base > 0)
160                 ? em_width_base
161                 : 10*(dpi/72.27)*zoom;
162         // A different estimate for em_width is
163         // theFontMetrics(FontInfo(sane_font)).width('M')
164         // but this estimate might not be more accurate as the screen font
165         // is different then the latex font.
166
167         // Pixel values are scaled so that the ratio
168         // between lengths and font sizes on the screen
169         // is the same as on paper.
170
171         double result = 0.0;
172
173         switch (unit_) {
174         case Length::SP:
175                 // Scaled point: sp = 1/65536 pt
176                 result = zoom * dpi * val_
177                         / (72.27 * 65536); // 4736286.7
178                 break;
179         case Length::PT:
180                 // Point: 1 pt = 1/72.27 inch
181                 result = zoom * dpi * val_
182                         / 72.27; // 72.27
183                 break;
184         case Length::BP:
185                 // Big point: 1 bp = 1/72 inch
186                 result = zoom * dpi * val_
187                         / 72; // 72
188                 break;
189         case Length::DD:
190                 // Didot: 1157dd = 1238 pt?
191                 result = zoom * dpi * val_
192                         / (72.27 / (0.376 * 2.845)); // 67.559735
193                 break;
194         case Length::MM:
195                 // Millimeter: 1 mm = 1/25.4 inch
196                 result = zoom * dpi * val_
197                         / 25.4; // 25.4
198                 break;
199         case Length::PC:
200                 // Pica: 1 pc = 12 pt
201                 result = zoom * dpi * val_
202                         / (72.27 / 12); // 6.0225
203                 break;
204         case Length::CC:
205                 // Cicero: 1 cc = 12 dd
206                 result = zoom * dpi * val_
207                         / (72.27 / (12 * 0.376 * 2.845)); // 5.6299779
208                 break;
209         case Length::CM:
210                 // Centimeter: 1 cm = 1/2.54 inch
211                 result = zoom * dpi * val_
212                         / 2.54; // 2.54
213                 break;
214         case Length::IN:
215                 // Inch
216                 result = zoom * dpi * val_;
217                 break;
218         case Length::EX:
219                 // Ex: The height of an "x"
220                 // 0.4305 is the ration between 1ex and 1em in cmr10
221                 result = val_ * em_width * 0.4305;
222                 break;
223         case Length::EM:
224                 // Em: The width of an "m"
225                 result = val_ * em_width;
226                 break;
227         case Length::MU:
228                 // math unit = 1/18em
229                 result = val_ * em_width / 18;
230                 break;
231         case Length::PCW: // Always % of workarea
232         case Length::PTW:
233         case Length::PLW:
234                 result = val_ * text_width / 100;
235                 break;
236         case Length::PPW:
237                 // paperwidth/textwidth is 1.7 for A4 paper with default margins
238                 result = val_ * text_width * 1.7 / 100;
239                 break;
240         case Length::PTH:
241                 result = val_ * text_width * 1.787 / 100;
242                 break;
243         case Length::PPH:
244                 result = val_ * text_width * 2.2 / 100;
245                 break;
246         case Length::UNIT_NONE:
247                 result = 0;  // this cannot happen
248                 break;
249         }
250         return static_cast<int>(result + ((result >= 0) ? 0.5 : -0.5));
251 }
252
253
254 int Length::inBP() const
255 {
256         // return any Length value as a one with
257         // the PostScript point, called bp (big points)
258         double result = 0.0;
259         switch (unit_) {
260         case Length::CM:
261                 // 1bp = 0.2835cm
262                 result = val_ * 28.346;
263                 break;
264         case Length::MM:
265                 // 1bp = 0.02835mm
266                 result = val_ * 2.8346;
267                 break;
268         case Length::IN:
269                 // 1pt = 1/72in
270                 result = val_ * 72.0;
271                 break;
272         default:
273                 // no other than bp possible
274                 result = val_;
275                 break;
276         }
277         return static_cast<int>(result + 0.5);
278 }
279
280
281 bool operator==(Length const & l1, Length const & l2)
282 {
283         return l1.value() == l2.value() && l1.unit() == l2.unit();
284 }
285
286
287 bool operator!=(Length const & l1, Length const & l2)
288 {
289         return !(l1 == l2);
290 }
291
292
293 /////////////////////////////////////////////////////////////////////
294 //
295 // GlueLength
296 //
297 /////////////////////////////////////////////////////////////////////
298
299
300 GlueLength::GlueLength(Length const & len)
301         : len_(len)
302 {}
303
304
305 GlueLength::GlueLength(Length const & len, Length const & plus,
306                 Length const & minus)
307         : len_(len), plus_(plus), minus_(minus)
308 {}
309
310
311 GlueLength::GlueLength(string const & data)
312 {
313         isValidGlueLength(data, this);
314 }
315
316
317 string const GlueLength::asString() const
318 {
319         ostringstream buffer;
320
321         buffer << len_.value();
322
323         if (plus_.zero() && minus_.zero()) {
324                 buffer << unit_name[len_.unit()];
325                 return buffer.str();
326         }
327
328         // just len and plus
329         if (minus_.zero()) {
330                 if (len_.unit() != plus_.unit())
331                         buffer << unit_name[len_.unit()];
332                 buffer << '+' << plus_.value();
333                 buffer << unit_name[plus_.unit()];
334                 return buffer.str();
335         }
336
337         // just len and minus
338         if (plus_.zero()) {
339                 if (len_.unit() != minus_.unit())
340                         buffer << unit_name[len_.unit()];
341                 buffer << '-' << minus_.value();
342                 buffer << unit_name[minus_.unit()];
343                 return buffer.str();
344         }
345
346         // ok, len, plus AND minus
347
348         // len+-
349         if (minus_ == plus_) {
350                 if (len_.unit() != minus_.unit())
351                         buffer << unit_name[len_.unit()];
352                 buffer << "+-" << minus_.value();
353                 buffer << unit_name[minus_.unit()];
354                 return buffer.str();
355         }
356
357         // this is so rare a case, why bother minimising units ?
358
359         buffer << unit_name[len_.unit()];
360         buffer << '+' << plus_.value() << unit_name[plus_.unit()];
361         buffer << '-' << minus_.value() << unit_name[minus_.unit()];
362
363         return buffer.str();
364 }
365
366
367 string const GlueLength::asLatexString() const
368 {
369         ostringstream buffer;
370
371         buffer << len_.value() << unit_name[len_.unit()];
372
373         if (!plus_.zero())
374                 buffer << " plus " << plus_.value() << unit_name[plus_.unit()];
375         if (!minus_.zero())
376                 buffer << " minus " << minus_.value() << unit_name[minus_.unit()];
377         return buffer.str();
378 }
379
380
381 Length const & GlueLength::len() const
382 {
383         return len_;
384 }
385
386
387 Length const & GlueLength::plus() const
388 {
389         return plus_;
390 }
391
392
393 Length const & GlueLength::minus() const
394 {
395         return minus_;
396 }
397
398
399 bool operator==(GlueLength const & l1, GlueLength const & l2)
400 {
401         return l1.len() == l2.len()
402                  && l1.plus() == l2.plus()
403                  && l1.minus() == l2.minus();
404 }
405
406
407 bool operator!=(GlueLength const & l1, GlueLength const & l2)
408 {
409         return !(l1 == l2);
410 }
411
412
413 } // namespace lyx