]> git.lyx.org Git - lyx.git/blob - src/Length.cpp
Routines to retrieve HTML style information.
[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 Length::UNIT Length::defaultUnit()
280 {
281         // FIXME user a proper pref, since we should get rid of
282         // default_papersize in lyxrc.
283         UNIT u = Length::CM;
284         switch (lyxrc.default_papersize) {
285                 case PAPER_USLETTER:
286                 case PAPER_USLEGAL:
287                 case PAPER_USEXECUTIVE:
288                         u = Length::IN;
289                         break;
290                 default:
291                         break;
292         }
293
294         return u;
295 }
296
297
298
299 bool operator==(Length const & l1, Length const & l2)
300 {
301         return l1.value() == l2.value() && l1.unit() == l2.unit();
302 }
303
304
305 bool operator!=(Length const & l1, Length const & l2)
306 {
307         return !(l1 == l2);
308 }
309
310
311 /////////////////////////////////////////////////////////////////////
312 //
313 // GlueLength
314 //
315 /////////////////////////////////////////////////////////////////////
316
317
318 GlueLength::GlueLength(Length const & len)
319         : len_(len)
320 {}
321
322
323 GlueLength::GlueLength(Length const & len, Length const & plus,
324                 Length const & minus)
325         : len_(len), plus_(plus), minus_(minus)
326 {}
327
328
329 GlueLength::GlueLength(string const & data)
330 {
331         isValidGlueLength(data, this);
332 }
333
334
335 string const GlueLength::asString() const
336 {
337         ostringstream buffer;
338
339         buffer << len_.value();
340
341         if (plus_.zero() && minus_.zero()) {
342                 buffer << unit_name[len_.unit()];
343                 return buffer.str();
344         }
345
346         // just len and plus
347         if (minus_.zero()) {
348                 if (len_.unit() != plus_.unit())
349                         buffer << unit_name[len_.unit()];
350                 buffer << '+' << plus_.value();
351                 buffer << unit_name[plus_.unit()];
352                 return buffer.str();
353         }
354
355         // just len and minus
356         if (plus_.zero()) {
357                 if (len_.unit() != minus_.unit())
358                         buffer << unit_name[len_.unit()];
359                 buffer << '-' << minus_.value();
360                 buffer << unit_name[minus_.unit()];
361                 return buffer.str();
362         }
363
364         // ok, len, plus AND minus
365
366         // len+-
367         if (minus_ == plus_) {
368                 if (len_.unit() != minus_.unit())
369                         buffer << unit_name[len_.unit()];
370                 buffer << "+-" << minus_.value();
371                 buffer << unit_name[minus_.unit()];
372                 return buffer.str();
373         }
374
375         // this is so rare a case, why bother minimising units ?
376
377         buffer << unit_name[len_.unit()];
378         buffer << '+' << plus_.value() << unit_name[plus_.unit()];
379         buffer << '-' << minus_.value() << unit_name[minus_.unit()];
380
381         return buffer.str();
382 }
383
384
385 string const GlueLength::asLatexString() const
386 {
387         ostringstream buffer;
388
389         buffer << len_.value() << unit_name[len_.unit()];
390
391         if (!plus_.zero())
392                 buffer << " plus " << plus_.value() << unit_name[plus_.unit()];
393         if (!minus_.zero())
394                 buffer << " minus " << minus_.value() << unit_name[minus_.unit()];
395         return buffer.str();
396 }
397
398
399 Length const & GlueLength::len() const
400 {
401         return len_;
402 }
403
404
405 Length const & GlueLength::plus() const
406 {
407         return plus_;
408 }
409
410
411 Length const & GlueLength::minus() const
412 {
413         return minus_;
414 }
415
416
417 bool operator==(GlueLength const & l1, GlueLength const & l2)
418 {
419         return l1.len() == l2.len()
420                  && l1.plus() == l2.plus()
421                  && l1.minus() == l2.minus();
422 }
423
424
425 bool operator!=(GlueLength const & l1, GlueLength const & l2)
426 {
427         return !(l1 == l2);
428 }
429
430
431 } // namespace lyx