lyx_mirror/src/mathed/MathSupport.cpp

1021 lines
23 KiB
C++
Raw Normal View History

/**
* \file MathSupport.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Alejandro Aguilar Sierra
* \author André Pönitz
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "MathSupport.h"
#include "InsetMathFont.h"
#include "InsetMathSymbol.h"
2016-11-20 22:41:36 +00:00
#include "Length.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/debug.h"
#include "support/docstream.h"
#include "support/lassert.h"
#include "support/lyxlib.h"
#include <map>
#include <algorithm>
using namespace std;
namespace lyx {
using frontend::Painter;
///
class Matrix {
public:
///
Matrix(int, double, double);
///
void transform(double &, double &);
private:
///
double m_[2][2];
};
Matrix::Matrix(int code, double x, double y)
{
double const cs = (code & 1) ? 0 : (1 - code);
double const sn = (code & 1) ? (2 - code) : 0;
m_[0][0] = cs * x;
m_[0][1] = sn * x;
m_[1][0] = -sn * y;
m_[1][1] = cs * y;
}
void Matrix::transform(double & x, double & y)
{
double xx = m_[0][0] * x + m_[0][1] * y;
double yy = m_[1][0] * x + m_[1][1] * y;
x = xx;
y = yy;
}
namespace {
/*
* 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
*/
double const parenthHigh[] = {
2, 13,
0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
0.9840, 0.9986,
0
};
double const parenth[] = {
2, 13,
0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
0.9930, 0.9919,
0
};
double const brace[] = {
2, 21,
0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
0
};
double const mapsto[] = {
2, 3,
0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
1, 0.015, 0.475, 0.945, 0.475,
1, 0.015, 0.015, 0.015, 0.985,
0
};
double const lhook[] = {
2, 3,
0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
1, 0.015, 0.475, 0.7, 0.475,
2, 5,
0.7, 0.015, 0.825, 0.15, 0.985, 0.25,
0.825, 0.35, 0.7, 0.475,
0
};
double const rhook[] = {
2, 3,
0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
1, 0.3, 0.475, 0.985, 0.475,
2, 5,
0.3, 0.015, 0.175, 0.15, 0.05, 0.25,
0.175, 0.35, 0.3, 0.475,
0
};
double const LRArrow[] = {
2, 3,
0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
2, 3,
0.75, 0.015, 0.95, 0.5, 0.75, 0.985,
1, 0.2, 0.8, 0.8, 0.8,
1, 0.2, 0.2, 0.8, 0.2,
0
};
double const LArrow[] = {
2, 3,
0.25, 0.015, 0.05, 0.5, 0.25, 0.985,
1, 0.2, 0.8, 0.985, 0.8,
1, 0.2, 0.2, 0.985, 0.2,
0
};
double const lharpoondown[] = {
2, 2,
0.015, 0.5, 0.25, 0.985,
1, 0.02, 0.475, 0.985, 0.475,
0
};
double const lharpoonup[] = {
2, 2,
0.25, 0.015, 0.015, 0.5,
1, 0.02, 0.525, 0.985, 0.525,
0
};
double const lrharpoons[] = {
2, 2,
0.25, 0.015, 0.015, 0.225,
1, 0.02, 0.23, 0.985, 0.23,
2, 2,
0.75, 0.985, 0.985, 0.775,
1, 0.02, 0.7, 0.980, 0.7,
0
};
double const rlharpoons[] = {
2, 2,
0.75, 0.015, 0.985, 0.225,
1, 0.02, 0.23, 0.985, 0.23,
2, 2,
0.25, 0.985, 0.015, 0.775,
1, 0.02, 0.7, 0.980, 0.7,
0
};
double const arrow[] = {
4, 7,
0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
0.9500, 0.7500,
3, 0.5000, 0.1500, 0.5000, 0.9500,
0
};
double const Arrow[] = {
4, 7,
0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
0.9500, 0.7500,
3, 0.3500, 0.5000, 0.3500, 0.9500,
3, 0.6500, 0.5000, 0.6500, 0.9500,
0
};
double const udarrow[] = {
2, 3,
0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
2, 3,
0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
1, 0.5, 0.1, 0.5, 0.9,
0
};
double const Udarrow[] = {
2, 3,
0.015, 0.25, 0.5, 0.05, 0.95, 0.25,
2, 3,
0.015, 0.75, 0.5, 0.95, 0.95, 0.75,
1, 0.35, 0.2, 0.35, 0.8,
1, 0.65, 0.2, 0.65, 0.8,
0
};
double const brack[] = {
2, 4,
0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
0
};
double const dbrack[] = {
2, 4,
0.95, 0.05, 0.05, 0.05, 0.05, 0.95, 0.95, 0.95,
2, 2,
0.50, 0.05, 0.50, 0.95,
0
};
double const corner[] = {
2, 3,
0.95, 0.05, 0.05, 0.05, 0.05, 0.95,
0
};
double const angle[] = {
2, 3,
1, 0, 0.05, 0.5, 1, 1,
0
};
double const slash[] = {
1, 0.95, 0.05, 0.05, 0.95,
0
};
double const hline[] = {
1, 0.00, 0.5, 1.0, 0.5,
0
};
double const ddot[] = {
1, 0.2, 0.5, 0.3, 0.5,
1, 0.7, 0.5, 0.8, 0.5,
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,
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,
0
};
double const hline3[] = {
1, 0.1, 0, 0.15, 0,
1, 0.475, 0, 0.525, 0,
1, 0.85, 0, 0.9, 0,
0
};
double const dline3[] = {
1, 0.1, 0.1, 0.15, 0.15,
1, 0.475, 0.475, 0.525, 0.525,
1, 0.85, 0.85, 0.9, 0.9,
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,
0
};
double const vert[] = {
1, 0.5, 0.05, 0.5, 0.95,
0
};
double const Vert[] = {
1, 0.3, 0.05, 0.3, 0.95,
1, 0.7, 0.05, 0.7, 0.95,
0
};
double const tilde[] = {
2, 4,
0.00, 0.8, 0.25, 0.2, 0.75, 0.8, 1.00, 0.2,
0
};
struct deco_struct {
double const * data;
int angle;
};
struct named_deco_struct {
char const * name;
double const * data;
int angle;
};
named_deco_struct deco_table[] = {
// Decorations
{"widehat", angle, 3 },
{"widetilde", tilde, 0 },
{"underbar", hline, 0 },
{"underline", hline, 0 },
{"overline", hline, 0 },
{"underbrace", brace, 1 },
{"overbrace", brace, 3 },
{"overleftarrow", arrow, 1 },
{"overrightarrow", arrow, 3 },
{"overleftrightarrow", udarrow, 1 },
{"xhookleftarrow", lhook, 0 },
{"xhookrightarrow", rhook, 0 },
{"xleftarrow", arrow, 1 },
{"xLeftarrow", LArrow, 0 },
{"xleftharpoondown", lharpoondown, 0 },
{"xleftharpoonup", lharpoonup, 0 },
{"xleftrightharpoons", lrharpoons, 0 },
{"xleftrightarrow", udarrow, 1 },
{"xLeftrightarrow", LRArrow, 0 },
{"xmapsto", mapsto, 0 },
{"xrightarrow", arrow, 3 },
{"xRightarrow", LArrow, 2 },
{"xrightharpoondown", lharpoonup, 2 },
{"xrightharpoonup", lharpoondown, 2 },
{"xrightleftharpoons", rlharpoons, 0 },
{"underleftarrow", arrow, 1 },
{"underrightarrow", arrow, 3 },
{"underleftrightarrow", udarrow, 1 },
{"undertilde", tilde, 0 },
{"utilde", tilde, 0 },
// Delimiters
{"(", parenth, 0 },
{")", parenth, 2 },
{"{", brace, 0 },
{"}", brace, 2 },
{"lbrace", brace, 0 },
{"rbrace", brace, 2 },
{"[", brack, 0 },
{"]", brack, 2 },
{"llbracket", dbrack, 0 },
{"rrbracket", dbrack, 2 },
{"|", vert, 0 },
{"/", slash, 0 },
{"slash", slash, 0 },
{"vert", vert, 0 },
{"lvert", vert, 0 },
{"rvert", vert, 0 },
{"Vert", Vert, 0 },
{"lVert", Vert, 0 },
{"rVert", Vert, 0 },
{"'", slash, 1 },
{"<", angle, 0 },
{">", angle, 2 },
{"\\", slash, 1 },
{"backslash", slash, 1 },
{"langle", angle, 0 },
{"lceil", corner, 0 },
{"lfloor", corner, 1 },
{"rangle", angle, 2 },
{"rceil", corner, 3 },
{"rfloor", corner, 2 },
{"downarrow", arrow, 2 },
{"Downarrow", Arrow, 2 },
{"uparrow", arrow, 0 },
{"Uparrow", Arrow, 0 },
{"updownarrow", udarrow, 0 },
{"Updownarrow", Udarrow, 0 },
// Accents
{"ddot", ddot, 0 },
{"dddot", dddot, 0 },
{"ddddot", ddddot, 0 },
{"hat", angle, 3 },
{"grave", slash, 1 },
{"acute", slash, 0 },
{"tilde", tilde, 0 },
{"bar", hline, 0 },
{"dot", hlinesmall, 0 },
{"check", angle, 1 },
{"breve", parenth, 1 },
{"vec", arrow, 3 },
{"mathring", ring, 0 },
// Dots
{"dots", hline3, 0 },
{"ldots", hline3, 0 },
{"cdots", hline3, 0 },
{"vdots", hline3, 1 },
{"ddots", dline3, 0 },
{"adots", dline3, 1 },
{"iddots", dline3, 1 },
{"dotsb", hline3, 0 },
{"dotsc", hline3, 0 },
{"dotsi", hline3, 0 },
{"dotsm", hline3, 0 },
{"dotso", hline3, 0 }
};
map<docstring, deco_struct> deco_list;
// sort the table on startup
class init_deco_table {
public:
init_deco_table() {
unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
deco_struct d;
d.data = p->data;
d.angle = p->angle;
deco_list[from_ascii(p->name)] = d;
}
}
};
2017-12-16 04:53:45 +00:00
static init_deco_table dummy_deco_table;
deco_struct const * search_deco(docstring const & name)
{
map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
return p == deco_list.end() ? 0 : &(p->second);
}
Bulk cleanup/fix incorrect annotation at the end of namespaces. This commit does a bulk fix of incorrect annotations (comments) at the end of namespaces. The commit was generated by initially running clang-format, and then from the diff of the result extracting the hunks corresponding to fixes of namespace comments. The changes being applied and all the results have been manually reviewed. The source code successfully builds on macOS. Further details on the steps below, in case they're of interest to someone else in the future. 1. Checkout a fresh and up to date version of src/ git pull && git checkout -- src && git status src 2. Ensure there's a suitable .clang-format in place, i.e. with options to fix the comment at the end of namespaces, including: FixNamespaceComments: true SpacesBeforeTrailingComments: 1 and that clang-format is >= 5.0.0, by doing e.g.: clang-format -dump-config | grep Comments: clang-format --version 3. Apply clang-format to the source: clang-format -i $(find src -name "*.cpp" -or -name "*.h") 4. Create and filter out hunks related to fixing the namespace git diff -U0 src > tmp.patch grepdiff '^} // namespace' --output-matching=hunk tmp.patch > fix_namespace.patch 5. Filter out hunks corresponding to simple fixes into to a separate patch: pcregrep -M -e '^diff[^\n]+\nindex[^\n]+\n--- [^\n]+\n\+\+\+ [^\n]+\n' \ -e '^@@ -[0-9]+ \+[0-9]+ @@[^\n]*\n-\}[^\n]*\n\+\}[^\n]*\n' \ fix_namespace.patch > fix_namespace_simple.patch 6. Manually review the simple patch and then apply it, after first restoring the source. git checkout -- src patch -p1 < fix_namespace_simple.path 7. Manually review the (simple) changes and then stage the changes git diff src git add src 8. Again apply clang-format and filter out hunks related to any remaining fixes to the namespace, this time filter with more context. There will be fewer hunks as all the simple cases have already been handled: clang-format -i $(find src -name "*.cpp" -or -name "*.h") git diff src > tmp.patch grepdiff '^} // namespace' --output-matching=hunk tmp.patch > fix_namespace2.patch 9. Manually review/edit the resulting patch file to remove hunks for files which need to be dealt with manually, noting the file names and line numbers. Then restore files to as before applying clang-format and apply the patch: git checkout src patch -p1 < fix_namespace2.patch 10. Manually fix the files noted in the previous step. Stage files, review changes and commit.
2017-07-23 11:11:54 +00:00
} // namespace
int mathed_font_em(FontInfo const & font)
{
return theFontMetrics(font).em();
}
int mathed_font_x_height(FontInfo const & font)
{
return theFontMetrics(font).ascent('x');
}
/* The math units. Quoting TeX by Topic, p.205:
*
* Spacing around mathematical objects is measured in mu units. A mu
* is 1/18th part of \fontdimen6 of the font in family 2 in the
* current style, the quad value of the symbol font.
*
* A \thickmuskip (default value in plain TeX: 5mu plus 5mu) is
* inserted around (binary) relations, except where these are preceded
* or followed by other relations or punctuation, and except if they
* follow an open, or precede a close symbol.
*
* A \medmuskip (default value in plain TeX: 4mu plus 2mu minus 4mu)
* is put around binary operators.
*
* A \thinmuskip (default value in plain TeX: 3mu) follows after
* 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.
*/
2016-11-20 22:41:36 +00:00
int mathed_mu(FontInfo const & font, double mu)
{
2016-11-20 22:41:36 +00:00
MetricsBase mb(nullptr, font);
return mb.inPixels(Length(mu, Length::MU));
}
2016-11-20 22:41:36 +00:00
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)
{
return theFontMetrics(font).width(c);
}
int mathed_char_kerning(FontInfo const & font, char_type c)
{
frontend::FontMetrics const & fm = theFontMetrics(font);
return max(0, fm.rbearing(c) - fm.width(c));
}
void mathed_string_dim(FontInfo const & font,
docstring const & s,
Dimension & dim)
{
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));
}
dim.wid = fm.width(s);
}
int mathed_string_width(FontInfo const & font, docstring const & s)
{
return theFontMetrics(font).width(s);
}
void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
docstring const & name)
{
if (name == ".") {
pi.pain.line(x + w/2, y, x + w/2, y + h,
Color_cursor, Painter::line_onoffdash);
return;
}
deco_struct const * mds = search_deco(name);
if (!mds) {
lyxerr << "Deco was not found. Programming error?" << endl;
lyxerr << "name: '" << to_utf8(name) << "'" << endl;
return;
}
int const n = (w < h) ? w : h;
int const r = mds->angle;
double const * d = mds->data;
if (h > 70 && (name == "(" || name == ")"))
d = parenthHigh;
Matrix mt(r, w, h);
Matrix sqmt(r, n, n);
if (r > 0 && r < 3)
y += h;
if (r >= 2)
x += w;
for (int i = 0; d[i]; ) {
int code = int(d[i++]);
if (code & 1) { // code == 1 || code == 3
double xx = d[i++];
double yy = d[i++];
double x2 = d[i++];
double y2 = d[i++];
if (code == 3)
sqmt.transform(xx, yy);
else
mt.transform(xx, yy);
mt.transform(x2, y2);
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());
} else {
int xp[32];
int yp[32];
2017-12-16 04:53:45 +00:00
int const n2 = int(d[i++]);
for (int j = 0; j < n2; ++j) {
double xx = d[i++];
double yy = d[i++];
// lyxerr << ' ' << xx << ' ' << yy << ' ';
if (code == 4)
sqmt.transform(xx, yy);
else
mt.transform(xx, yy);
xp[j] = int(x + xx + 0.5);
yp[j] = int(y + yy + 0.5);
// lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
}
2017-12-16 04:53:45 +00:00
pi.pain.lines(xp, yp, n2, pi.base.font.color());
}
}
}
2016-11-20 21:34:03 +00:00
void mathedSymbolDim(MetricsBase & mb, Dimension & dim, latexkeys const * sym)
{
LASSERT((bool)sym, return);
//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" &&
2016-11-20 21:34:03 +00:00
mb.fontname == "mathit";
std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
2016-11-20 21:34:03 +00:00
Changer dummy = mb.changeFontSet(font);
mathed_string_dim(mb.font, sym->draw, dim);
}
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;
Changer dummy = pi.base.changeFontSet(font);
pi.draw(x, y, sym->draw);
}
void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
{
FontInfo font = mi.base.font;
augmentFont(font, "mathnormal");
mathed_string_dim(font, str, dim);
}
void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
{
FontInfo f = pi.base.font;
augmentFont(f, "mathnormal");
f.setColor(Color_latex);
pi.pain.text(x, y, str, f);
}
void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
{
FontInfo f = pi.base.font;
augmentFont(f, "mathnormal");
f.setColor(Color_foreground);
pi.pain.text(x, y, str, f);
}
void math_font_max_dim(FontInfo const & font, int & asc, int & des)
{
frontend::FontMetrics const & fm = theFontMetrics(font);
asc = fm.maxAscent();
des = fm.maxDescent();
}
struct fontinfo {
string cmd_;
FontFamily family_;
FontSeries series_;
FontShape shape_;
ColorCode color_;
};
FontFamily const inh_family = INHERIT_FAMILY;
FontSeries const inh_series = INHERIT_SERIES;
FontShape const inh_shape = INHERIT_SHAPE;
// mathnormal should be the first, otherwise the fallback further down
// 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},
{"mathcal", CMSY_FAMILY, inh_series,
inh_shape, Color_math},
{"mathfrak", EUFRAK_FAMILY, inh_series,
inh_shape, Color_math},
{"mathrm", ROMAN_FAMILY, inh_series,
UP_SHAPE, Color_math},
{"mathsf", SANS_FAMILY, inh_series,
inh_shape, Color_math},
{"mathbb", MSB_FAMILY, inh_series,
inh_shape, Color_math},
{"mathtt", TYPEWRITER_FAMILY, inh_series,
inh_shape, Color_math},
{"mathit", inh_family, inh_series,
ITALIC_SHAPE, Color_math},
{"mathscr", RSFS_FAMILY, inh_series,
2014-03-08 09:57:24 +00:00
inh_shape, Color_math},
{"cmex", CMEX_FAMILY, inh_series,
inh_shape, Color_math},
{"cmm", CMM_FAMILY, inh_series,
inh_shape, Color_math},
{"cmr", CMR_FAMILY, inh_series,
inh_shape, Color_math},
{"cmsy", CMSY_FAMILY, inh_series,
inh_shape, Color_math},
{"eufrak", EUFRAK_FAMILY, inh_series,
inh_shape, Color_math},
{"msa", MSA_FAMILY, inh_series,
inh_shape, Color_math},
{"msb", MSB_FAMILY, inh_series,
inh_shape, Color_math},
{"stmry", STMARY_FAMILY, inh_series,
inh_shape, Color_math},
{"wasy", WASY_FAMILY, inh_series,
inh_shape, Color_math},
{"esint", ESINT_FAMILY, inh_series,
inh_shape, Color_math},
// Text fonts
{"text", inh_family, inh_series,
inh_shape, Color_foreground},
{"textbf", inh_family, BOLD_SERIES,
inh_shape, Color_foreground},
{"textit", inh_family, inh_series,
ITALIC_SHAPE, Color_foreground},
{"textmd", inh_family, MEDIUM_SERIES,
inh_shape, Color_foreground},
{"textnormal", inh_family, inh_series,
UP_SHAPE, Color_foreground},
{"textrm", ROMAN_FAMILY,
inh_series, UP_SHAPE,Color_foreground},
{"textsc", inh_family, inh_series,
SMALLCAPS_SHAPE, Color_foreground},
{"textsf", SANS_FAMILY, inh_series,
inh_shape, Color_foreground},
{"textsl", inh_family, inh_series,
SLANTED_SHAPE, Color_foreground},
{"texttt", TYPEWRITER_FAMILY, inh_series,
inh_shape, Color_foreground},
{"textup", inh_family, inh_series,
UP_SHAPE, Color_foreground},
// TIPA support
{"textipa", inh_family, inh_series,
inh_shape, Color_foreground},
// mhchem support
{"ce", inh_family, inh_series,
inh_shape, Color_foreground},
{"cf", inh_family, inh_series,
inh_shape, Color_foreground},
// LyX internal usage
{"lyxtex", inh_family, inh_series,
UP_SHAPE, Color_latex},
// FIXME: The following two don't work on OS X, since the Symbol font
// uses a different encoding, and is therefore disabled in
// FontLoader::available().
{"lyxsymbol", SYMBOL_FAMILY, inh_series,
inh_shape, Color_math},
{"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
inh_shape, Color_math},
{"lyxblacktext", ROMAN_FAMILY, MEDIUM_SERIES,
UP_SHAPE, Color_foreground},
{"lyxnochange", inh_family, inh_series,
inh_shape, Color_foreground},
{"lyxfakebb", TYPEWRITER_FAMILY, BOLD_SERIES,
UP_SHAPE, Color_math},
{"lyxfakecal", SANS_FAMILY, MEDIUM_SERIES,
ITALIC_SHAPE, Color_math},
{"lyxfakefrak", ROMAN_FAMILY, BOLD_SERIES,
ITALIC_SHAPE, Color_math}
};
fontinfo * lookupFont(string const & name)
{
//lyxerr << "searching font '" << name << "'" << endl;
int const n = sizeof(fontinfos) / sizeof(fontinfo);
for (int i = 0; i < n; ++i)
if (fontinfos[i].cmd_ == name) {
//lyxerr << "found '" << i << "'" << endl;
return fontinfos + i;
}
return 0;
}
fontinfo * searchFont(string const & name)
{
fontinfo * f = lookupFont(name);
return f ? f : fontinfos;
// this should be mathnormal
//return searchFont("mathnormal");
}
bool isFontName(string const & name)
{
return lookupFont(name);
}
bool isMathFont(string const & name)
{
fontinfo * f = lookupFont(name);
return f && f->color_ == Color_math;
}
bool isTextFont(string const & name)
Index: src/mathed/InsetMathHull.cpp =================================================================== --- src/mathed/InsetMathHull.cpp (revisione 34304) +++ src/mathed/InsetMathHull.cpp (copia locale) @@ -328,6 +328,23 @@ docstring InsetMathHull::standardFont() } +docstring InsetMathHull::standardColor() const +{ + docstring color; + switch (type_) { + case hullRegexp: + color = from_ascii("foreground"); + break; + case hullNone: + color = from_ascii("foreground"); + break; + default: + color = from_ascii("math"); + } + return color; +} + + bool InsetMathHull::previewState(BufferView * bv) const { if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON) { @@ -417,8 +434,11 @@ void InsetMathHull::draw(PainterInfo & p return; } + bool const really_change_color = pi.base.font.color() == Color_none; + ColorChanger dummy0(pi.base.font, standardColor(), really_change_color); FontSetChanger dummy1(pi.base, standardFont()); StyleChanger dummy2(pi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT); + InsetMathGrid::draw(pi, x + 1, y); if (numberedType()) { Index: src/mathed/MathSupport.cpp =================================================================== --- src/mathed/MathSupport.cpp (revisione 34311) +++ src/mathed/MathSupport.cpp (copia locale) @@ -653,6 +653,13 @@ bool isMathFont(docstring const & name) } +bool isTextFont(docstring const & name) +{ + fontinfo * f = lookupFont(name); + return f && f->color_ == Color_foreground; +} + + FontInfo getFont(docstring const & name) { FontInfo font; Index: src/mathed/MathSupport.h =================================================================== --- src/mathed/MathSupport.h (revisione 34311) +++ src/mathed/MathSupport.h (copia locale) @@ -51,6 +51,8 @@ bool isFontName(docstring const & name); bool isMathFont(docstring const & name); +bool isTextFont(docstring const & name); + // converts single cell to string docstring asString(MathData const & ar); // converts single inset to string Index: src/mathed/InsetMathHull.h =================================================================== --- src/mathed/InsetMathHull.h (revisione 34304) +++ src/mathed/InsetMathHull.h (copia locale) @@ -197,6 +197,8 @@ private: void changeCols(col_type); /// docstring standardFont() const; + /// + docstring standardColor() const; /// consistency check void check() const; /// can this change its number of rows? Index: src/MetricsInfo.cpp =================================================================== --- src/MetricsInfo.cpp (revisione 34312) +++ src/MetricsInfo.cpp (copia locale) @@ -235,11 +235,15 @@ FontSetChanger::FontSetChanger(MetricsBa save_ = mb; FontSize oldsize = save_.font.size(); ColorCode oldcolor = save_.font.color(); + docstring const oldname = from_ascii(save_.fontname); mb.fontname = name; mb.font = sane_font; augmentFont(mb.font, from_ascii(name)); mb.font.setSize(oldsize); - mb.font.setColor(oldcolor); + if (string(name) != "lyxtex" + && ((isTextFont(oldname) && oldcolor != Color_foreground) + || (isMathFont(oldname) && oldcolor != Color_math))) + mb.font.setColor(oldcolor); } } @@ -252,11 +256,15 @@ FontSetChanger::FontSetChanger(MetricsBa save_ = mb; FontSize oldsize = save_.font.size(); ColorCode oldcolor = save_.font.color(); + docstring const oldname = from_ascii(save_.fontname); mb.fontname = to_utf8(name); mb.font = sane_font; augmentFont(mb.font, name); mb.font.setSize(oldsize); - mb.font.setColor(oldcolor); + if (name != "lyxtex" + && ((isTextFont(oldname) && oldcolor != Color_foreground) + || (isMathFont(oldname) && oldcolor != Color_math))) + mb.font.setColor(oldcolor); } } @@ -294,17 +302,21 @@ WidthChanger::~WidthChanger() // ///////////////////////////////////////////////////////////////////////// -ColorChanger::ColorChanger(FontInfo & font, string const & color) - : Changer<FontInfo, string>(font) +ColorChanger::ColorChanger(FontInfo & font, docstring const & color, + bool really_change_color) + : Changer<FontInfo, ColorCode>(font), change_(really_change_color) { - save_ = lcolor.getFromLyXName(color); - font.setColor(lcolor.getFromLyXName(color)); + if (change_) { + save_ = font.color(); + font.setColor(lcolor.getFromLyXName(to_utf8(color))); + } } ColorChanger::~ColorChanger() { - orig_.setColor(lcolor.getFromLyXName(save_)); + if (change_) + orig_.setColor(save_); } Index: src/MetricsInfo.h =================================================================== --- src/MetricsInfo.h (revisione 34312) +++ src/MetricsInfo.h (copia locale) @@ -222,12 +222,16 @@ public: // temporarily change the used color -class ColorChanger : public Changer<FontInfo, std::string> { +class ColorChanger : public Changer<FontInfo, ColorCode> { public: /// - ColorChanger(FontInfo & font, std::string const & color); + ColorChanger(FontInfo & font, docstring const & color, + bool really_change_color = true); /// ~ColorChanger(); +private: + /// + bool change_; }; } // namespace lyx git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@34320 a592a061-630c-0410-9148-cb99ea01b6c8
2010-04-28 01:40:11 +00:00
{
fontinfo * f = lookupFont(name);
return f && f->color_ == Color_foreground;
}
FontInfo getFont(string const & name)
{
FontInfo font;
augmentFont(font, name);
return font;
}
void fakeFont(string const & orig, string const & fake)
{
fontinfo * forig = searchFont(orig);
fontinfo * ffake = searchFont(fake);
if (forig && ffake) {
forig->family_ = ffake->family_;
forig->series_ = ffake->series_;
forig->shape_ = ffake->shape_;
forig->color_ = ffake->color_;
} else {
lyxerr << "Can't fake font '" << orig << "' with '"
<< fake << "'" << endl;
}
}
void augmentFont(FontInfo & font, string const & name)
{
static bool initialized = false;
if (!initialized) {
initialized = true;
// fake fonts if necessary
if (!theFontLoader().available(getFont("mathfrak")))
fakeFont("mathfrak", "lyxfakefrak");
if (!theFontLoader().available(getFont("mathcal")))
fakeFont("mathcal", "lyxfakecal");
}
fontinfo * info = searchFont(name);
if (info->family_ != inh_family)
font.setFamily(info->family_);
if (info->series_ != inh_series)
font.setSeries(info->series_);
if (info->shape_ != inh_shape)
font.setShape(info->shape_);
if (info->color_ != Color_none)
font.setColor(info->color_);
}
bool isAlphaSymbol(MathAtom const & at)
{
if (at->asCharInset() ||
(at->asSymbolInset() &&
at->asSymbolInset()->isOrdAlpha()))
return true;
if (at->asFontInset()) {
MathData const & ar = at->asFontInset()->cell(0);
for (size_t i = 0; i < ar.size(); ++i) {
if (!(ar[i]->asCharInset() ||
(ar[i]->asSymbolInset() &&
ar[i]->asSymbolInset()->isOrdAlpha())))
return false;
}
return true;
}
return false;
}
docstring asString(MathData const & ar)
{
odocstringstream os;
otexrowstream ots(os);
WriteStream 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;
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);
WriteStream ws(ots);
inset.write(ws);
return os.str();
}
docstring asString(MathAtom const & at)
{
odocstringstream os;
otexrowstream ots(os);
WriteStream ws(ots);
at->write(ws);
return os.str();
}
2016-12-19 23:15:59 +00:00
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.requires;
if (!req.empty())
features.require(req);
}
}
} // namespace lyx