Prepare ANNOUNCE and NEWS for rc2
[lyx.git] / src / Length.cpp
blob90da83a74ca7080a9fbc2b75762ce761f13501f0
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.
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
13 * Full author contact details are available in file CREDITS.
16 #include <config.h>
18 #include "Length.h"
19 #include "LyXRC.h"
21 #include "support/docstream.h"
23 #include <sstream>
24 #include <iomanip>
26 using namespace std;
28 namespace lyx {
31 /////////////////////////////////////////////////////////////////////
33 // Length
35 /////////////////////////////////////////////////////////////////////
37 Length::Length()
38 : val_(0), unit_(Length::UNIT_NONE)
42 Length::Length(double v, Length::UNIT u)
43 : val_(v), unit_(u)
47 Length::Length(string const & data)
48 : val_(0), unit_(Length::PT)
50 Length tmp;
52 if (!isValidLength(data, &tmp))
53 return; // should raise an exception
55 val_ = tmp.val_;
56 unit_ = tmp.unit_;
60 void Length::swap(Length & rhs)
62 std::swap(val_, rhs.val_);
63 std::swap(unit_, rhs.unit_);
67 string const Length::asString() const
69 ostringstream os;
70 os << val_ << unit_name[unit_]; // setw?
71 return os.str();
75 docstring const Length::asDocstring() const
77 odocstringstream os;
78 os << val_ << unit_name[unit_]; // setw?
79 return os.str();
83 string const Length::asLatexString() const
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;
109 return os.str();
113 double Length::value() const
115 return val_;
119 Length::UNIT Length::unit() const
121 return unit_;
125 void Length::value(double v)
127 val_ = v;
131 void Length::unit(Length::UNIT u)
133 unit_ = u;
137 bool Length::zero() const
139 return val_ == 0.0;
143 bool Length::empty() const
145 return unit_ == Length::UNIT_NONE;
149 int Length::inPixels(int text_width, int em_width_base) const
151 // Zoom factor specified by user in percent
152 double const zoom = lyxrc.zoom / 100.0; // [percent]
154 // DPI setting for monitor: pixels/inch
155 double const dpi = lyxrc.dpi; // screen resolution [pixels/inch]
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.
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.
169 double result = 0.0;
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;
248 return static_cast<int>(result + ((result >= 0) ? 0.5 : -0.5));
252 int Length::inBP() const
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;
275 return static_cast<int>(result + 0.5);
279 bool operator==(Length const & l1, Length const & l2)
281 return l1.value() == l2.value() && l1.unit() == l2.unit();
285 bool operator!=(Length const & l1, Length const & l2)
287 return !(l1 == l2);
291 /////////////////////////////////////////////////////////////////////
293 // GlueLength
295 /////////////////////////////////////////////////////////////////////
298 GlueLength::GlueLength(Length const & len)
299 : len_(len)
303 GlueLength::GlueLength(Length const & len, Length const & plus,
304 Length const & minus)
305 : len_(len), plus_(plus), minus_(minus)
309 GlueLength::GlueLength(string const & data)
311 isValidGlueLength(data, this);
315 string const GlueLength::asString() const
317 ostringstream buffer;
319 buffer << len_.value();
321 if (plus_.zero() && minus_.zero()) {
322 buffer << unit_name[len_.unit()];
323 return buffer.str();
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();
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();
344 // ok, len, plus AND minus
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();
355 // this is so rare a case, why bother minimising units ?
357 buffer << unit_name[len_.unit()];
358 buffer << '+' << plus_.value() << unit_name[plus_.unit()];
359 buffer << '-' << minus_.value() << unit_name[minus_.unit()];
361 return buffer.str();
365 string const GlueLength::asLatexString() const
367 ostringstream buffer;
369 buffer << len_.value() << unit_name[len_.unit()];
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();
379 Length const & GlueLength::len() const
381 return len_;
385 Length const & GlueLength::plus() const
387 return plus_;
391 Length const & GlueLength::minus() const
393 return minus_;
397 bool operator==(GlueLength const & l1, GlueLength const & l2)
399 return l1.len() == l2.len()
400 && l1.plus() == l2.plus()
401 && l1.minus() == l2.minus();
405 bool operator!=(GlueLength const & l1, GlueLength const & l2)
407 return !(l1 == l2);
411 } // namespace lyx