mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-25 10:58:52 +00:00
Display properly math characters that behave like symbols
* set up a replacement of *, -, and : by the adequate symbols (#9893) * fix the wrong character selection and operator spacing in \text mode * hide some internal symbols from the auto-completion.
This commit is contained in:
parent
ad7e2435cf
commit
be836909c5
17
lib/symbols
17
lib/symbols
@ -298,7 +298,7 @@ diamondsuit cmsy 125 168 mathord ♢
|
||||
heartsuit cmsy 126 169 mathord ♡
|
||||
spadesuit cmsy 127 170 mathord ♠
|
||||
# We define lyxnot as mathrel in order to have proper alignment
|
||||
lyxnot cmsy 54 47 mathrel /
|
||||
lyxnot cmsy 54 47 mathrel / hiddensymbol
|
||||
iffont cmsy
|
||||
# 10mu is the extra space added to relation operators
|
||||
\def\not{\lyxnot\kern-20mu}
|
||||
@ -669,11 +669,16 @@ hslash msb 125 0 mathord ℏ
|
||||
hbar msb 126 0 mathord ℏ
|
||||
backepsilon msb 127 0 mathrel ϶
|
||||
|
||||
lyxbar cmsy 161 0 mathord —
|
||||
lyxeq cmr 61 0 mathord =
|
||||
lyxdabar msa 57 0 mathord –
|
||||
lyxright msa 75 0 mathord →
|
||||
lyxleft msa 76 0 mathord ←
|
||||
lyxbar cmsy 161 0 mathord — hiddensymbol
|
||||
lyxminus cmsy 161 0 mathbin — hiddensymbol
|
||||
lyxplus cmr 43 43 mathbin + hiddensymbol
|
||||
lyxeq cmr 61 61 mathord = hiddensymbol
|
||||
lyxeqrel cmr 61 61 mathrel = hiddensymbol
|
||||
lyxlt cmm 60 60 mathrel < hiddensymbol
|
||||
lyxgt cmm 62 62 mathrel > hiddensymbol
|
||||
lyxdabar msa 57 0 mathord – hiddensymbol
|
||||
lyxright msa 75 0 mathord → hiddensymbol
|
||||
lyxleft msa 76 0 mathord ← hiddensymbol
|
||||
|
||||
male wasy 26 0 x ♂
|
||||
female wasy 25 0 x ♀
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "InsetMathChar.h"
|
||||
|
||||
#include "MathParser.h"
|
||||
#include "MathSupport.h"
|
||||
#include "MathStream.h"
|
||||
#include "MetricsInfo.h"
|
||||
@ -34,6 +35,57 @@ namespace lyx {
|
||||
extern bool has_math_fonts;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
latexkeys const * makeSubstitute(char_type c)
|
||||
{
|
||||
std::string name;
|
||||
switch (c) {
|
||||
// Latex replaces ', *, -, and : with specific symbols. With unicode-math,
|
||||
// these symbols are replaced respectively by ^U+2032, U+2217, U+2212 and
|
||||
// U+2236 (the latter substitution can be turned off with a package
|
||||
// option). Unicode-math also replaces ` with \backprime.
|
||||
// prime needs to be placed in superscript unless an opentype font is used.
|
||||
//case '\'':
|
||||
//name = "prime";
|
||||
//break;
|
||||
case '*':
|
||||
name = "ast";
|
||||
break;
|
||||
case '-':
|
||||
name = "lyxminus";// unicode-math: "minus"
|
||||
break;
|
||||
case ':':
|
||||
name = "ordinarycolon";// unicode-math: "mathratio"
|
||||
break;
|
||||
// The remaining replacements are not real character substitutions (from a
|
||||
// unicode point of view) but are done here: 1. for cosmetic reasons, in the
|
||||
// context of being stuck with CM fonts at the moment, to ensure consistency
|
||||
// with related symbols: -, \leq, \geq, etc. 2. to get the proper spacing
|
||||
// as defined in lib/symbols.
|
||||
case '+':
|
||||
name = "lyxplus";//unicode-math: "mathplus"
|
||||
break;
|
||||
case '>':
|
||||
name = "lyxgt";//unicode-math: "greater"
|
||||
break;
|
||||
case '<':
|
||||
name = "lyxlt";//unicode-math: "less"
|
||||
break;
|
||||
case '=':
|
||||
name = "lyxeqrel";//unicode-math: "equal"
|
||||
break;
|
||||
//case ','://unicode-math: "mathcomma"
|
||||
//case ';'://unicode-math: "mathsemicolon"
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return in_word_set(from_ascii(name));
|
||||
}
|
||||
|
||||
} //anonymous namespace
|
||||
|
||||
|
||||
static bool slanted(char_type c)
|
||||
{
|
||||
return isAlphaASCII(c) || Encodings::isMathAlpha(c);
|
||||
@ -41,7 +93,7 @@ static bool slanted(char_type c)
|
||||
|
||||
|
||||
InsetMathChar::InsetMathChar(char_type c)
|
||||
: char_(c), kerning_(0)
|
||||
: char_(c), kerning_(0), subst_(makeSubstitute(c))
|
||||
{}
|
||||
|
||||
|
||||
@ -54,13 +106,13 @@ Inset * InsetMathChar::clone() const
|
||||
|
||||
void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
{
|
||||
#if 1
|
||||
if (char_ == '=' && has_math_fonts) {
|
||||
Changer dummy = mi.base.changeFontSet("cmr");
|
||||
dim = theFontMetrics(mi.base.font).dimension(char_);
|
||||
} else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
|
||||
Changer dummy = mi.base.changeFontSet("cmm");
|
||||
dim = theFontMetrics(mi.base.font).dimension(char_);
|
||||
bool const mathfont = isMathFont(mi.base.fontname);
|
||||
if (mathfont && subst_) {
|
||||
// If the char has a substitute, draw the replacement symbol
|
||||
// instead, but only in math mode.
|
||||
mathedSymbolDim(mi, dim, subst_);
|
||||
kerning_ = mathed_char_kerning(mi.base.font, *subst_->draw.rbegin());
|
||||
return;
|
||||
} else if (!slanted(char_) && mi.base.fontname == "mathnormal") {
|
||||
Changer dummy = mi.base.font.changeShape(UP_SHAPE);
|
||||
dim = theFontMetrics(mi.base.font).dimension(char_);
|
||||
@ -69,50 +121,27 @@ void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
dim = fm.dimension(char_);
|
||||
kerning_ = fm.rbearing(char_) - dim.wid;
|
||||
}
|
||||
if (isMathBin())
|
||||
dim.wid += 2 * mathed_medmuskip(mi.base.font);
|
||||
else if (isMathRel())
|
||||
dim.wid += 2 * mathed_thickmuskip(mi.base.font);
|
||||
else if (isMathPunct())
|
||||
if (mathfont && isMathPunct())
|
||||
dim.wid += mathed_thinmuskip(mi.base.font);
|
||||
else if (char_ == '\'')
|
||||
// FIXME: don't know where this is coming from
|
||||
dim.wid += mathed_thinmuskip(mi.base.font);
|
||||
#else
|
||||
whichFont(font_, code_, mi);
|
||||
dim = theFontMetrics(font_).dimension(char_);
|
||||
if (isBinaryOp(char_, code_))
|
||||
dim.wid += 2 * theFontMetrics(font_).width(' ');
|
||||
lyxerr << "InsetMathChar::metrics: " << dim << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
|
||||
{
|
||||
//lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << std::endl;
|
||||
if (isMathBin())
|
||||
x += mathed_medmuskip(pi.base.font);
|
||||
else if (isMathRel())
|
||||
x += mathed_thickmuskip(pi.base.font);
|
||||
else if (char_ == '\'')
|
||||
x += mathed_thinmuskip(pi.base.font) / 2;
|
||||
#if 1
|
||||
if (char_ == '=' && has_math_fonts) {
|
||||
Changer dummy = pi.base.changeFontSet("cmr");
|
||||
pi.draw(x, y, char_);
|
||||
} else if ((char_ == '>' || char_ == '<') && has_math_fonts) {
|
||||
Changer dummy = pi.base.changeFontSet("cmm");
|
||||
pi.draw(x, y, char_);
|
||||
if (isMathFont(pi.base.fontname)) {
|
||||
if (subst_) {
|
||||
// If the char has a substitute, draw the replacement symbol
|
||||
// instead, but only in math mode.
|
||||
mathedSymbolDraw(pi, x, y, subst_);
|
||||
return;
|
||||
} else if (!slanted(char_) && pi.base.fontname == "mathnormal") {
|
||||
Changer dummy = pi.base.font.changeShape(UP_SHAPE);
|
||||
pi.draw(x, y, char_);
|
||||
} else {
|
||||
pi.draw(x, y, char_);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
drawChar(pain, font_, x, y, char_);
|
||||
#endif
|
||||
}
|
||||
pi.draw(x, y, char_);
|
||||
}
|
||||
|
||||
|
||||
@ -202,6 +231,8 @@ void InsetMathChar::mathmlize(MathStream & ms) const
|
||||
void InsetMathChar::htmlize(HtmlStream & ms) const
|
||||
{
|
||||
std::string entity;
|
||||
// Not taking subst_ into account here because the MathML output of
|
||||
// <>=+-* looks correct as it is. FIXME: ' is not output as ^\prime
|
||||
switch (char_) {
|
||||
case '<': entity = "<"; break;
|
||||
case '>': entity = ">"; break;
|
||||
@ -237,19 +268,20 @@ void InsetMathChar::htmlize(HtmlStream & ms) const
|
||||
|
||||
bool InsetMathChar::isMathBin() const
|
||||
{
|
||||
return support::contains("+-*", static_cast<char>(char_));
|
||||
return subst_ && subst_->extra == "mathbin";
|
||||
}
|
||||
|
||||
|
||||
bool InsetMathChar::isMathRel() const
|
||||
{
|
||||
return support::contains("<>=:", static_cast<char>(char_));
|
||||
return subst_ && subst_->extra == "mathrel";
|
||||
}
|
||||
|
||||
|
||||
bool InsetMathChar::isMathPunct() const
|
||||
{
|
||||
return support::contains(",;", static_cast<char>(char_));
|
||||
return support::contains(",;", static_cast<char>(char_))
|
||||
|| (subst_ && subst_->extra == "mathpunct");
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
namespace lyx {
|
||||
|
||||
class latexkeys;
|
||||
|
||||
/// The base character inset.
|
||||
class InsetMathChar : public InsetMath {
|
||||
public:
|
||||
@ -60,9 +62,22 @@ public:
|
||||
private:
|
||||
virtual Inset * clone() const;
|
||||
/// the character
|
||||
char_type char_;
|
||||
char_type const char_;
|
||||
/// cached kerning for superscript
|
||||
mutable int kerning_;
|
||||
/// Inset to substitute char for, for on-screen display in math mode, as
|
||||
/// performed by LaTeX (#9893):
|
||||
/// * -> \ast (U+2217)
|
||||
/// - -> \lyxminus (U+2212)
|
||||
/// : -> \ordinarycolon (U+2236)
|
||||
///
|
||||
/// For cosmetic reasons, +, >, <, and = are also substituted to force the
|
||||
/// use of CM fonts for uniformity. If CM fonts are replaced with unicode
|
||||
/// math fonts, this should be removed, and substitutions of "'", ",", and
|
||||
/// ";" added.
|
||||
///
|
||||
/// Null if there is no substitute.
|
||||
latexkeys const * const subst_;
|
||||
};
|
||||
|
||||
} // namespace lyx
|
||||
|
@ -60,36 +60,17 @@ docstring InsetMathSymbol::name() const
|
||||
|
||||
void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
{
|
||||
//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" &&
|
||||
mi.base.fontname == "mathit";
|
||||
std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
|
||||
Changer dummy = mi.base.changeFontSet(font);
|
||||
mathed_string_dim(mi.base.font, sym_->draw, dim);
|
||||
docstring::const_reverse_iterator rit = sym_->draw.rbegin();
|
||||
kerning_ = mathed_char_kerning(mi.base.font, *rit);
|
||||
// set dim
|
||||
mathedSymbolDim(mi, dim, sym_);
|
||||
// set kerning_
|
||||
kerning_ = mathed_char_kerning(mi.base.font, *sym_->draw.rbegin());
|
||||
// correct height for broken cmex and wasy font
|
||||
if (sym_->inset == "cmex" || sym_->inset == "wasy") {
|
||||
h_ = 4 * dim.des / 5;
|
||||
dim.asc += h_;
|
||||
dim.des -= h_;
|
||||
}
|
||||
// seperate things a bit
|
||||
if (isMathBin())
|
||||
dim.wid += 2 * mathed_medmuskip(mi.base.font);
|
||||
else if (isMathRel())
|
||||
dim.wid += 2 * mathed_thickmuskip(mi.base.font);
|
||||
else if (isMathPunct())
|
||||
dim.wid += mathed_thinmuskip(mi.base.font);
|
||||
// FIXME: I see no reason for this
|
||||
//else
|
||||
// dim.wid += support::iround(0.1667 * em);
|
||||
|
||||
// set striptable_
|
||||
scriptable_ = false;
|
||||
if (mi.base.style == LM_ST_DISPLAY)
|
||||
if (sym_->inset == "cmex" || sym_->inset == "esint" ||
|
||||
@ -101,25 +82,7 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
|
||||
void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
|
||||
{
|
||||
//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" &&
|
||||
pi.base.fontname == "mathit";
|
||||
std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
|
||||
if (isMathBin())
|
||||
x += mathed_medmuskip(pi.base.font);
|
||||
else if (isMathRel())
|
||||
x += mathed_thickmuskip(pi.base.font);
|
||||
// FIXME: I see no reason for this
|
||||
//else
|
||||
// x += support::iround(0.0833 * em);
|
||||
|
||||
Changer dummy = pi.base.changeFontSet(font);
|
||||
pi.draw(x, y - h_, sym_->draw);
|
||||
mathedSymbolDraw(pi, x, y - h_, sym_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/docstream.h"
|
||||
#include "support/lassert.h"
|
||||
#include "support/lyxlib.h"
|
||||
|
||||
#include <map>
|
||||
@ -656,6 +657,52 @@ void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
|
||||
}
|
||||
|
||||
|
||||
void mathedSymbolDim(MetricsInfo & mi, 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" &&
|
||||
mi.base.fontname == "mathit";
|
||||
std::string const font = italic_upcase_greek ? "cmm" : sym->inset;
|
||||
Changer dummy = mi.base.changeFontSet(font);
|
||||
mathed_string_dim(mi.base.font, sym->draw, dim);
|
||||
// seperate things a bit
|
||||
if (sym->extra == "mathbin")
|
||||
dim.wid += 2 * mathed_medmuskip(mi.base.font);
|
||||
else if (sym->extra == "mathrel")
|
||||
dim.wid += 2 * mathed_thickmuskip(mi.base.font);
|
||||
else if (sym->extra == "mathpunct")
|
||||
dim.wid += mathed_thinmuskip(mi.base.font);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
if (sym->extra == "mathbin")
|
||||
x += mathed_medmuskip(pi.base.font);
|
||||
else if (sym->extra == "mathrel")
|
||||
x += mathed_thickmuskip(pi.base.font);
|
||||
|
||||
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;
|
||||
@ -708,6 +755,7 @@ FontShape const inh_shape = INHERIT_SHAPE;
|
||||
// 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,
|
||||
|
@ -25,6 +25,7 @@ class Dimension;
|
||||
class MathData;
|
||||
class MathAtom;
|
||||
class InsetMath;
|
||||
class latexkeys;
|
||||
|
||||
|
||||
int mathed_font_em(FontInfo const &);
|
||||
@ -48,6 +49,10 @@ void mathed_string_dim(FontInfo const & font,
|
||||
|
||||
int mathed_string_width(FontInfo const &, docstring const & s);
|
||||
|
||||
void mathedSymbolDim(MetricsInfo & mi, Dimension & dim, latexkeys const * sym);
|
||||
|
||||
void mathedSymbolDraw(PainterInfo & pi, int x, int y, latexkeys const * sym);
|
||||
|
||||
void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & s);
|
||||
|
||||
void drawStrRed(PainterInfo & pi, int x, int y, docstring const & s);
|
||||
|
Loading…
Reference in New Issue
Block a user