File: FractionAtom.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 (271 lines) | stat: -rw-r--r-- 9,996 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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/* FractionAtom.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;

/**
 * An atom representing a fraction.
 */
class FractionAtom extends Atom {
    
    // whether the default thickness should not be used for the fraction line
    private boolean noDefault = false;
    
    // unit used for the thickness of the fraction line
    private int unit;
    
    // alignment settings for the numerator and denominator
    private int numAlign = TeXConstants.ALIGN_CENTER,
            denomAlign = TeXConstants.ALIGN_CENTER;
    
    // the atoms representing the numerator and denominator
    private Atom numerator, denominator;
    
    // thickness of the fraction line
    private float thickness;
    
    // thickness of the fraction line relative to the default thickness
    private float defFactor;
    
    // whether the "defFactor" value should be used
    private boolean defFactorSet = false;
    
    /**
     * Uses the default thickness for the fraction line
     *
     * @param num the numerator
     * @param den the denominator
     */
    public FractionAtom(Atom num, Atom den) {
        this(num, den, true);
    }
    
    /**
     * Uses the default thickness for the fraction line
     *
     * @param num the numerator
     * @param den the denominator
     * @param rule whether the fraction line should be drawn
     */
    public FractionAtom(Atom num, Atom den, boolean rule) {
        this(num, den, !rule, TeXConstants.UNIT_PIXEL, 0f);
    }
    
    /**
     * Depending on noDef, the given thickness and unit will be used (<-> the default
     * thickness).
     *
     * @param num the numerator
     * @param den the denominator
     * @param noDef whether the default thickness should not be used for the fraction line
     * @param unit a unit constant for the line thickness
     * @param t the thickness of the fraction line (in the given unit)
     * @throws InvalidUnitException if the given integer is not a valid unit constant
     */
    public FractionAtom(Atom num, Atom den, boolean noDef, int unit, float t)
    throws InvalidUnitException {
        // check unit
        SpaceAtom.checkUnit(unit);
        
        // unit ok
        numerator = num;
        denominator = den;
        noDefault = noDef;
        thickness = t;
        this.unit = unit;
        type = TeXConstants.TYPE_INNER;
    }
    
    /**
     * Uses the default thickness for the fraction line.
     *
     * @param num the numerator
     * @param den the denominator
     * @param rule whether the fraction line should be drawn
     * @param numAlign alignment of the numerator
     * @param denomAlign alignment of the denominator
     */
    public FractionAtom(Atom num, Atom den, boolean rule, int numAlign,
            int denomAlign) {
        this(num, den, rule);
        this.numAlign = checkAlignment(numAlign);
        this.denomAlign = checkAlignment(denomAlign);
    }
    
    /**
     * The thickness of the fraction line will be "defFactor" times the default thickness.
     *
     * @param num the numerator
     * @param den the denominator
     * @param defFactor the thickness of the fraction line relative to the default thickness
     * @param numAlign alignment of the numerator
     * @param denomAlign alignment of the denominator
     */
    public FractionAtom(Atom num, Atom den, float defFactor, int numAlign,
            int denomAlign) {
        this(num, den, true, numAlign, denomAlign);
        this.defFactor = defFactor;
        defFactorSet = true;
    }
    
    /**
     * The thickness of the fraction line is determined by the given value "t" in the
     * given unit.
     *
     * @param num the numerator
     * @param den the denominator
     * @param unit a unit constant for the line thickness
     * @param t the thickness of the fraction line (in the given unit)
     * @param numAlign alignment of the numerator
     * @param denomAlign alignment of the denominator
     */
    public FractionAtom(Atom num, Atom den, int unit, float t, int numAlign,
            int denomAlign) {
        this(num, den, unit, t);
        this.numAlign = checkAlignment(numAlign);
        this.denomAlign = checkAlignment(denomAlign);
    }
    
    /**
     * The thickness of the fraction line is determined by the given value "t" in the
     * given unit.
     *
     * @param num the numerator
     * @param den the denominator
     * @param unit a unit constant for the line thickness
     * @param t the thickness of the fraction line (in the given unit)
     */
    public FractionAtom(Atom num, Atom den, int unit, float t) {
        this(num, den, true, unit, t);
    }
    
    // Checks if the alignment constant is valid.
    // If not, a default value will be used.
    private int checkAlignment(int align) {
        if (align == TeXConstants.ALIGN_LEFT ||
                align == TeXConstants.ALIGN_RIGHT)
            return align;
        else
            return TeXConstants.ALIGN_CENTER;
    }
    
    public Box createBox(TeXEnvironment env) {
        TeXFont tf = env.getTeXFont();
        int style = env.getStyle();
        // set thickness to default if default value should be used
        float drt = tf.getDefaultRuleThickness(style);
        if (noDefault)
            // convert the thickness to pixels
            thickness = new SpaceAtom(unit, 0, thickness, 0).createBox(env).getHeight();
        else
            thickness = (defFactorSet ? defFactor * drt : drt);
        
        // create equal width boxes (in appropriate styles)
        Box num = (numerator == null ? new StrutBox(0, 0, 0, 0) : numerator
                .createBox(env.numStyle()));
        Box denom = (denominator == null ? new StrutBox(0, 0, 0, 0) : denominator
                .createBox(env.denomStyle()));
        
        if (num.getWidth() < denom.getWidth())
            num = new HorizontalBox(num, denom.getWidth(), numAlign);
        else
            denom = new HorizontalBox(denom, num.getWidth(), denomAlign);
        
        // calculate default shift amounts
        float shiftUp, shiftDown;
        if (style < TeXConstants.STYLE_TEXT) {
            shiftUp = tf.getNum1(style);
            shiftDown = tf.getDenom1(style);
        } else {
            shiftDown = tf.getDenom2(style);
            if (thickness > 0)
                shiftUp = tf.getNum2(style);
            else
                shiftUp = tf.getNum3(style);
        }
        
        // upper part of vertical box = numerator
        VerticalBox vBox = new VerticalBox();
        vBox.add(num);
        
        // calculate clearance clr, adjust shift amounts and create vertical box
        float clr, delta, axis = tf.getAxisHeight(style);
        
        if (thickness > 0) { // WITH fraction rule
            // clearance clr
            if (style < TeXConstants.STYLE_TEXT)
                clr = 3 * thickness;
            else
                clr = thickness;
            
            // adjust shift amounts
            delta = thickness / 2;
            float kern1 = shiftUp - num.getDepth() - (axis + delta), kern2 = axis
                    - delta - (denom.getHeight() - shiftDown);
            float delta1 = clr - kern1, delta2 = clr - kern2;
            if (delta1 > 0) {
                shiftUp += delta1;
                kern1 += delta1;
            }
            if (delta2 > 0) {
                shiftDown += delta2;
                kern2 += delta2;
            }
            
            // fill vertical box
            vBox.add(new StrutBox(0, kern1, 0, 0));
            vBox.add(new HorizontalRule(thickness, num.getWidth(), 0));
            vBox.add(new StrutBox(0, kern2, 0, 0));
        } else { // WITHOUT fraction rule
            // clearance clr
            if (style < TeXConstants.STYLE_TEXT)
                clr = 7 * drt;
            else
                clr = 3 * drt;
            
            // adjust shift amounts
            float kern = shiftUp - num.getDepth()
            - (denom.getHeight() - shiftDown);
            delta = (clr - kern) / 2;
            if (delta > 0) {
                shiftUp += delta;
                shiftDown += delta;
                kern += 2 * delta;
            }
            
            // fill vertical box
            vBox.add(new StrutBox(0, kern, 0, 0));
        }
        
        // finish vertical box
        vBox.add(denom);
        vBox.setHeight(shiftUp + num.getHeight());
        vBox.setDepth(shiftDown + denom.getDepth());
        return vBox;
    }
}