* Licence details can be found in the file COPYING.
*
* \author Matthias Ettrich
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
* \author Jean-Marc Lasgouttes
* \author Angus Leeming
* \author John Levon
#include <config.h>
#include "Length.h"
-#include "lengthcommon.h"
#include "LyXRC.h"
+#include "MetricsInfo.h"
+#include "frontends/FontMetrics.h"
+
+#include "support/debug.h"
#include "support/docstream.h"
+#include "support/lstrings.h"
+#include "support/lyxlib.h"
+
#include <sstream>
#include <iomanip>
+using namespace std;
+using namespace lyx::support;
namespace lyx {
-using std::ostringstream;
-using std::string;
-
/////////////////////////////////////////////////////////////////////
//
string const Length::asString() const
{
ostringstream os;
- os << val_ << unit_name[unit_]; // setw?
+ if (unit_ != UNIT_NONE)
+ os << formatFPNumber(val_) << unit_name[unit_]; // setw?
return os.str();
}
docstring const Length::asDocstring() const
{
odocstringstream os;
- os << val_ << unit_name[unit_]; // setw?
+ if (unit_ != UNIT_NONE)
+ os << from_ascii(formatFPNumber(val_))
+ << from_ascii(unit_name[unit_]); // setw?
return os.str();
}
string const Length::asLatexString() const
{
ostringstream os;
+ // Do not allow scientific notation (e.g. 1.2e+03), since this is not valid
+ // LaTeX (bug 9416)
switch (unit_) {
case PTW:
- os << val_ / 100.0 << "\\textwidth";
+ os << formatFPNumber(val_ / 100.0) << "\\textwidth";
break;
case PCW:
- os << val_ / 100.0 << "\\columnwidth";
+ os << formatFPNumber(val_ / 100.0) << "\\columnwidth";
break;
case PPW:
- os << val_ / 100.0 << "\\paperwidth";
+ os << formatFPNumber(val_ / 100.0) << "\\paperwidth";
break;
case PLW:
- os << val_ / 100.0 << "\\linewidth";
+ os << formatFPNumber(val_ / 100.0) << "\\linewidth";
+ break;
+ case PTH:
+ os << formatFPNumber(val_ / 100.0) << "\\textheight";
break;
case PPH:
- os << val_ / 100.0 << "\\paperheight";
+ os << formatFPNumber(val_ / 100.0) << "\\paperheight";
break;
- case PTH:
- os << val_ / 100.0 << "\\textheight";
+ case BLS:
+ os << formatFPNumber(val_ / 100.0) << "\\baselineskip";
+ break;
+ case UNIT_NONE:
break;
default:
- os << val_ << unit_name[unit_];
+ os << formatFPNumber(val_) << unit_name[unit_];
break;
}
return os.str();
}
+string const Length::asHTMLString() const
+{
+ ostringstream os;
+ switch (unit_) {
+ case PT:
+ case BP:
+ case DD:
+ // close enough
+ os << formatFPNumber(val_) << "pt";
+ break;
+ case MM:
+ case CM:
+ case PC:
+ case IN:
+ case EX:
+ case EM:
+ os << formatFPNumber(val_) << unit_name[unit_];
+ break;
+ case CC:
+ os << formatFPNumber(val_ / 12.0) << "pt";
+ break;
+ case MU:
+ os << formatFPNumber(val_ / 18.0) << "em";
+ break;
+ case PTW:
+ case PPW:
+ case PLW:
+ case PCW:
+ case PTH:
+ case PPH:
+ case BLS:
+ // what it's a percentage of probably won't make sense for HTML,
+ // so we'll assume people have chosen these appropriately
+ os << formatFPNumber(val_) << '%';
+ break;
+ case SP:
+ case UNIT_NONE:
+ break;
+ }
+ return os.str();
+}
+
+
double Length::value() const
{
return val_;
// DPI setting for monitor: pixels/inch
double const dpi = lyxrc.dpi; // screen resolution [pixels/inch]
- double const em_width = (em_width_base > 0)
- ? em_width_base
- : 10*(dpi/72.27)*zoom;
+ double const em_width_in = (em_width_base > 0)
+ ? em_width_base / (zoom * dpi)
+ : 10.0/72.27;
// A different estimate for em_width is
- // theFontMetrics(Font(Font::ALL_SANE)).width('M')
+ // theFontMetrics(FontInfo(sane_font)).em()
// but this estimate might not be more accurate as the screen font
// is different then the latex font.
// between lengths and font sizes on the screen
// is the same as on paper.
+ double const text_width_in = text_width / (zoom * dpi);
+ double const result = zoom * dpi * inInch(text_width_in, em_width_in);
+ return support::iround(result);
+}
+
+
+double Length::inInch(double text_width, double em_width) const
+{
double result = 0.0;
switch (unit_) {
case Length::SP:
// Scaled point: sp = 1/65536 pt
- result = zoom * dpi * val_
- / (72.27 * 65536); // 4736286.7
+ result = val_ / (72.27 * 65536); // 4736286.7
break;
case Length::PT:
// Point: 1 pt = 1/72.27 inch
- result = zoom * dpi * val_
- / 72.27; // 72.27
+ result = val_ / 72.27; // 72.27
break;
case Length::BP:
// Big point: 1 bp = 1/72 inch
- result = zoom * dpi * val_
- / 72; // 72
+ result = val_ / 72; // 72
break;
case Length::DD:
// Didot: 1157dd = 1238 pt?
- result = zoom * dpi * val_
- / (72.27 / (0.376 * 2.845)); // 67.559735
+ result = val_ / (72.27 / (0.376 * 2.845)); // 67.559735
break;
case Length::MM:
// Millimeter: 1 mm = 1/25.4 inch
- result = zoom * dpi * val_
- / 25.4; // 25.4
+ result = val_ / 25.4; // 25.4
break;
case Length::PC:
// Pica: 1 pc = 12 pt
- result = zoom * dpi * val_
- / (72.27 / 12); // 6.0225
+ result = val_ / (72.27 / 12); // 6.0225
break;
case Length::CC:
// Cicero: 1 cc = 12 dd
- result = zoom * dpi * val_
+ result = val_
/ (72.27 / (12 * 0.376 * 2.845)); // 5.6299779
break;
case Length::CM:
// Centimeter: 1 cm = 1/2.54 inch
- result = zoom * dpi * val_
- / 2.54; // 2.54
+ result = val_ / 2.54; // 2.54
break;
case Length::IN:
// Inch
- result = zoom * dpi * val_;
+ result = val_;
break;
case Length::EX:
// Ex: The height of an "x"
case Length::PPH:
result = val_ * text_width * 2.2 / 100;
break;
+ case Length::BLS:
+ // baselineskip is approximately 1.2 times the font size for the cmr fonts
+ // The value actually depends on the current paragraph (see TextMetrics::setRowHeight),
+ // but we do not have this information here.
+ result = val_ * em_width * 1.2 / 100;
+ break;
case Length::UNIT_NONE:
result = 0; // this cannot happen
break;
}
- return static_cast<int>(result + ((result >= 0) ? 0.5 : -0.5));
+ return result;
+}
+
+
+int Length::inPixels(MetricsBase const & base) const
+{
+ FontInfo fi = base.font;
+ if (unit_ == Length::MU)
+ // mu is 1/18th of an em in the math symbol font
+ fi.setFamily(SYMBOL_FAMILY);
+ else
+ // Math style is only taken into account in the case of mu
+ fi.setStyle(LM_ST_TEXT);
+ return inPixels(base.textwidth, theFontMetrics(fi).em());
}
{
// return any Length value as a one with
// the PostScript point, called bp (big points)
- double result = 0.0;
- switch (unit_) {
- case Length::CM:
- // 1bp = 0.2835cm
- result = val_ * 28.346;
- break;
- case Length::MM:
- // 1bp = 0.02835mm
- result = val_ * 2.8346;
- break;
- case Length::IN:
- // 1pt = 1/72in
- result = val_ * 72.0;
- break;
- default:
- // no other than bp possible
- result = val_;
- break;
- }
- return static_cast<int>(result + 0.5);
+
+ double const text_width_in = 210.0 / 2.54; // assume A4
+ double const em_width_in = 10.0 / 72.27;
+ double result = 72.0 * inInch(text_width_in, em_width_in);
+ return support::iround(result);
+}
+
+
+Length::UNIT Length::defaultUnit()
+{
+ return lyxrc.default_length_unit;
}
+
bool operator==(Length const & l1, Length const & l2)
{
return l1.value() == l2.value() && l1.unit() == l2.unit();
GlueLength::GlueLength(string const & data)
{
- isValidGlueLength(data, this);
+ if (!isValidGlueLength(data, this))
+ LYXERR0("Invalid glue length " + data);
}
string const GlueLength::asString() const
{
+ if (len_.empty())
+ return string();
+
ostringstream buffer;
- buffer << len_.value();
+ buffer << formatFPNumber(len_.value());
if (plus_.zero() && minus_.zero()) {
buffer << unit_name[len_.unit()];
if (minus_.zero()) {
if (len_.unit() != plus_.unit())
buffer << unit_name[len_.unit()];
- buffer << '+' << plus_.value();
+ buffer << '+' << formatFPNumber(plus_.value());
buffer << unit_name[plus_.unit()];
return buffer.str();
}
if (plus_.zero()) {
if (len_.unit() != minus_.unit())
buffer << unit_name[len_.unit()];
- buffer << '-' << minus_.value();
+ buffer << '-' << formatFPNumber(minus_.value());
buffer << unit_name[minus_.unit()];
return buffer.str();
}
if (minus_ == plus_) {
if (len_.unit() != minus_.unit())
buffer << unit_name[len_.unit()];
- buffer << "+-" << minus_.value();
+ buffer << "+-" << formatFPNumber(minus_.value());
buffer << unit_name[minus_.unit()];
return buffer.str();
}
// this is so rare a case, why bother minimising units ?
buffer << unit_name[len_.unit()];
- buffer << '+' << plus_.value() << unit_name[plus_.unit()];
- buffer << '-' << minus_.value() << unit_name[minus_.unit()];
+ buffer << '+' << formatFPNumber(plus_.value()) << unit_name[plus_.unit()];
+ buffer << '-' << formatFPNumber(minus_.value()) << unit_name[minus_.unit()];
return buffer.str();
}
string const GlueLength::asLatexString() const
{
ostringstream buffer;
-
- buffer << len_.value() << unit_name[len_.unit()];
-
+ // use Length::asLatexString() to handle also the percent lengths
+ buffer << len_.Length::asLatexString();
if (!plus_.zero())
- buffer << " plus " << plus_.value() << unit_name[plus_.unit()];
+ buffer << " plus " << plus_.Length::asLatexString();
if (!minus_.zero())
- buffer << " minus " << minus_.value() << unit_name[minus_.unit()];
+ buffer << " minus " << minus_.Length::asLatexString();
return buffer.str();
}