mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Implement rule 17
* Convert the kerning into a proper right margin for mathnormal, mathscr and mathcal (fonts with \fontdimen2 == 0 as per rule 17 from TeXBook). * Simulate the fact that characters in mathnormal fonts have a 0-width left bearing. * Implement subscript positioning in the case of rule 17 using negative italic correction (kerning_).
This commit is contained in:
parent
566d008c9d
commit
03a4b8c932
@ -230,7 +230,7 @@ public:
|
||||
/// math stuff usually isn't allowed in text mode
|
||||
virtual bool allowedIn(mode_type mode) const { return mode == MATH_MODE; }
|
||||
|
||||
/// superscript kerning
|
||||
/// Italic correction as described in InsetMathScript.h
|
||||
virtual int kerning(BufferView const *) const { return 0; }
|
||||
///
|
||||
bool isInToc() const { return true; }
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include "support/lstrings.h"
|
||||
#include "support/textutils.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace lyx {
|
||||
|
||||
@ -105,20 +109,38 @@ Inset * InsetMathChar::clone() const
|
||||
|
||||
void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
{
|
||||
bool const mathfont = isMathFont(mi.base.fontname);
|
||||
if (mathfont && subst_) {
|
||||
string const & f = mi.base.fontname;
|
||||
if (isMathFont(f) && 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") {
|
||||
} else if (!slanted(char_) && f == "mathnormal") {
|
||||
Changer dummy = mi.base.font.changeShape(UP_SHAPE);
|
||||
dim = theFontMetrics(mi.base.font).dimension(char_);
|
||||
kerning_ = 0;
|
||||
} else {
|
||||
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
|
||||
dim = fm.dimension(char_);
|
||||
kerning_ = fm.rbearing(char_) - dim.wid;
|
||||
kerning_ = mathed_char_kerning(mi.base.font, char_);
|
||||
// cmmi has almost no left bearing: simulate this
|
||||
if (f == "mathnormal") {
|
||||
dim.wid += max(-fm.lbearing(char_), 0);
|
||||
}
|
||||
// Rule 17 from Appendix G
|
||||
// These are the fonts with fontdimen(2)==0.
|
||||
// To properly handle the case fontdimen(2)!=0 (that is for all other
|
||||
// math fonts), where the italic correction must also be converted into
|
||||
// kerning but only at the end of strings of characters with the same
|
||||
// font, one would need a more elaborate implementation in MathRow. For
|
||||
// now the case fontdimen(2)==0 is the most important.
|
||||
if (f == "mathnormal" || f == "mathscr" || f == "mathcal") {
|
||||
dim.wid += kerning_;
|
||||
// We use a negative value to tell InsetMathScript to move the
|
||||
// subscript leftwards instead of the superscript rightwards
|
||||
kerning_ = -kerning_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +160,10 @@ void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
|
||||
return;
|
||||
}
|
||||
}
|
||||
// cmmi has almost no left bearing: simulate this
|
||||
if (pi.base.fontname == "mathnormal") {
|
||||
x += max(-theFontMetrics(pi.base.font).lbearing(char_), 0);
|
||||
}
|
||||
pi.draw(x, y, char_);
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,8 @@ int InsetMathScript::dx0(BufferView const & bv) const
|
||||
{
|
||||
LASSERT(hasDown(), return 0);
|
||||
Dimension const dim = dimension(bv);
|
||||
return hasLimits() ? (dim.wid - down().dimension(bv).width()) / 2 : nwid(bv);
|
||||
return hasLimits() ? (dim.wid - down().dimension(bv).width()) / 2
|
||||
: nwid(bv) + min(nker(&bv), 0);
|
||||
}
|
||||
|
||||
|
||||
@ -234,7 +235,8 @@ int InsetMathScript::dx1(BufferView const & bv) const
|
||||
{
|
||||
LASSERT(hasUp(), return 0);
|
||||
Dimension const dim = dimension(bv);
|
||||
return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2 : nwid(bv) + nker(&bv);
|
||||
return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2
|
||||
: nwid(bv) + max(nker(&bv), 0);
|
||||
}
|
||||
|
||||
|
||||
@ -265,10 +267,8 @@ int InsetMathScript::ndes(BufferView const & bv) const
|
||||
|
||||
int InsetMathScript::nker(BufferView const * bv) const
|
||||
{
|
||||
if (!nuc().empty()) {
|
||||
int kerning = nuc().kerning(bv);
|
||||
return kerning > 0 ? kerning : 0;
|
||||
}
|
||||
if (!nuc().empty())
|
||||
return nuc().kerning(bv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -320,9 +320,9 @@ void InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
dim.wid = max(dim.wid, dimdown.width());
|
||||
} else {
|
||||
if (hasUp())
|
||||
dim.wid = max(dim.wid, nker(mi.base.bv) + dimup.width());
|
||||
dim.wid = max(dim.wid, max(nker(mi.base.bv), 0) + dimup.width());
|
||||
if (hasDown())
|
||||
dim.wid = max(dim.wid, dimdown.width());
|
||||
dim.wid = max(dim.wid, min(nker(mi.base.bv), 0) + dimdown.width());
|
||||
dim.wid += nwid(bv);
|
||||
}
|
||||
int na = nasc(bv);
|
||||
|
@ -135,7 +135,10 @@ private:
|
||||
int nasc(BufferView const &) const;
|
||||
/// returns descent of nucleus if any
|
||||
int ndes(BufferView const &) const;
|
||||
/// returns superscript kerning of nucleus if any
|
||||
/// Italic correction: amount of displacement between subscript and
|
||||
/// superscript in math mode as per Appendix G, rule 18f. A positive value
|
||||
/// shifts the superscript to the right, and a negative value shifts the
|
||||
/// subscript to the left.
|
||||
int nker(BufferView const * bv) const;
|
||||
/// where do we have to draw the scripts?
|
||||
bool hasLimits() const;
|
||||
|
@ -104,7 +104,7 @@ private:
|
||||
int nasc(BufferView const &) const;
|
||||
/// returns descent of nucleus if any
|
||||
int ndes(BufferView const &) const;
|
||||
/// returns subscript and superscript kerning of nucleus if any
|
||||
/// Italic correction as described in InsetMathScript.h
|
||||
int nker(BufferView const * bv) const;
|
||||
/// Whether there are two left scripts or one single cell
|
||||
bool scriptl_;
|
||||
|
@ -61,7 +61,7 @@ void InsetMathSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
} else {
|
||||
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
|
||||
dim = fm.dimension(char_);
|
||||
kerning_ = fm.rbearing(char_) - dim.wid;
|
||||
kerning_ = mathed_char_kerning(mi.base.font, char_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ public:
|
||||
int slevel() const { return slevel_; }
|
||||
/// additional super/subscript shift
|
||||
int sshift() const { return sshift_; }
|
||||
/// superscript kerning
|
||||
/// Italic correction as described in InsetMathScript.h
|
||||
int kerning(BufferView const *) const { return kerning_; }
|
||||
///
|
||||
void swap(MathData & ar) { base_type::swap(ar); }
|
||||
|
@ -556,7 +556,7 @@ 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));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user