File: RowAtom.java

package info (click to toggle)
libjmathtex-java 0.7~pre-4
  • links: PTS, VCS
  • area: main
  • in suites: lenny, squeeze
  • size: 952 kB
  • ctags: 1,112
  • sloc: java: 5,129; xml: 2,151; makefile: 24
file content (221 lines) | stat: -rw-r--r-- 8,302 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/* RowAtom.java
 * =========================================================================
 * This file is part of the JMathTeX Library - http://jmathtex.sourceforge.net
 *
 * Copyright (C) 2004-2007 Universiteit Gent
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * A copy of the GNU General Public License can be found in the file
 * LICENSE.txt provided with the source distribution of this program (see
 * the META-INF directory in the source jar). This license can also be
 * found on the GNU website at http://www.gnu.org/licenses/gpl.html.
 *
 * If you did not receive a copy of the GNU General Public License along
 * with this program, contact the lead developer, or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 */

package be.ugent.caagt.jmathtex;

import java.util.BitSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * An atom representing a horizontal row of other atoms, to be seperated by glue.
 * It's also responsible for inserting kerns and ligatures.
 */
class RowAtom extends Atom implements Row {
    
    // atoms to be displayed horizontally next to eachother
    protected List<Atom> elements = new LinkedList<Atom>();
    
    // previous atom (for nested Row atoms)
    private Dummy previousAtom = null;
    
    // set of atom types that make a previous bin atom change to ord
    private static BitSet binSet;
    
    // set of atom types that can possibly need a kern or, together with the
    // previous atom, be replaced by a ligature
    private static BitSet ligKernSet;
    
    static {
        // fill binSet
        binSet = new BitSet (16);
        binSet.set(TeXConstants.TYPE_BINARY_OPERATOR);
        binSet.set(TeXConstants.TYPE_BIG_OPERATOR);
        binSet.set(TeXConstants.TYPE_RELATION);
        binSet.set(TeXConstants.TYPE_OPENING);
        binSet.set(TeXConstants.TYPE_PUNCTUATION);
        
        // fill ligKernSet
        ligKernSet = new BitSet (16);
        ligKernSet.set(TeXConstants.TYPE_ORDINARY);
        ligKernSet.set(TeXConstants.TYPE_BIG_OPERATOR);
        ligKernSet.set(TeXConstants.TYPE_BINARY_OPERATOR);
        ligKernSet.set(TeXConstants.TYPE_RELATION);
        ligKernSet.set(TeXConstants.TYPE_OPENING);
        ligKernSet.set(TeXConstants.TYPE_CLOSING);
        ligKernSet.set(TeXConstants.TYPE_PUNCTUATION);
    }
    
    protected RowAtom() {
        // empty
    }
    
    public RowAtom(Atom el) {
        if (el != null) {
            if (el instanceof RowAtom)
                // no need to make an mrow the only element of an mrow
                elements.addAll(((RowAtom) el).elements);
            else
                elements.add(el);
        }
    }
    
    /**
     * Only used while parsing MathML. An empty Mrow is not allowed, otherwise
     * it's possible to create fractions with an empty numerator or denominator.
     *
     * @param l
     *           list of objects of the type Formula
     * @throws EmptyFormulaException
     */
    public RowAtom(List<TeXFormula> l) throws EmptyFormulaException {
        for (TeXFormula f : l) {
            if (f.root != null)
                elements.add(f.root);
        }
        if (elements.isEmpty())
            throw new EmptyFormulaException();
    }
    
    public final void add(Atom el) {
        if (el != null)
            elements.add(el);
    }
    
    /**
     *
     * @param cur
     *           current atom being processed
     * @param prev
     *           previous atom
     */
    private void changeToOrd(Dummy cur, Dummy prev, Atom next) {
        int type = cur.getLeftType();
        if (type == TeXConstants.TYPE_BINARY_OPERATOR
                && (prev == null || binSet.get(prev.getRightType())))
            cur.setType(TeXConstants.TYPE_ORDINARY);
        else if (next != null
                && cur.getRightType() == TeXConstants.TYPE_BINARY_OPERATOR) {
            int nextType = next.getLeftType();
            if (nextType == TeXConstants.TYPE_RELATION
                    || nextType == TeXConstants.TYPE_CLOSING
                    || nextType == TeXConstants.TYPE_PUNCTUATION)
                cur.setType(TeXConstants.TYPE_ORDINARY);
        }
    }
    
    public Box createBox(TeXEnvironment env) {
        TeXFont tf = env.getTeXFont();
        HorizontalBox hBox = new HorizontalBox(env.getColor(), env
                .getBackground());
        env.reset();
        
        // convert atoms to boxes and add to the horizontal box
        for (ListIterator it = elements.listIterator(); it.hasNext();) {
            Dummy atom = new Dummy((Atom) it.next());
            
            // if necessary, change BIN type to ORD
            Atom nextAtom = null;
            if (it.hasNext()) {
                nextAtom = (Atom) it.next();
                it.previous();
            }
            changeToOrd(atom, previousAtom, nextAtom);
            
            // check for ligatures or kerning
            float kern = 0;
            if (it.hasNext() && atom.getRightType() == TeXConstants.TYPE_ORDINARY
                    && atom.isCharSymbol()) {
                Atom next = (Atom) it.next();
                if (next instanceof CharSymbol
                        && ligKernSet.get(next.getLeftType())) {
                    atom.markAsTextSymbol();
                    CharFont l = atom.getCharFont(tf), r = ((CharSymbol) next)
                    .getCharFont(tf);
                    CharFont lig = tf.getLigature(l, r);
                    if (lig == null) {
                        kern = tf.getKern(l, r, env.getStyle());
                        it.previous(); // iterator remains unchanged (no ligature!)
                    } 
                    else { // ligature
                        atom.changeAtom(new FixedCharAtom(lig)); // go on with the
                        // ligature
                    }
                } else
                    it.previous();// iterator remains unchanged
            }
            
            // insert glue, unless it's the first element of the row
            // OR this element or the next is a Kern.
            if (it.previousIndex() != 0 && previousAtom != null
                    && !previousAtom.isKern() && !atom.isKern())
                hBox.add(Glue.get(previousAtom.getRightType(), atom.getLeftType(),
                        env));
            
            // insert atom's box
            atom.setPreviousAtom(previousAtom);
            Box b = atom.createBox(env);
            hBox.add(b);
            
            // set last used fontId (for next atom)
            env.setLastFontId(b.getLastFontId());
            
            // insert kern
            if (kern > TeXFormula.PREC)
                hBox.add(new StrutBox(0, kern, 0, 0));
            
            // kerns do not interfere with the normal glue-rules without kerns
            if (!atom.isKern())
                previousAtom = atom;
        }
        // reset previousAtom
        previousAtom = null;
        
        // return resulting horizontal box
        return hBox;
    }
    
    public void setPreviousAtom(Dummy prev) {
        previousAtom = prev;
    }
    
    public int getLeftType() {
        if (elements.isEmpty())
            return TeXConstants.TYPE_ORDINARY;
        else
            return ((Atom) elements.get(0)).getLeftType();
    }
    
    public int getRightType() {
        if (elements.isEmpty())
            return TeXConstants.TYPE_ORDINARY;
        else
            return ((Atom) elements.get(elements.size() - 1)).getRightType();
    }
}