With the attached patch LyX correctly positions superscripts accounting for the real width of the nucleus. I also attach two screenshots showing a formula before and after the patch.
I'll commit it tomorrow if I don't get objections. I will also address caching of the right bearings later. -- Enrico
Index: src/mathed/InsetMathScript.C =================================================================== --- src/mathed/InsetMathScript.C (revision 17487) +++ src/mathed/InsetMathScript.C (working copy) @@ -225,7 +225,7 @@ int InsetMathScript::dx0() const int InsetMathScript::dx1() const { BOOST_ASSERT(hasUp()); - return hasLimits() ? (dim_.wid - up().width()) / 2 : nwid(); + return hasLimits() ? (dim_.wid - up().width()) / 2 : nwid() + nker(); } @@ -253,6 +253,16 @@ int InsetMathScript::ndes() const } +int InsetMathScript::nker() const +{ + if (nuc().size()) { + int kerning = nuc().kerning(); + return kerning > 0 ? kerning : 0; + } + return 0; +} + + bool InsetMathScript::metrics(MetricsInfo & mi, Dimension & dim) const { cell(0).metrics(mi); @@ -270,7 +280,7 @@ bool InsetMathScript::metrics(MetricsInf dim.wid = max(dim.wid, down().width()); } else { if (hasUp()) - dim.wid = max(dim.wid, up().width()); + dim.wid = max(dim.wid, nker() + up().width()); if (hasDown()) dim.wid = max(dim.wid, down().width()); dim.wid += nwid(); Index: src/mathed/MathData.C =================================================================== --- src/mathed/MathData.C (revision 17487) +++ src/mathed/MathData.C (working copy) @@ -282,6 +282,8 @@ void MathArray::metrics(MetricsInfo & mi #endif at->metrics(mi, d); dim_ += d; + if (i == n - 1) + kerning_ = at->kerning(); } } Index: src/mathed/InsetMathChar.h =================================================================== --- src/mathed/InsetMathChar.h (revision 17487) +++ src/mathed/InsetMathChar.h (working copy) @@ -32,6 +32,8 @@ public: void drawT(TextPainter &, int x, int y) const; /// int width() const { return width_; } + /// + int kerning() const { return kerning_; } /// void write(WriteStream & os) const; @@ -54,6 +56,8 @@ private: char_type char_; /// cached width mutable int width_; + /// cached kerning for superscript + mutable int kerning_; }; } // namespace lyx Index: src/mathed/InsetMathScript.h =================================================================== --- src/mathed/InsetMathScript.h (revision 17487) +++ src/mathed/InsetMathScript.h (working copy) @@ -124,6 +124,8 @@ private: int nasc() const; /// returns descent of nucleus if any int ndes() const; + /// returns superscript kerning of nucleus if any + int nker() const; /// where do we have to draw the scripts? bool hasLimits() const; /// clean up empty cells and return true if a cell has been deleted. Index: src/mathed/MathSupport.C =================================================================== --- src/mathed/MathSupport.C (revision 17487) +++ src/mathed/MathSupport.C (working copy) @@ -373,6 +373,13 @@ int mathed_char_width(LyXFont const & fo } +int mathed_char_kerning(LyXFont const & font, char_type c) +{ + frontend::FontMetrics const & fm = theFontMetrics(font); + return fm.rbearing(c) - fm.width(c); +} + + void mathed_string_dim(LyXFont const & font, docstring const & s, Dimension & dim) Index: src/mathed/MathData.h =================================================================== --- src/mathed/MathData.h (revision 17487) +++ src/mathed/MathData.h (working copy) @@ -158,6 +158,8 @@ public: int slevel() const { return slevel_; } /// additional super/subscript shift int sshift() const { return sshift_; } + /// superscript kerning + int kerning() const { return kerning_; } protected: /// cached dimensions of cell @@ -167,6 +169,7 @@ protected: mutable int mindes_; mutable int slevel_; mutable int sshift_; + mutable int kerning_; private: /// is this an exact match at this position? Index: src/mathed/MathSupport.h =================================================================== --- src/mathed/MathSupport.h (revision 17487) +++ src/mathed/MathSupport.h (working copy) @@ -30,6 +30,8 @@ class InsetMath; int mathed_char_width(LyXFont const &, char_type c); +int mathed_char_kerning(LyXFont const &, char_type c); + void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h, docstring const & name); Index: src/mathed/InsetMath.h =================================================================== --- src/mathed/InsetMath.h (revision 17487) +++ src/mathed/InsetMath.h (working copy) @@ -200,6 +200,9 @@ public: /// math stuff usually isn't allowed in text mode virtual bool allowedIn(mode_type mode) const { return mode == MATH_MODE; } + + /// superscript kerning + virtual int kerning() const { return 0; } }; /// Index: src/mathed/InsetMathSymbol.C =================================================================== --- src/mathed/InsetMathSymbol.C (revision 17487) +++ src/mathed/InsetMathSymbol.C (working copy) @@ -64,6 +64,8 @@ bool InsetMathSymbol::metrics(MetricsInf int const em = mathed_char_width(mi.base.font, 'M'); FontSetChanger dummy(mi.base, sym_->inset); 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); // correct height for broken cmex and wasy font if (sym_->inset == "cmex" || sym_->inset == "wasy") { h_ = 4 * dim.des / 5; Index: src/mathed/InsetMathSymbol.h =================================================================== --- src/mathed/InsetMathSymbol.h (revision 17487) +++ src/mathed/InsetMathSymbol.h (working copy) @@ -37,6 +37,8 @@ public: void draw(PainterInfo &, int x, int y) const; /// int width() const { return width_; } + /// + int kerning() const { return kerning_; } /// bool isRelOp() const; @@ -76,6 +78,8 @@ private: mutable int h_; /// cached width mutable int width_; + /// cached superscript kerning + mutable int kerning_; /// mutable bool scriptable_; }; Index: src/mathed/InsetMathFont.h =================================================================== --- src/mathed/InsetMathFont.h (revision 17487) +++ src/mathed/InsetMathFont.h (working copy) @@ -45,6 +45,8 @@ public: void validate(LaTeXFeatures & features) const; /// void infoize(odocstream & os) const; + /// + int kerning() const { return cell(0).kerning(); } private: virtual std::auto_ptr<InsetBase> doClone() const; Index: src/mathed/InsetMathChar.C =================================================================== --- src/mathed/InsetMathChar.C (revision 17487) +++ src/mathed/InsetMathChar.C (working copy) @@ -46,7 +46,7 @@ namespace { InsetMathChar::InsetMathChar(char_type c) - : char_(c) + : char_(c), kerning_(0) {} @@ -70,7 +70,9 @@ bool InsetMathChar::metrics(MetricsInfo ShapeChanger dummy(mi.base.font, LyXFont::UP_SHAPE); dim = theFontMetrics(mi.base.font).dimension(char_); } else { - dim = theFontMetrics(mi.base.font).dimension(char_); + 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_))
before.png
Description: PNG image
after.png
Description: PNG image