Implement computation of spacing according to the TeXBook

This implements the relevant math typography rules described in the
Appendix G of the TeXbook. More precisely, for each atom

  + the class is computed by implementing rules 5 and 6 of Appendix G

  + the spacing is computed according to the table p. 170

This code is not used at this point.
This commit is contained in:
Jean-Marc Lasgouttes 2016-08-22 14:15:28 +02:00
parent 361bd53bc3
commit f6df4e7985
3 changed files with 106 additions and 0 deletions

View File

@ -11,10 +11,17 @@
#include <config.h>
#include "MathClass.h"
#include "MathSupport.h"
#include "MetricsInfo.h"
#include "FontInfo.h"
#include "support/debug.h"
#include "support/docstring.h"
#include "support/lassert.h"
#include <ostream>
using namespace std;
namespace lyx {
@ -79,4 +86,95 @@ MathClass string_to_class(docstring const &s)
}
/*
* The TeXbook presents in Appendix G a set of 22 rules (!) explaining
* how to typeset mathematic formulas. Of interest here are rules 5
* and 6:
* 5. If the current item is a Bin atom, and if this was the first
* atom in the list, or if the most recent previous atom was Bin,
* Op, Rel, Open, or Punct, change the current Bin to Ord [and
* continue with Rule 14. Otherwise continue with Rule 17]
*
* 6. If the current item is a Rel or Close or Punct atom, and if the
* most recent previous atom was Bin, change that previous Bin to
* Ord. [Continue with Rule 17.]
*/
void update_class(MathClass & mc, MathClass const prev, MathClass const next)
{
if (mc == MC_BIN
&& (prev == MC_BIN || prev == MC_OP || prev == MC_OPEN
|| prev == MC_PUNCT || prev == MC_REL
|| next == MC_CLOSE || next == MC_PUNCT || next == MC_REL))
mc = MC_ORD;
}
/*
* This table of spacing between two classes can be found p. 170 of
* The TeXbook.
*
* The line is the class of the first class, and the column the second
* class. The number encodes the spacing between the two atoms, as
* follows
*
* + 0: no spacing
* + 1: thin mu skip
* + 2: med mu skip
* + 3: thick mu skip
* + 9: should never happen
* + negative value: either 0 if the atom is in script or scriptscript mode,
* or the spacing given by the absolute value.
*/
int pair_spc[MC_UNKNOWN][MC_UNKNOWN] = {
// ORD OP BIN REL OPEN CLOSE PUNCT INNER
{ 0, 1, -2, -3, 0, 0, 0, -1}, // ORD
{ 1, 1, 9, -3, 0, 0, 0, -1}, // OP
{ -2, -2, 9, 9, -2, 9, 9, -2}, // BIN
{ -3, -3, 9, 0, -3, 0, 0, -3}, // REL
{ 0, 0, 9, 0, 0, 0, 0, 0}, // OPEN
{ 0, 1, -2, -3, 0, 0, 0, -1}, // CLOSE
{ -1, -1, 9, -1, -1, -1, -1, -1}, // PUNCT
{ -1, 1, -2, -3, -1, 0, -1, -1}, // INNER
};
int class_spacing(MathClass const mc1, MathClass const mc2,
MetricsBase const & mb)
{
int spc_code = pair_spc[mc1][mc2];
//lyxerr << class_to_string(mc1) << "+" << class_to_string(mc2)
// << "=" << spc_code << " @" << mb.style << endl;
if (spc_code < 0) {
switch (mb.style) {
case LM_ST_DISPLAY:
case LM_ST_TEXT:
spc_code = abs(spc_code);
break;
case LM_ST_SCRIPT:
case LM_ST_SCRIPTSCRIPT:
spc_code = 0;
}
}
int spc = 0;
switch(spc_code) {
case 0:
break;
case 1:
spc = mathed_thinmuskip(mb.font);
break;
case 2:
spc = mathed_medmuskip(mb.font);
break;
case 3:
spc = mathed_thickmuskip(mb.font);
break;
default:
LYXERR0("Impossible pair of classes: (" << mc1 << ", " << mc2 << ")");
LATTEST(false);
}
return spc;
}
} // namespace lyx

View File

@ -16,6 +16,7 @@
namespace lyx {
class MetricsBase;
/* The TeXbook, p. 158:
*
@ -58,6 +59,10 @@ MathClass string_to_class(docstring const &);
docstring const class_to_string(MathClass);
void update_class(MathClass & mc, MathClass const prev, MathClass const next);
int class_spacing(MathClass const mc1, MathClass const mc2,
MetricsBase const & mb);
} // namespace lyx

View File

@ -528,6 +528,9 @@ int mathed_font_em(FontInfo const & font)
* 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.
*
* See the file MathClass.cpp for a formal implementation of the rules
* above.
*/
int mathed_thinmuskip(FontInfo font)