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