1 /**
2 * \file MathClass.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
5 *
6 * \author Jean-Marc Lasgouttes
7 *
8 * Full author contact details are available in file CREDITS.
9 */
10
11 #include <config.h>
12
13 #include "MathClass.h"
14 #include "MathSupport.h"
15
16 #include "MetricsInfo.h"
17 #include "FontInfo.h"
18
19 #include "support/debug.h"
20 #include "support/docstring.h"
21 #include "support/lassert.h"
22
23 #include <ostream>
24
25 using namespace std;
26
27 namespace lyx {
28
29
class_to_string(MathClass const mc)30 docstring const class_to_string(MathClass const mc)
31 {
32 string s;
33 switch (mc) {
34 case MC_ORD:
35 s = "mathord";
36 break;
37 case MC_OP:
38 s = "mathop";
39 break;
40 case MC_BIN:
41 s = "mathbin";
42 break;
43 case MC_REL:
44 s = "mathrel";
45 break;
46 case MC_OPEN:
47 s = "mathopen";
48 break;
49 case MC_CLOSE:
50 s = "mathclose";
51 break;
52 case MC_PUNCT:
53 s = "mathpunct";
54 break;
55 case MC_INNER:
56 s = "mathinner";
57 break;
58 case MC_UNKNOWN:
59 LATTEST(false);
60 s = "mathord";
61 }
62 return from_ascii(s);
63 }
64
65
string_to_class(docstring const & s)66 MathClass string_to_class(docstring const &s)
67 {
68 if (s == "mathop")
69 return MC_OP;
70 else if (s == "mathbin")
71 return MC_BIN;
72 else if (s == "mathrel")
73 return MC_REL;
74 else if (s == "mathopen")
75 return MC_OPEN;
76 else if (s == "mathclose")
77 return MC_CLOSE;
78 else if (s == "mathpunct")
79 return MC_PUNCT;
80 else if (s == "mathinner")
81 return MC_INNER;
82 else if (s == "mathord")
83 return MC_ORD;
84 else
85 return MC_UNKNOWN;
86 }
87
88
89 /*
90 * The TeXbook presents in Appendix G a set of 22 rules (!) explaining
91 * how to typeset mathematic formulas. Of interest here are rules 5
92 * and 6:
93
94 * 5. If the current item is a Bin atom, and if this was the first
95 * atom in the list, or if the most recent previous atom was Bin,
96 * Op, Rel, Open, or Punct, change the current Bin to Ord [and
97 * continue with Rule 14. Otherwise continue with Rule 17]
98 *
99 * 6. If the current item is a Rel or Close or Punct atom, and if the
100 * most recent previous atom was Bin, change that previous Bin to
101 * Ord. [Continue with Rule 17.]
102 */
update_class(MathClass & mc,MathClass const prev,MathClass const next)103 void update_class(MathClass & mc, MathClass const prev, MathClass const next)
104 {
105 if (mc == MC_BIN
106 && (prev == MC_BIN || prev == MC_OP || prev == MC_OPEN
107 || prev == MC_PUNCT || prev == MC_REL
108 || next == MC_CLOSE || next == MC_PUNCT || next == MC_REL))
109 mc = MC_ORD;
110 }
111
112
113 /*
114 * This table of spacing between two classes can be found p. 170 of
115 * The TeXbook.
116 *
117 * The line is the class of the first class, and the column the second
118 * class. The number encodes the spacing between the two atoms, as
119 * follows
120 *
121 * + 0: no spacing
122 * + 1: thin mu skip
123 * + 2: med mu skip
124 * + 3: thick mu skip
125 * + 9: should never happen
126 * + negative value: either 0 if the atom is in script or scriptscript mode,
127 * or the spacing given by the absolute value.
128 */
129 int pair_spc[MC_UNKNOWN][MC_UNKNOWN] = {
130 // ORD OP BIN REL OPEN CLOSE PUNCT INNER
131 { 0, 1, -2, -3, 0, 0, 0, -1}, // ORD
132 { 1, 1, 9, -3, 0, 0, 0, -1}, // OP
133 { -2, -2, 9, 9, -2, 9, 9, -2}, // BIN
134 { -3, -3, 9, 0, -3, 0, 0, -3}, // REL
135 { 0, 0, 9, 0, 0, 0, 0, 0}, // OPEN
136 { 0, 1, -2, -3, 0, 0, 0, -1}, // CLOSE
137 { -1, -1, 9, -1, -1, -1, -1, -1}, // PUNCT
138 { -1, 1, -2, -3, -1, 0, -1, -1}, // INNER
139 };
140
141
class_spacing(MathClass const mc1,MathClass const mc2,MetricsBase const & mb)142 int class_spacing(MathClass const mc1, MathClass const mc2,
143 MetricsBase const & mb)
144 {
145 int spc_code = pair_spc[mc1][mc2];
146 //lyxerr << class_to_string(mc1) << "+" << class_to_string(mc2)
147 // << "=" << spc_code << " @" << mb.style << endl;
148 if (spc_code < 0) {
149 switch (mb.font.style()) {
150 case LM_ST_DISPLAY:
151 case LM_ST_TEXT:
152 spc_code = abs(spc_code);
153 break;
154 case LM_ST_SCRIPT:
155 case LM_ST_SCRIPTSCRIPT:
156 spc_code = 0;
157 }
158 }
159
160 int spc = 0;
161 switch(spc_code) {
162 case 0:
163 break;
164 case 1:
165 spc = mathed_thinmuskip(mb.font);
166 break;
167 case 2:
168 spc = mathed_medmuskip(mb.font);
169 break;
170 case 3:
171 spc = mathed_thickmuskip(mb.font);
172 break;
173 default:
174 LYXERR0("Impossible pair of classes: (" << mc1 << ", " << mc2 << ")");
175 LATTEST(false);
176 }
177 return spc;
178 }
179
180 } // namespace lyx
181