X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathChar.cpp;h=1fef2209a54c09bd3601ea4d86621ef10f31883f;hb=cdc847fd304019a19425a0d5d9d42a556a937097;hp=03bda07cf60475c4ebaae4584ea401c613fccc12;hpb=8164fea772121e41145fabed8172ea6b8ec0f007;p=lyx.git diff --git a/src/mathed/InsetMathChar.cpp b/src/mathed/InsetMathChar.cpp index 03bda07cf6..1fef2209a5 100644 --- a/src/mathed/InsetMathChar.cpp +++ b/src/mathed/InsetMathChar.cpp @@ -13,6 +13,7 @@ #include "InsetMathChar.h" +#include "MathParser.h" #include "MathSupport.h" #include "MathStream.h" #include "MetricsInfo.h" @@ -34,11 +35,55 @@ namespace lyx { extern bool has_math_fonts; -static bool isBinaryOp(char_type c) +namespace { +latexkeys const * makeSubstitute(char_type c) { - return support::contains("+-<>=/*", static_cast(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) { @@ -47,7 +92,7 @@ static bool slanted(char_type c) InsetMathChar::InsetMathChar(char_type c) - : char_(c), kerning_(0) + : char_(c), kerning_(0), subst_(makeSubstitute(c)) {} @@ -60,60 +105,40 @@ Inset * InsetMathChar::clone() const void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const { -#if 1 - if (char_ == '=' && has_math_fonts) { - FontSetChanger dummy(mi.base, "cmr"); - dim = theFontMetrics(mi.base.font).dimension(char_); - } else if ((char_ == '>' || char_ == '<') && has_math_fonts) { - FontSetChanger dummy(mi.base, "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.base, dim, subst_); + kerning_ = mathed_char_kerning(mi.base.font, *subst_->draw.rbegin()); + return; } else if (!slanted(char_) && mi.base.fontname == "mathnormal") { - ShapeChanger dummy(mi.base.font, UP_SHAPE); + Changer dummy = mi.base.font.changeShape(UP_SHAPE); dim = theFontMetrics(mi.base.font).dimension(char_); } else { frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); dim = fm.dimension(char_); kerning_ = fm.rbearing(char_) - dim.wid; } - int const em = mathed_char_width(mi.base.font, 'M'); - if (isBinaryOp(char_)) - dim.wid += static_cast(0.5*em+0.5); - else if (char_ == '\'') - dim.wid += static_cast(0.1667*em+0.5); -#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 << endl; - int const em = mathed_char_width(pi.base.font, 'M'); - if (isBinaryOp(char_)) - x += static_cast(0.25*em+0.5); - else if (char_ == '\'') - x += static_cast(0.0833*em+0.5); -#if 1 - if (char_ == '=' && has_math_fonts) { - FontSetChanger dummy(pi.base, "cmr"); - pi.draw(x, y, char_); - } else if ((char_ == '>' || char_ == '<') && has_math_fonts) { - FontSetChanger dummy(pi.base, "cmm"); - pi.draw(x, y, char_); - } else if (!slanted(char_) && pi.base.fontname == "mathnormal") { - ShapeChanger dummy(pi.base.font, UP_SHAPE); - pi.draw(x, y, char_); - } else { - pi.draw(x, y, char_); + //lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << std::endl; + 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_); + return; + } } -#else - drawChar(pain, font_, x, y, char_); -#endif + pi.draw(x, y, char_); } @@ -203,6 +228,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; @@ -236,9 +263,19 @@ void InsetMathChar::htmlize(HtmlStream & ms) const } -bool InsetMathChar::isRelOp() const +MathClass InsetMathChar::mathClass() const { - return char_ == '=' || char_ == '<' || char_ == '>'; + // this information comes from fontmath.ltx in LaTeX source. + char const ch = static_cast(char_); + if (subst_) + return string_to_class(subst_->extra); + else if (support::contains(",;", ch)) + return MC_PUNCT; + else if (support::contains("([", ch)) + return MC_OPEN; + else if (support::contains(")]!?", ch)) + return MC_CLOSE; + else return MC_ORD; }