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
13 * Full author contact details are available in file CREDITS.
21 #include "support/debug.h"
22 #include "support/docstream.h"
23 #include "support/lstrings.h"
24 #include "support/lyxlib.h"
30 using namespace lyx::support;
35 /////////////////////////////////////////////////////////////////////
39 /////////////////////////////////////////////////////////////////////
42 : val_(0), unit_(Length::UNIT_NONE)
46 Length::Length(double v, Length::UNIT u)
51 Length::Length(string const & data)
52 : val_(0), unit_(Length::UNIT_NONE)
56 if (!isValidLength(data, &tmp))
57 return; // should raise an exception
64 string const Length::asString() const
67 if (unit_ != UNIT_NONE)
68 os << formatFPNumber(val_) << unit_name[unit_]; // setw?
73 docstring const Length::asDocstring() const
76 if (unit_ != UNIT_NONE)
77 os << from_ascii(formatFPNumber(val_))
78 << from_ascii(unit_name[unit_]); // setw?
83 string const Length::asLatexString() const
86 // Do not allow scientific notation (e.g. 1.2e+03), since this is not valid
90 os << formatFPNumber(val_ / 100.0) << "\\textwidth";
93 os << formatFPNumber(val_ / 100.0) << "\\columnwidth";
96 os << formatFPNumber(val_ / 100.0) << "\\paperwidth";
99 os << formatFPNumber(val_ / 100.0) << "\\linewidth";
102 os << formatFPNumber(val_ / 100.0) << "\\textheight";
105 os << formatFPNumber(val_ / 100.0) << "\\paperheight";
108 os << formatFPNumber(val_ / 100.0) << "\\baselineskip";
113 os << formatFPNumber(val_) << unit_name[unit_];
120 string const Length::asHTMLString() const
128 os << formatFPNumber(val_) << "pt";
136 os << formatFPNumber(val_) << unit_name[unit_];
139 os << formatFPNumber(val_ / 12.0) << "pt";
142 os << formatFPNumber(val_ / 18.0) << "em";
151 // what it's a percentage of probably won't make sense for HTML,
152 // so we'll assume people have chosen these appropriately
153 os << formatFPNumber(val_) << '%';
163 double Length::value() const
169 Length::UNIT Length::unit() const
175 void Length::value(double v)
181 void Length::unit(Length::UNIT u)
187 bool Length::zero() const
193 bool Length::empty() const
195 return unit_ == Length::UNIT_NONE;
199 int Length::inPixels(int text_width, int em_width_base) const
201 // Zoom factor specified by user in percent
202 double const zoom = lyxrc.currentZoom / 100.0; // [percent]
204 // DPI setting for monitor: pixels/inch
205 double const dpi = lyxrc.dpi; // screen resolution [pixels/inch]
207 double const em_width_in = (em_width_base > 0)
208 ? em_width_base / (zoom * dpi)
210 // A different estimate for em_width is
211 // theFontMetrics(FontInfo(sane_font)).em()
212 // but this estimate might not be more accurate as the screen font
213 // is different then the latex font.
215 // Pixel values are scaled so that the ratio
216 // between lengths and font sizes on the screen
217 // is the same as on paper.
219 double const text_width_in = text_width / (zoom * dpi);
220 double const result = zoom * dpi * inInch(text_width_in, em_width_in);
221 return support::iround(result);
225 double Length::inInch(double text_width, double em_width) const
231 // Scaled point: sp = 1/65536 pt
232 result = val_ / (72.27 * 65536); // 4736286.7
235 // Point: 1 pt = 1/72.27 inch
236 result = val_ / 72.27; // 72.27
239 // Big point: 1 bp = 1/72 inch
240 result = val_ / 72; // 72
243 // Didot: 1157dd = 1238 pt?
244 result = val_ / (72.27 / (0.376 * 2.845)); // 67.559735
247 // Millimeter: 1 mm = 1/25.4 inch
248 result = val_ / 25.4; // 25.4
251 // Pica: 1 pc = 12 pt
252 result = val_ / (72.27 / 12); // 6.0225
255 // Cicero: 1 cc = 12 dd
257 / (72.27 / (12 * 0.376 * 2.845)); // 5.6299779
260 // Centimeter: 1 cm = 1/2.54 inch
261 result = val_ / 2.54; // 2.54
268 // Ex: The height of an "x"
269 // 0.4305 is the ration between 1ex and 1em in cmr10
270 result = val_ * em_width * 0.4305;
273 // Em: The width of an "m"
274 result = val_ * em_width;
277 // math unit = 1/18em
278 result = val_ * em_width / 18;
280 case Length::PCW: // Always % of workarea
283 result = val_ * text_width / 100;
286 // paperwidth/textwidth is 1.7 for A4 paper with default margins
287 result = val_ * text_width * 1.7 / 100;
290 result = val_ * text_width * 1.787 / 100;
293 result = val_ * text_width * 2.2 / 100;
296 // baselineskip is approximately 1.2 times the font size for the cmr fonts
297 // The value actually depends on the current paragraph (see TextMetrics::setRowHeight),
298 // but we do not have this information here.
299 result = val_ * em_width * 1.2 / 100;
301 case Length::UNIT_NONE:
302 result = 0; // this cannot happen
309 int Length::inBP() const
311 // return any Length value as a one with
312 // the PostScript point, called bp (big points)
314 double const text_width_in = 210.0 / 2.54; // assume A4
315 double const em_width_in = 10.0 / 72.27;
316 double result = 72.0 * inInch(text_width_in, em_width_in);
317 return support::iround(result);
321 Length::UNIT Length::defaultUnit()
323 return lyxrc.default_length_unit;
328 bool operator==(Length const & l1, Length const & l2)
330 return l1.value() == l2.value() && l1.unit() == l2.unit();
334 bool operator!=(Length const & l1, Length const & l2)
340 /////////////////////////////////////////////////////////////////////
344 /////////////////////////////////////////////////////////////////////
347 GlueLength::GlueLength(Length const & len)
352 GlueLength::GlueLength(Length const & len, Length const & plus,
353 Length const & minus)
354 : len_(len), plus_(plus), minus_(minus)
358 GlueLength::GlueLength(string const & data)
360 if (!isValidGlueLength(data, this))
361 LYXERR0("Invalid glue length " + data);
365 string const GlueLength::asString() const
370 ostringstream buffer;
372 buffer << formatFPNumber(len_.value());
374 if (plus_.zero() && minus_.zero()) {
375 buffer << unit_name[len_.unit()];
381 if (len_.unit() != plus_.unit())
382 buffer << unit_name[len_.unit()];
383 buffer << '+' << formatFPNumber(plus_.value());
384 buffer << unit_name[plus_.unit()];
388 // just len and minus
390 if (len_.unit() != minus_.unit())
391 buffer << unit_name[len_.unit()];
392 buffer << '-' << formatFPNumber(minus_.value());
393 buffer << unit_name[minus_.unit()];
397 // ok, len, plus AND minus
400 if (minus_ == plus_) {
401 if (len_.unit() != minus_.unit())
402 buffer << unit_name[len_.unit()];
403 buffer << "+-" << formatFPNumber(minus_.value());
404 buffer << unit_name[minus_.unit()];
408 // this is so rare a case, why bother minimising units ?
410 buffer << unit_name[len_.unit()];
411 buffer << '+' << formatFPNumber(plus_.value()) << unit_name[plus_.unit()];
412 buffer << '-' << formatFPNumber(minus_.value()) << unit_name[minus_.unit()];
418 string const GlueLength::asLatexString() const
420 ostringstream buffer;
421 // use Length::asLatexString() to handle also the percent lengths
422 buffer << len_.Length::asLatexString();
424 buffer << " plus " << plus_.Length::asLatexString();
426 buffer << " minus " << minus_.Length::asLatexString();
431 Length const & GlueLength::len() const
437 Length const & GlueLength::plus() const
443 Length const & GlueLength::minus() const
449 bool operator==(GlueLength const & l1, GlueLength const & l2)
451 return l1.len() == l2.len()
452 && l1.plus() == l2.plus()
453 && l1.minus() == l2.minus();
457 bool operator!=(GlueLength const & l1, GlueLength const & l2)