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