]> git.lyx.org Git - features.git/commitdiff
Cleanup of spacing in mathed
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Tue, 24 May 2016 10:08:24 +0000 (12:08 +0200)
committerRichard Heck <rgheck@lyx.org>
Sun, 29 May 2016 21:55:55 +0000 (17:55 -0400)
This is a first cleanup step. More complex rules have to be
implemented on top of this.

Use proper spacing \thinmuskip, \medmuskip and \thickmuskip instead of
ad-hoc values.

Rename isRelOp to isMathRel and introduce isMathBin and isMathPunct
(for InsetMathChar and InsetMathSymbol). Update the categories of
characters in InsetMathChar according to LaTeX source (fontmath.ltx).

Set correctly the spacing around mathrel, mathbin and mathpunct
elements. Use \thinmuskip around MathDelim instead of a hardcoded 4.

This is related to bug #8883.

src/mathed/InsetMath.h
src/mathed/InsetMathChar.cpp
src/mathed/InsetMathChar.h
src/mathed/InsetMathDelim.cpp
src/mathed/InsetMathHull.cpp
src/mathed/InsetMathSymbol.cpp
src/mathed/InsetMathSymbol.h
src/mathed/MathSupport.cpp
src/mathed/MathSupport.h

index b23ffb5179e1ef542352e49673ded594d5710a86..088fce6c2be97a281bf32112be25ebf8fbf1cffb 100644 (file)
@@ -162,8 +162,12 @@ public:
 
        /// identifies things that can get scripts
        virtual bool isScriptable() const { return false; }
-       /// is the a relational operator (used for splitting equations)
-       virtual bool isRelOp() const { return false; }
+       /// identifies a binary operators (used for spacing)
+       virtual bool isMathBin() const { return false; }
+       /// identifies relational operators (used for spacing and splitting equations)
+       virtual bool isMathRel() const { return false; }
+       /// identifies punctuation (used for spacing)
+       virtual bool isMathPunct() const { return false; }
        /// will this get written as a single block in {..}
        virtual bool extraBraces() const { return false; }
 
index 713e1353e683ee9cff9460285b0cc7e8e36e1afa..2879ac91fccf9a442f70ca07adc63f4052370e4d 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "support/debug.h"
 #include "support/lstrings.h"
-#include "support/lyxlib.h"
 #include "support/textutils.h"
 
 
@@ -35,12 +34,6 @@ namespace lyx {
 extern bool has_math_fonts;
 
 
-static bool isBinaryOp(char_type c)
-{
-       return support::contains("+-<>=/*", static_cast<char>(c));
-}
-
-
 static bool slanted(char_type c)
 {
        return isAlphaASCII(c) || Encodings::isMathAlpha(c);
@@ -76,11 +69,15 @@ void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
                dim = fm.dimension(char_);
                kerning_ = fm.rbearing(char_) - dim.wid;
        }
-       int const em = mathed_font_em(mi.base.font);
-       if (isBinaryOp(char_))
-               dim.wid += support::iround(0.5 * em);
+       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);
        else if (char_ == '\'')
-               dim.wid += support::iround(0.1667 * em);
+               // 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_);
@@ -94,11 +91,12 @@ void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
 void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
 {
        //lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << std::endl;
-       int const em = mathed_font_em(pi.base.font);
-       if (isBinaryOp(char_))
-               x += support::iround(0.25 * em);
+       if (isMathBin())
+               x += mathed_medmuskip(pi.base.font);
+       else if (isMathRel())
+               x += mathed_thickmuskip(pi.base.font);
        else if (char_ == '\'')
-               x += support::iround(0.0833 * em);
+               x += mathed_thinmuskip(pi.base.font) / 2;
 #if 1
        if (char_ == '=' && has_math_fonts) {
                FontSetChanger dummy(pi.base, "cmr");
@@ -237,9 +235,21 @@ void InsetMathChar::htmlize(HtmlStream & ms) const
 }
 
 
-bool InsetMathChar::isRelOp() const
+bool InsetMathChar::isMathBin() const
+{
+       return support::contains("+-*", static_cast<char>(char_));
+}
+
+
+bool InsetMathChar::isMathRel() const
+{
+       return support::contains("<>=:", static_cast<char>(char_));
+}
+
+
+bool InsetMathChar::isMathPunct() const
 {
-       return char_ == '=' || char_ == '<' || char_ == '>';
+       return support::contains(",;", static_cast<char>(char_));
 }
 
 
index 65fac82fffb04c5067ebec2c0d4beb7f9e793068..67bbc64e8c866fc345bd9042bc12fa1ebf897971 100644 (file)
@@ -49,7 +49,11 @@ public:
        ///
        char_type getChar() const { return char_; }
        ///
-       bool isRelOp() const;
+       bool isMathBin() const;
+       ///
+       bool isMathRel() const;
+       ///
+       bool isMathPunct() const;
        ///
        InsetCode lyxCode() const { return MATH_CHAR_CODE; }
 
index 8e8b6e295bad9672f493a258cf16e206fa77a5ed..b10d37ad698b81e0048dd5c2961fd5d5c3aadb15 100644 (file)
@@ -115,7 +115,7 @@ void InsetMathDelim::metrics(MetricsInfo & mi, Dimension & dim) const
                dw_ = 8;
        if (dw_ < 4)
                dw_ = 4;
-       dim.wid = dim0.width() + 2 * dw_ + 8;
+       dim.wid = dim0.width() + 2 * dw_ + 2 * mathed_thinmuskip(mi.base.font);
        dim.asc = max(a0, d0) + h0;
        dim.des = max(a0, d0) - h0;
 }
@@ -125,9 +125,10 @@ void InsetMathDelim::draw(PainterInfo & pi, int x, int y) const
 {
        Dimension const dim = dimension(*pi.base.bv);
        int const b = y - dim.asc;
-       cell(0).draw(pi, x + dw_ + 4, y);
-       mathed_draw_deco(pi, x + 4, b, dw_, dim.height(), left_);
-       mathed_draw_deco(pi, x + dim.width() - dw_ - 4,
+       int const skip = mathed_thinmuskip(pi.base.font);
+       cell(0).draw(pi, x + dw_ + skip, y);
+       mathed_draw_deco(pi, x + skip, b, dw_, dim.height(), left_);
+       mathed_draw_deco(pi, x + dim.width() - dw_ - skip,
                b, dw_, dim.height(), right_);
        setPosCache(pi, x, y);
 }
index 48792a81ae8b090a256dec55e0febac309498dfd..34955147e260e3ef3a7f674de0473ee237c6ac4a 100644 (file)
@@ -106,7 +106,7 @@ namespace {
        size_t firstRelOp(MathData const & ar)
        {
                for (MathData::const_iterator it = ar.begin(); it != ar.end(); ++it)
-                       if ((*it)->isRelOp())
+                       if ((*it)->isMathRel())
                                return it - ar.begin();
                return ar.size();
        }
index a160dec684883a5cb31f099b6b9615130cd5ed76..a04f6e0bcf7bed47bd99dd7593ed81854d00591f 100644 (file)
@@ -21,7 +21,6 @@
 
 #include "support/debug.h"
 #include "support/docstream.h"
-#include "support/lyxlib.h"
 #include "support/textutils.h"
 
 #include <boost/scoped_ptr.hpp>
@@ -68,7 +67,6 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
                                         sym_->extra == "mathalpha" &&
                                         mi.base.fontname == "mathit";
        std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
-       int const em = mathed_font_em(mi.base.font);
        FontSetChanger dummy(mi.base, from_ascii(font));
        mathed_string_dim(mi.base.font, sym_->draw, dim);
        docstring::const_reverse_iterator rit = sym_->draw.rbegin();
@@ -80,10 +78,15 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
                dim.des -= h_;
        }
        // seperate things a bit
-       if (isRelOp())
-               dim.wid += support::iround(0.5 * em);
-       else
-               dim.wid += support::iround(0.1667 * em);
+       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);
 
        scriptable_ = false;
        if (mi.base.style == LM_ST_DISPLAY)
@@ -105,11 +108,13 @@ void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
                                         sym_->extra == "mathalpha" &&
                                         pi.base.fontname == "mathit";
        std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
-       int const em = mathed_font_em(pi.base.font);
-       if (isRelOp())
-               x += support::iround(0.25 * em);
-       else
-               x += support::iround(0.0833 * em);
+       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);
 
        FontSetChanger dummy(pi.base, from_ascii(font));
        pi.draw(x, y - h_, sym_->draw);
@@ -122,12 +127,24 @@ InsetMath::mode_type InsetMathSymbol::currentMode() const
 }
 
 
-bool InsetMathSymbol::isRelOp() const
+bool InsetMathSymbol::isMathBin() const
+{
+       return sym_->extra == "mathbin";
+}
+
+
+bool InsetMathSymbol::isMathRel() const
 {
        return sym_->extra == "mathrel";
 }
 
 
+bool InsetMathSymbol::isMathPunct() const
+{
+       return sym_->extra == "mathpunct";
+}
+
+
 bool InsetMathSymbol::isOrdAlpha() const
 {
        return sym_->extra == "mathord" || sym_->extra == "mathalpha";
index bb18217a8416dbd9b112e84bbd4ea539760dfdef..6ca3ded7d1bbd0df864326e00305184a0c823caf 100644 (file)
@@ -40,7 +40,11 @@ public:
        ///
        mode_type currentMode() const;
        ///
-       bool isRelOp() const;
+       bool isMathRel() const;
+       ///
+       bool isMathBin() const;
+       ///
+       bool isMathPunct() const;
        ///
        bool isOrdAlpha() const;
        /// do we take scripts?
index 9801151129454530d7dd48141f7cf2e5ba0411d9..7769176e7aad403c6733d86c51bda8f1a4283a38 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "support/debug.h"
 #include "support/docstream.h"
+#include "support/lyxlib.h"
 
 #include <map>
 #include <algorithm>
@@ -506,6 +507,46 @@ int mathed_font_em(FontInfo const & font)
        return theFontMetrics(font).em();
 }
 
+/* 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.
+ */
+
+int mathed_thinmuskip(FontInfo font)
+{
+       font.setFamily(SYMBOL_FAMILY);
+       return support::iround(3.0 / 18 * theFontMetrics(font).em());
+}
+
+
+int mathed_medmuskip(FontInfo font)
+{
+       font.setFamily(SYMBOL_FAMILY);
+       return support::iround(4.0 / 18 * theFontMetrics(font).em());
+}
+
+
+int mathed_thickmuskip(FontInfo font)
+{
+       font.setFamily(SYMBOL_FAMILY);
+       return support::iround(5.0 / 18 * theFontMetrics(font).em());
+}
+
 
 int mathed_char_width(FontInfo const & font, char_type c)
 {
index aa5ef2adc2a56f7de8e43364a47c8394551004f9..c14f21a807b21d83b149720c5c8fba6849ef956e 100644 (file)
@@ -29,6 +29,12 @@ class InsetMath;
 
 int mathed_font_em(FontInfo const &);
 
+int mathed_thinmuskip(FontInfo font);
+
+int mathed_medmuskip(FontInfo font);
+
+int mathed_thickmuskip(FontInfo font);
+
 int mathed_char_width(FontInfo const &, char_type c);
 
 int mathed_char_kerning(FontInfo const &, char_type c);