#include "InsetMathFont.h"
#include "InsetMathSymbol.h"
#include "MathData.h"
+#include "MathFactory.h"
#include "MathParser.h"
#include "MathStream.h"
+#include "LaTeXFeatures.h"
#include "MetricsInfo.h"
#include "frontends/FontLoader.h"
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
+#include "support/Changer.h"
#include "support/debug.h"
#include "support/docstream.h"
-#include "support/lyxlib.h"
+#include "support/lassert.h"
+#include "support/Length.h"
#include <map>
#include <algorithm>
/*
* Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
* 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
+ * 5 = rounded thick line (i.e. dot for short line)
*/
};
+double const dot[] = {
+// 1, 0.5, 0.2, 0.5, 0.2,
+// 1, 0.4, 0.4, 0.6, 0.4,
+// 1, 0.5, 0.5, 0.5, 0.5,
+ 5, 0.4, 0.6, 0.6, 0.6,
+ 0
+};
+
+
double const ddot[] = {
- 1, 0.2, 0.5, 0.3, 0.5,
- 1, 0.7, 0.5, 0.8, 0.5,
+ 5, 0.1, 0.6, 0.3, 0.6,
+ 5, 0.6, 0.6, 0.8, 0.6,
0
};
double const dddot[] = {
- 1, 0.1, 0.5, 0.2, 0.5,
- 1, 0.45, 0.5, 0.55, 0.5,
- 1, 0.8, 0.5, 0.9, 0.5,
+ 5, -0.2, 0.6, 0.0, 0.6,
+ 5, 0.3, 0.6, 0.5, 0.6,
+ 5, 0.8, 0.6, 1.0, 0.6,
0
};
double const ddddot[] = {
- 1, 0.1, 0.5, 0.2, 0.5,
- 1, 0.45, 0.5, 0.55, 0.5,
- 1, 0.8, 0.5, 0.9, 0.5,
- 1, 1.15, 0.5, 1.25, 0.5,
+ 5, -0.4, 0.6, -0.2, 0.6,
+ 5, 0.1, 0.6, 0.3, 0.6,
+ 5, 0.6, 0.6, 0.8, 0.6,
+ 5, 1.1, 0.6, 1.3, 0.6,
0
};
};
-double const hlinesmall[] = {
- 1, 0.4, 0.5, 0.6, 0.5,
- 0
-};
-
-
double const ring[] = {
- 2, 5,
- 0.5, 0.8, 0.8, 0.5, 0.5, 0.2, 0.2, 0.5, 0.5, 0.8,
+ 2, 9,
+ 0.5, 0.8, 0.7, 0.7, 0.8, 0.4,
+ 0.7, 0.1, 0.5, 0.0, 0.3, 0.1,
+ 0.2, 0.4, 0.3, 0.7, 0.5, 0.8,
0
};
double const tilde[] = {
- 2, 4,
- 0.00, 0.8, 0.25, 0.2, 0.75, 0.8, 1.00, 0.2,
+ 2, 6,
+ 0.0, 0.8, 0.15, 0.2, 0.35, 0.2, 0.65, 0.8, 0.85, 0.8, 1.0, 0.2,
0
};
{"acute", slash, 0 },
{"tilde", tilde, 0 },
{"bar", hline, 0 },
- {"dot", hlinesmall, 0 },
+ {"dot", dot, 0 },
{"check", angle, 1 },
{"breve", parenth, 1 },
{"vec", arrow, 3 },
}
};
-static init_deco_table dummy;
+static init_deco_table dummy_deco_table;
deco_struct const * search_deco(docstring const & name)
}
-} // namespace anon
+} // namespace
int mathed_font_em(FontInfo const & font)
return theFontMetrics(font).em();
}
+
+int mathed_font_x_height(FontInfo const & font)
+{
+ return theFontMetrics(font).xHeight();
+}
+
/* The math units. Quoting TeX by Topic, p.205:
*
* Spacing around mathematical objects is measured in mu units. A mu
* punctuation, and is put around inner objects, except where these
* are followed by a close or preceded by an open symbol, and except
* if the other object is a large operator or a binary relation.
+ *
+ * See the file MathClass.cpp for a formal implementation of the rules
+ * above.
*/
-int mathed_thinmuskip(FontInfo font)
-{
- font.setFamily(SYMBOL_FAMILY);
- return support::iround(3.0 / 18 * theFontMetrics(font).em());
-}
-
-
-int mathed_medmuskip(FontInfo font)
+int mathed_mu(FontInfo const & font, double mu)
{
- font.setFamily(SYMBOL_FAMILY);
- return support::iround(4.0 / 18 * theFontMetrics(font).em());
+ MetricsBase mb(nullptr, font);
+ return mb.inPixels(Length(mu, Length::MU));
}
-
-int mathed_thickmuskip(FontInfo font)
-{
- font.setFamily(SYMBOL_FAMILY);
- return support::iround(5.0 / 18 * theFontMetrics(font).em());
-}
+int mathed_thinmuskip(FontInfo const & font) { return mathed_mu(font, 3.0); }
+int mathed_medmuskip(FontInfo const & font) { return mathed_mu(font, 4.0); }
+int mathed_thickmuskip(FontInfo const & font) { return mathed_mu(font, 5.0); }
int mathed_char_width(FontInfo const & font, char_type c)
int mathed_char_kerning(FontInfo const & font, char_type c)
{
frontend::FontMetrics const & fm = theFontMetrics(font);
- return fm.rbearing(c) - fm.width(c);
+ return max(0, fm.rbearing(c) - fm.width(c));
}
frontend::FontMetrics const & fm = theFontMetrics(font);
dim.asc = 0;
dim.des = 0;
- for (docstring::const_iterator it = s.begin();
- it != s.end();
- ++it) {
- dim.asc = max(dim.asc, fm.ascent(*it));
- dim.des = max(dim.des, fm.descent(*it));
+ for (char_type const c : s) {
+ dim.asc = max(dim.asc, fm.ascent(c));
+ dim.des = max(dim.des, fm.descent(c));
}
dim.wid = fm.width(s);
}
void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
docstring const & name)
{
+ int const lw = pi.base.solidLineThickness();
+
if (name == ".") {
pi.pain.line(x + w/2, y, x + w/2, y + h,
- Color_cursor, Painter::line_onoffdash);
+ Color_cursor, Painter::line_onoffdash, lw);
return;
}
for (int i = 0; d[i]; ) {
int code = int(d[i++]);
- if (code & 1) { // code == 1 || code == 3
+ if (code & 1) { // code == 1 || code == 3 || code == 5
double xx = d[i++];
double yy = d[i++];
double x2 = d[i++];
pi.pain.line(
int(x + xx + 0.5), int(y + yy + 0.5),
int(x + x2 + 0.5), int(y + y2 + 0.5),
- pi.base.font.color());
+ pi.base.font.color(), Painter::line_solid, lw);
+ if (code == 5) { // thicker, but rounded
+ double const xa = x + xx + 0.5;
+ double const xb = x + x2 + 0.5;
+ double const ya = y + yy + 0.5;
+ double const yb = y + y2 + 0.5;
+ pi.pain.line(int(xa + 1), int(ya - 1),
+ int(xb - 1), int(yb - 1),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ pi.pain.line(int(xa + 1), int(ya + 1),
+ int(xb - 1), int(yb + 1),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ if (xa + 2 <= xb - 2) {
+ pi.pain.line(int(xa + 2), int(ya - 2),
+ int(xb - 2), int(yb - 2),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ pi.pain.line(int(xa + 2), int(ya + 2),
+ int(xb - 2), int(yb + 2),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ }
+ if (xa + 3 <= xb - 3) {
+ pi.pain.line(int(xa + 3), int(ya - 3),
+ int(xb - 3), int(yb - 3),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ pi.pain.line(int(xa + 3), int(ya + 3),
+ int(xb - 3), int(yb + 3),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ }
+ if (xa + 4 <= xb - 4) {
+ pi.pain.line(int(xa + 4), int(ya - 4),
+ int(xb - 4), int(yb - 4),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ pi.pain.line(int(xa + 4), int(ya + 4),
+ int(xb - 4), int(yb + 4),
+ pi.base.font.color(),
+ Painter::line_solid, lw);
+ }
+ }
} else {
int xp[32];
int yp[32];
- int const n = int(d[i++]);
- for (int j = 0; j < n; ++j) {
+ int const n2 = int(d[i++]);
+ for (int j = 0; j < n2; ++j) {
double xx = d[i++];
double yy = d[i++];
// lyxerr << ' ' << xx << ' ' << yy << ' ';
yp[j] = int(y + yy + 0.5);
// lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
}
- pi.pain.lines(xp, yp, n, pi.base.font.color());
+ pi.pain.lines(xp, yp, n2, pi.base.font.color(),
+ Painter::fill_none, Painter::line_solid, lw);
}
}
}
+docstring const & mathedSymbol(MetricsBase & mb, latexkeys const * sym)
+{
+ return (mb.font.style() == DISPLAY_STYLE && !sym->dsp_draw.empty()) ?
+ sym->dsp_draw : sym->draw;
+}
+
+
+int mathedSymbolDim(MetricsBase & mb, Dimension & dim, latexkeys const * sym)
+{
+ LASSERT((bool)sym, return 0);
+ //lyxerr << "metrics: symbol: '" << sym->name
+ // << "' in font: '" << sym->inset
+ // << "' drawn as: '" << sym->draw
+ // << "'" << endl;
+
+ bool const italic_upcase_greek = sym->inset == "cmr" &&
+ sym->extra == "mathalpha" &&
+ mb.fontname == "mathit";
+ std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
+ bool const change_font = font != "cmr" ||
+ (mb.fontname != "mathbb" &&
+ mb.fontname != "mathds" &&
+ mb.fontname != "mathfrak" &&
+ mb.fontname != "mathcal" &&
+ mb.fontname != "mathscr");
+ Changer dummy = change_font ? mb.changeFontSet(font) : noChange();
+ mathed_string_dim(mb.font, mathedSymbol(mb, sym), dim);
+ return mathed_char_kerning(mb.font, mathedSymbol(mb, sym).back());
+}
+
+
+void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym)
+{
+ LASSERT((bool)sym, return);
+ //lyxerr << "drawing: symbol: '" << sym->name
+ // << "' in font: '" << sym->inset
+ // << "' drawn as: '" << sym->draw
+ // << "'" << endl;
+
+ bool const italic_upcase_greek = sym->inset == "cmr" &&
+ sym->extra == "mathalpha" &&
+ pi.base.fontname == "mathit";
+ std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
+ bool const change_font = font != "cmr" ||
+ (pi.base.fontname != "mathbb" &&
+ pi.base.fontname != "mathds" &&
+ pi.base.fontname != "mathfrak" &&
+ pi.base.fontname != "mathcal" &&
+ pi.base.fontname != "mathscr");
+ Changer dummy = change_font ? pi.base.changeFontSet(font) : noChange();
+ pi.draw(x, y, mathedSymbol(pi.base, sym));
+}
+
+
void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
{
FontInfo font = mi.base.font;
// does not work
fontinfo fontinfos[] = {
// math fonts
+ // Color_math determines which fonts are math (see isMathFont)
{"mathnormal", ROMAN_FAMILY, MEDIUM_SERIES,
ITALIC_SHAPE, Color_math},
{"mathbf", inh_family, BOLD_SERIES,
inh_shape, Color_math},
{"mathbb", MSB_FAMILY, inh_series,
inh_shape, Color_math},
+ {"mathds", DS_FAMILY, inh_series,
+ inh_shape, Color_math},
{"mathtt", TYPEWRITER_FAMILY, inh_series,
inh_shape, Color_math},
{"mathit", inh_family, inh_series,
docstring asString(MathData const & ar)
{
odocstringstream os;
- otexrowstream ots(os, false);
- WriteStream ws(ots);
+ otexrowstream ots(os);
+ TeXMathStream ws(ots);
ws << ar;
return os.str();
}
void asArray(docstring const & str, MathData & ar, Parse::flags pf)
{
+ // If the QUIET flag is set, we are going to parse for either
+ // a paste operation or a macro definition. We try to do the
+ // right thing in all cases.
+
bool quiet = pf & Parse::QUIET;
- if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet))
+ bool macro = pf & Parse::MACRODEF;
+ if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet && !macro))
mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
}
docstring asString(InsetMath const & inset)
{
odocstringstream os;
- otexrowstream ots(os, false);
- WriteStream ws(ots);
+ otexrowstream ots(os);
+ TeXMathStream ws(ots);
inset.write(ws);
return os.str();
}
docstring asString(MathAtom const & at)
{
odocstringstream os;
- otexrowstream ots(os, false);
- WriteStream ws(ots);
+ otexrowstream ots(os);
+ TeXMathStream ws(ots);
at->write(ws);
return os.str();
}
+int axis_height(MetricsBase & mb)
+{
+ Changer dummy = mb.changeFontSet("mathnormal");
+ return theFontMetrics(mb.font).ascent('-') - 1;
+}
+
+
+void validate_math_word(LaTeXFeatures & features, docstring const & word)
+{
+ MathWordList const & words = mathedWordList();
+ MathWordList::const_iterator it = words.find(word);
+ if (it != words.end()) {
+ string const req = it->second.required;
+ if (!req.empty())
+ features.require(req);
+ }
+}
+
+
} // namespace lyx