2
* =========================================================================
3
* This file is part of the JMathTeX Library - http://jmathtex.sourceforge.net
5
* Copyright (C) 2004-2007 Universiteit Gent
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or (at
10
* your option) any later version.
12
* This program is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* A copy of the GNU General Public License can be found in the file
18
* LICENSE.txt provided with the source distribution of this program (see
19
* the META-INF directory in the source jar). This license can also be
20
* found on the GNU website at http://www.gnu.org/licenses/gpl.html.
22
* If you did not receive a copy of the GNU General Public License along
23
* with this program, contact the lead developer, or write to the Free
24
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29
package be.ugent.caagt.jmathtex;
31
import java.awt.Color;
32
import java.util.HashMap;
33
import java.util.HashSet;
35
import java.util.List;
39
* Represents a logical mathematical formula that will be displayed (by creating a
40
* {@link TeXIcon} from it and painting it) using algorithms that are based on the
43
* These formula's can be built using the built-in primitive TeX parser
44
* (methods with String arguments) or using other TeXFormula objects. Most methods
45
* have (an) equivalent(s) where one or more TeXFormula arguments are replaced with
46
* String arguments. These are just shorter notations, because all they do is parse
47
* the string(s) to TeXFormula's and call an equivalent method with (a) TeXFormula argument(s).
48
* Most methods also come in 2 variants. One kind will use this TeXFormula to build
49
* another mathematical construction and then change this object to represent the newly
50
* build construction. The other kind will only use other
51
* TeXFormula's (or parse strings), build a mathematical construction with them and
52
* insert this newly build construction at the end of this TeXFormula.
53
* Because all the provided methods return a pointer to this (modified) TeXFormula
54
* (except for the createTeXIcon method that returns a TeXIcon pointer),
55
* method chaining is also possible.
57
* <b> Important: All the provided methods modify this TeXFormula object, but all the
58
* TeXFormula arguments of these methods will remain unchanged and independent of
59
* this TeXFormula object!</b>
61
public class TeXFormula {
63
// TeX commands and text styles (for parsing)
64
private static Set<String> commands = new HashSet<String>();
66
private static Set<String> textStyles;
68
// table for putting delimiters over and under formula's,
69
// indexed by constants from "TeXConstants"
70
private static final String[][] delimiterNames = {
71
{ "lbrace", "rbrace" },
72
{ "lsqbrack", "rsqbrack" },
73
{ "lbrack", "rbrack" },
74
{ "downarrow", "downarrow" },
75
{ "uparrow", "uparrow" },
76
{ "updownarrow", "updownarrow" },
77
{ "Downarrow", "Downarrow" },
78
{ "Uparrow", "Uparrow" },
79
{ "Updownarrow", "Updownarrow" },
84
// the escape character
85
private static final char ESCAPE = '\\';
87
// grouping characters (for parsing)
88
private static final char L_GROUP = '{';
89
private static final char R_GROUP = '}';
90
private static final char L_BRACK = '[';
91
private static final char R_BRACK = ']';
93
// used as second index in "delimiterNames" table (over or under)
94
private static final int OVER_DEL = 0;
95
private static final int UNDER_DEL = 1;
97
// for comparing floats with 0
98
protected static final float PREC = 0.0000001f;
100
// predefined TeXFormula's
101
private static Map<String,TeXFormula> predefinedTeXFormulas = new HashMap<String,TeXFormula>();
103
// script characters (for parsing)
104
private static final char SUB_SCRIPT = '_';
105
private static final char SUPER_SCRIPT = '^';
106
private static final char PRIME = '\'';
108
// character-to-symbol and character-to-delimiter mappings
109
private static String[] symbolMappings;
110
private static String[] delimiterMappings;
113
// character-to-symbol and character-to-delimiter mappings
114
TeXFormulaSettingsParser parser = new TeXFormulaSettingsParser();
115
symbolMappings = parser.parseSymbolMappings();
116
delimiterMappings = parser.parseDelimiterMappings();
118
// textstyle commands
119
textStyles = parser.parseTextStyles();
122
commands.add("frac");
123
commands.add("sqrt");
125
// predefined TeXFormula's
126
new PredefinedTeXFormulaParser().parse(predefinedTeXFormulas);
129
// the string to be parsed
130
private String parseString;
132
// current position in the parse string
135
// the root atom of the "atom tree" that represents the formula
136
protected Atom root = null;
138
// the current text style
139
private String textStyle = null;
142
* Creates an empty TeXFormula.
145
public TeXFormula() {
150
* Creates a new TeXFormula from a list of TeXFormula objects.
152
* If the list is empty (or null), then an empty TeXFormula will be created.
153
* Otherwise, the newly created TeXFormula is the same as if
154
* all the TeXFormula's in the list were added one after another (starting with the
155
* first one) to an empty TeXFormula using the {@link #add(TeXFormula)} method.
157
* <b> The new TeXFormula is independent of all the TeXFormula's from the list!</b>
159
* @param l a list of TeXFormula objects
161
public TeXFormula(List<TeXFormula> l) {
167
root = new RowAtom(l);
168
} catch (EmptyFormulaException e) {
176
* Creates a new TeXFormula by parsing the given string (using a primitive TeX parser).
178
* @param s the string to be parsed
179
* @throws ParseException if the string could not be parsed correctly
181
public TeXFormula(String s) throws ParseException {
186
* Creates a TeXFormula by parsing the given string in the given text style.
187
* Used when a text style command was found in the parse string.
189
private TeXFormula(String s, String textStyle) throws ParseException {
190
this.textStyle = textStyle;
191
if (s != null && s.length() != 0)
196
* Creates a new TeXFormula that is a copy of the given TeXFormula.
198
* <b>Both TeXFormula's are independent of one another!</b>
200
* @param f the formula to be copied
202
public TeXFormula(TeXFormula f) {
208
* Inserts an atom at the end of the current formula
210
private TeXFormula add(Atom el) {
215
if (!(root instanceof RowAtom))
216
root = new RowAtom(root);
217
((RowAtom) root).add(el);
224
* Parses the given string and inserts the resulting formula
225
* at the end of the current TeXFormula.
227
* @param s the string to be parsed and inserted
228
* @throws ParseException if the string could not be parsed correctly
229
* @return the modified TeXFormula
231
public TeXFormula add(String s) throws ParseException {
232
if (s != null && s.length() != 0) {
233
// reset parsing variables
236
// parse and add the string
243
* Inserts the given TeXFormula at the end of the current TeXFormula.
245
* @param f the TeXFormula to be inserted
246
* @return the modified TeXFormula
248
public TeXFormula add(TeXFormula f) {
253
private void addImpl (TeXFormula f) {
254
if (f.root != null) {
255
// special copy-treatment for Mrow as a root!!
256
if (f.root instanceof RowAtom)
257
add(new RowAtom(f.root));
264
* Centers the current TeXformula vertically on the axis (defined by the parameter
265
* "axisheight" in the resource "DefaultTeXFont.xml".
267
* @return the modified TeXFormula
269
public TeXFormula centerOnAxis() {
270
root = new VCenteredAtom(root);
275
* Parses the given string(s) into a TeXFormula, puts the given accent above it and
276
* inserts the result at the end of the current TeXFormula.
278
* @param s the string to be parsed into a TeXFormula above which te given accent
280
* @param accentName the name of the accent symbol
281
* @return the modified TeXFormula
282
* @throws InvalidSymbolTypeException if the symbol is not defined as an accent
283
* @throws SymbolNotFoundException if there's no symbol defined with the given name
284
* @throws ParseException if the string(s) could not be parsed correctly
286
public TeXFormula addAcc(String s, String accentName)
287
throws InvalidSymbolTypeException, SymbolNotFoundException,
289
return addAcc(new TeXFormula(s), accentName);
293
* Puts the given accent above the given TeXFormula and inserts the result
294
* at the end of the current TeXFormula.
296
* @param base the TeXFormula above which the given accent will be placed
297
* @param accentName the name of the accent symbol
298
* @return the modified TeXFormula
299
* @throws InvalidSymbolTypeException if the symbol is not defined as an accent
300
* @throws SymbolNotFoundException if there's no symbol defined with the given name
302
public TeXFormula addAcc(TeXFormula base, String accentName)
303
throws InvalidSymbolTypeException, SymbolNotFoundException {
304
return add(new AccentedAtom((base == null ? null : base.root), accentName));
308
* Puts the given accent TeXFormula (that must represent a single accent symbol!) above
309
* the given base TeXFormula and inserts the result at the end of the current TeXFormula.
311
* <b>It's recommended to use one of the other more simple "addAcc"-mehods that require
312
* the symbolname of the accent as a string! This method was added only because it was the
313
* best way for parsing the MathML "mover" element into a TeXFormula.</b>
315
* @param base the TeXFormula above which the given accent will be placed
316
* @param accent the TeXFormula that must represent a single accent symbol
317
* @return the modified TeXFormula
318
* @throws InvalidSymbolTypeException if the symbol that the given accent TeXFormula
319
* represents, is not defined as an accent
320
* @throws InvalidTeXFormulaException if the given accent TeXFormula does not represent
323
public TeXFormula addAcc(TeXFormula base, TeXFormula accent)
324
throws InvalidSymbolTypeException, InvalidTeXFormulaException {
325
return add(new AccentedAtom((base == null ? null : base.root), accent));
329
* Parses the given string into a TeXFormula, surrounds it with the given
330
* delimiters and inserts the result at the end of the current TeXformula.
332
* @param s the string to be parsed into a TeXFormula that will be surrounded
333
* by the given delimiters
334
* @param l the left delimiter character
335
* @param r the right delimiter character
336
* @return the modified TeXFormula
337
* @throws SymbolNotFoundException if one of the delimiter characters is mapped
338
* to an unknown symbol
339
* @throws InvalidDelimiterException if one of the delimiter characters is mapped
340
* to a symbol that is not defined as a delimiter symbol
341
* @throws ParseException if the string could not be parsed correctly
342
* @throws DelimiterMappingNotFoundException if no character-to-symbol mapping is
343
* found for one of the delimiter characters
345
public TeXFormula addEmbraced(String s, char l, char r)
346
throws SymbolNotFoundException, InvalidDelimiterException,
347
ParseException, DelimiterMappingNotFoundException {
348
return addEmbraced(new TeXFormula(s), l, r);
352
* Parses the given string(s) into a TeXFormula, surrounds it with the given
353
* delimiters (if not null) and inserts the result at the end of the current
356
* @param s the string to be parsed into a TeXFormula that will be
357
* surrounded by the given delimiters
358
* @param left the symbol name of the left delimiter (or null: no delimiter)
359
* @param right the symbol name of the right delimiter (or null: no delimiter)
360
* @return the modified TeXFormula
361
* @throws SymbolNotFoundException if no symbol is defined for one of the
363
* @throws ParseException if the string(s) could not be parsed correctly
364
* @throws InvalidDelimiterException if one of the symbols is not defined as a
367
public TeXFormula addEmbraced(String s, String left, String right)
368
throws SymbolNotFoundException, ParseException,
369
InvalidDelimiterException {
370
return addEmbraced(new TeXFormula(s), left, right);
374
* Surrounds the given TeXFormula with the given delimiters and
375
* inserts the result at the end of the current TeXformula.
377
* @param f the TeXFormula that will be surrounded by the given delimiters
378
* @param l the left delimiter character
379
* @param r the right delimiter character
380
* @return the modified TeXFormula
381
* @throws SymbolNotFoundException if one of the delimiter characters is mapped
382
* to an unknown symbol
383
* @throws InvalidDelimiterException if one of the delimiter characters is mapped
384
* to a symbol that is not defined as a delimiter symbol
385
* @throws DelimiterMappingNotFoundException if no character-to-symbol mapping is
386
* found for one of the delimiter characters
388
public TeXFormula addEmbraced(TeXFormula f, char l, char r)
389
throws SymbolNotFoundException, InvalidDelimiterException,
390
DelimiterMappingNotFoundException {
391
return addEmbraced(f, getCharacterToDelimiterMapping(l),
392
getCharacterToDelimiterMapping(r));
396
* Surrounds the given TeXFormula with the given delimiters (if not null) and inserts the
397
* result at the end of the current TeXFormula.
399
* @param f the TeXFormula that will be surrounded by the given delimiters
400
* @param left the symbol name of the left delimiter (or null: no delimiter)
401
* @param right the symbol name of the right delimiter (or null: no delimiter)
402
* @return the modified TeXFormula
403
* @throws SymbolNotFoundException if no symbol is defined for one of the
405
* @throws InvalidDelimiterException if one of the symbols is not defined as a
408
public TeXFormula addEmbraced(TeXFormula f, String left, String right)
409
throws SymbolNotFoundException, InvalidDelimiterException {
410
return add(new FencedAtom((f == null ? null : f.root),
411
getDelimiterSymbol(left), getDelimiterSymbol(right)));
415
* Parses the given strings into TeXFormula's that will represent the numerator (num)
416
* and the denominator (denom) of a fraction, draws a line between them
417
* depending on "rule" and inserts the result at the end of the current
420
* @param num the string to be parsed into a TeXFormula that will represent the
421
* numerator of the fraction
422
* @param denom the string to be parsed into a TeXFormula that will represent the
423
* denominator of the fraction
424
* @param rule whether a line should be drawn between numerator and denominator
425
* @return the modified TeXFormula
426
* @throws ParseException if one of the strings could not be parsed correctly
428
public TeXFormula addFraction(String num, String denom, boolean rule)
429
throws ParseException {
430
return addFraction(new TeXFormula(num), new TeXFormula(denom), rule);
434
* Parses the given strings into TeXFormula's that will represent the numerator (num)
435
* and denominator (denom) of a fraction, draws a line between them
436
* depending on "rule", aligns the numerator and denominator in comparison with
437
* each other (indicated by numAlign and denomAlign) and inserts the result at
438
* the end of the current TeXFormula.
440
* @param num the string to be parsed into a TeXFormula that will represent the
441
* numerator of the fraction
442
* @param denom the string to be parsed into a TeXFormula that will represent the
443
* denominator of the fraction
444
* @param rule whether a line should be drawn between numerator and denominator
445
* @param numAlign an alignment constant (from {@link TeXConstants}) indicating
446
* how the numerator should be aligned in comparison with the (larger)
448
* @param denomAlign an alignment constant (from TeXConstants) indicating
449
* how the denominator should be aligned in comparison with the (larger)
451
* @return the modified TeXFormula
452
* @throws ParseException if one of the strings could not be parsed correctly
454
public TeXFormula addFraction(String num, String denom, boolean rule,
455
int numAlign, int denomAlign) throws ParseException {
456
return addFraction(new TeXFormula(num), new TeXFormula(denom), rule,
457
numAlign, denomAlign);
461
* Parses the given string into a TeXFormula that will represent the numerator of
462
* a fraction, uses the given TeXFormula as the denominator of this fraction,
463
* draws a line between them depending on "rule" and inserts the
464
* result at the end of the current TeXFormula.
466
* @param num the string to be parsed into a TeXFormula that will represent the
467
* numerator of the fraction
468
* @param denom the TeXFormula that will represent the
469
* denominator of the fraction
470
* @param rule whether a line should be drawn between numerator and denominator
471
* @return the modified TeXFormula
472
* @throws ParseException if the string could not be parsed correctly
474
public TeXFormula addFraction(String num, TeXFormula denom, boolean rule)
475
throws ParseException {
476
return addFraction(new TeXFormula(num), denom, rule);
480
* Parses the given string into a TeXFormula that will represent the denominator of
481
* a fraction, uses the given TeXFormula as the numerator of this fraction,
482
* draws a line between them depending on "rule" and inserts the
483
* result at the end of the current TeXFormula.
485
* @param num the TeXFormula that will represent the
486
* numerator of the fraction
487
* @param denom the string to be parsed into a TeXFormula that will represent the
488
* denominator of the fraction
489
* @param rule whether a line should be drawn between numerator and denominator
490
* @return the modified TeXFormula
491
* @throws ParseException if the string could not be parsed correctly
493
public TeXFormula addFraction(TeXFormula num, String denom, boolean rule)
494
throws ParseException {
495
return addFraction(num, new TeXFormula(denom), rule);
499
* Uses the given TeXFormula's as the numerator (num) and denominator (denom) of
500
* a fraction, draws a line between them depending on "rule"
501
* and inserts the result at the end of the current TeXFormula.
503
* @param num the TeXFormula that will represent the
504
* numerator of the fraction
505
* @param denom the TeXFormula that will represent the
506
* denominator of the fraction
507
* @param rule whether a line should be drawn between numerator and denominator
508
* @return the modified TeXFormula
510
public TeXFormula addFraction(TeXFormula num, TeXFormula denom, boolean rule) {
511
return add(new FractionAtom((num == null ? null : num.root),
512
(denom == null ? null : denom.root), rule));
516
* Uses the given TeXFormula's as the numerator (num) and denominator (denom) of
517
* a fraction, draws a line between them depending on "rule",
518
* aligns the numerator and denominator in comparison with
519
* each other (indicated by numAlign and denomAlign) and inserts the result at
520
* the end of the current TeXFormula.
522
* @param num the TeXFormula that will represent the
523
* numerator of the fraction
524
* @param denom the TeXFormula that will represent the
525
* denominator of the fraction
526
* @param rule whether a line should be drawn between numerator and denominator
527
* @param numAlign an alignment constant (from {@link TeXConstants}) indicating
528
* how the numerator should be aligned in comparison with the (larger)
530
* @param denomAlign an alignment constant (from TeXConstants) indicating
531
* how the denominator should be aligned in comparison with the (larger)
533
* @return the modified TeXFormula
535
public TeXFormula addFraction(TeXFormula num, TeXFormula denom,
536
boolean rule, int numAlign, int denomAlign) {
537
return add(new FractionAtom((num == null ? null : num.root),
538
(denom == null ? null : denom.root), rule, numAlign, denomAlign));
542
* Parses the given strings into TeXFormula's, puts them under a root
543
* sign (base) and in the upper left corner over this root sign (nthRoot)
544
* and inserts the result at the end of the current TeXFormula.
546
* @param base the string to be parsed into a TeXFormula that will be put
547
* under the root sign.
548
* @param nthRoot the string to be parsed into a TeXFormula that will be put
549
* in the upper left corner over the root sign
550
* @return the modified TeXFormula
551
* @throws ParseException if one of the strings could not be parsed correctly
553
public TeXFormula addNthRoot(String base, String nthRoot)
554
throws ParseException {
555
return addNthRoot(new TeXFormula(base), new TeXFormula(nthRoot));
559
* Parses the given string into a TeXFormula, puts it under a root
560
* sign, puts the given TeXFormula in the upper left corner over this root sign
561
* and inserts the result at the end of the current TeXFormula.
563
* @param base the string to be parsed into a TeXFormula that will be put
564
* under the root sign.
565
* @param nthRoot the TeXFormula that will be put
566
* in the upper left corner over the root sign
567
* @return the modified TeXFormula
568
* @throws ParseException if the string could not be parsed correctly
570
public TeXFormula addNthRoot(String base, TeXFormula nthRoot)
571
throws ParseException {
572
return addNthRoot(new TeXFormula(base), nthRoot);
576
* Parses the given string into a TeXFormula, puts it in the upper
577
* left corner over the root sign, puts the given TeXFormula under this root sign
578
* and inserts the result at the end of the current TeXFormula.
580
* @param base the TeXFormula that will be put under the root sign.
581
* @param nthRoot the string to be parsed into a TeXFormula that will be put
582
* in the upper left corner over the root sign
583
* @return the modified TeXFormula
584
* @throws ParseException if the strings could not be parsed correctly
586
public TeXFormula addNthRoot(TeXFormula base, String nthRoot)
587
throws ParseException {
588
return addNthRoot(base, new TeXFormula(nthRoot));
592
* Puts the given TeXFormula's under a root sign (base) and in the upper left
593
* corner over this root sign (nthRoot) and inserts the result at the end of the
594
* current TeXFormula.
596
* @param base the TeXFormula that will be put under the root sign.
597
* @param nthRoot the TeXFormula that will be put
598
* in the upper left corner over the root sign
599
* @return the modified TeXFormula
601
public TeXFormula addNthRoot(TeXFormula base, TeXFormula nthRoot) {
602
return add(new NthRoot((base == null ? null : base.root),
603
(nthRoot == null ? null : nthRoot.root)));
607
* Parses the given strings into TeXFormula's that will represent a "big operator"
608
* (op), it's lower (low) and upper (up) bound, and inserts the result at the end
609
* of the current TeXFormula. The positioning of the upper and lower bound
610
* (as limits: over and under the "big operator", or as scripts: superscript and
611
* subscript) will be determined automatically according to the TeX algorithms.
612
* If low is null, the lower bound will be omitted. If up is null, the upper
613
* bound will be omitted.
615
* @param op the string to be parsed into a TeXFormula that will represent the
617
* @param low the string to be parsed into a TeXFormula that will represent
618
* the lower bound of the "big operator" (or null: no lower bound)
619
* @param up the string to be parsed into a TeXFormula that will represent
620
* the upper bound of the "big operator" (or null: no upper bound)
621
* @return the modified TeXFormula
622
* @throws ParseException if one of the strings could not be parsed correctly
624
public TeXFormula addOp(String op, String low, String up)
625
throws ParseException {
626
return addOp(new TeXFormula(op), new TeXFormula(low), new TeXFormula(up));
630
* Parses the given strings into TeXFormula's that will represent a "big operator"
631
* (op), it's lower (low) and upper (up) bound, and inserts the result at the end
632
* of the current TeXFormula. The positioning of the upper and lower bound
633
* (as limits: over and under the "big operator", or as scripts: superscript and
634
* subscript) is determined by lim.
636
* @param op the string to be parsed into a TeXFormula that will represent the
638
* @param low the string to be parsed into a TeXFormula that will represent
639
* the lower bound of the "big operator" (or null: no lower bound)
640
* @param up the string to be parsed into a TeXFormula that will represent
641
* the upper bound of the "big operator" (or null: no upper bound)
642
* @param lim whether the upper and lower bound should be displayed as limits
644
* @return the modified TeXFormula
645
* @throws ParseException if one of the strings could not be parsed correctly
647
public TeXFormula addOp(String op, String low, String up, boolean lim)
648
throws ParseException {
649
return addOp(new TeXFormula(op), new TeXFormula(low), new TeXFormula(up),
654
* Uses the given TeXFormula's as a "big operator"
655
* (op), it's lower (low) and upper (up) bound, and inserts the result at the end
656
* of the current TeXFormula. The positioning of the upper and lower bound
657
* (as limits: over and under the "big operator", or as scripts: superscript and
658
* subscript) will be determined automatically according to the TeX algorithms.
659
* If low is null, the lower bound will be omitted. If up is null, the upper
660
* bound will be omitted.
662
* @param op the TeXFormula that will represent the
664
* @param low the TeXFormula that will represent
665
* the lower bound of the "big operator" (or null: no lower bound)
666
* @param up the TeXFormula that will represent
667
* the upper bound of the "big operator" (or null: no upper bound)
668
* @return the modified TeXFormula
670
public TeXFormula addOp(TeXFormula op, TeXFormula low, TeXFormula up) {
671
return add(new BigOperatorAtom((op == null ? null : op.root),
672
(low == null ? null : low.root), (up == null ? null : up.root)));
676
* Uses the given TeXFormula's as a "big operator"
677
* (op), it's lower (low) and upper (up) bound, and inserts the result at the end
678
* of the current TeXFormula. The positioning of the upper and lower bound
679
* (as limits: over and under the "big operator", or as scripts: superscript and
680
* subscript) is determined by lim.
682
* @param op the TeXFormula that will represent the
684
* @param low the TeXFormula that will represent
685
* the lower bound of the "big operator" (or null: no lower bound)
686
* @param up the TeXFormula that will represent
687
* the upper bound of the "big operator" (or null: no upper bound)
688
* @param lim whether the upper and lower bound should be displayed as limits
690
* @return the modified TeXFormula
692
public TeXFormula addOp(TeXFormula op, TeXFormula low, TeXFormula up,
694
return add(new BigOperatorAtom((op == null ? null : op.root),
695
(low == null ? null : low.root), (up == null ? null : up.root), lim));
699
* Parses the given string into a phantom TeXFormula and inserts the result at the
700
* end of the current TeXFormula. A phantom TeXFormula will be rendered invisibly.
701
* Although the inserted formula is invisible, it's
702
* still treated as a normal visible formula when it comes to inserting glue.
704
* @param phantom the string to be parsed as a phantom TeXFormula
705
* @return the modified TeXFormula
706
* @throws ParseException if the string could not be parsed correctly
708
public TeXFormula addPhantom(String phantom) throws ParseException {
709
return addPhantom(new TeXFormula(phantom));
713
* Parses the given string into a phantom TeXFormula and inserts the result at the
714
* end of the current TeXFormula. Only the dimensions set to true will be taken into
715
* account for drawing the whitespace. Although the inserted formula is invisible, it's
716
* still treated as a normal visible formula when it comes to inserting glue.
718
* @param phantom the string to be parsed as a phantom TeXFormula
719
* @param width whether the width of the TeXFormula's box should be used (<-> width 0)
720
* @param height whether the height of the TeXFormula's box should be used (<-> height 0)
721
* @param depth whether the depth of the TeXFormula's box should be used (<-> depth 0)
722
* @return the modified TeXFormula
723
* @throws ParseException if the string could not be parsed correctly
725
public TeXFormula addPhantom(String phantom, boolean width, boolean height,
726
boolean depth) throws ParseException {
727
return addPhantom(new TeXFormula(phantom), width, height, depth);
731
* Inserts the given TeXFormula as a phantom TeXFormula at the
732
* end of the current TeXFormula. A phantom TeXFormula will be rendered invisibly.
733
* Although the inserted formula is invisible, it's
734
* still treated as a normal visible formula when it comes to inserting glue.
736
* @param phantom the TeXFormula to be inserted as a phantom TeXFormula
737
* @return the modified TeXFormula
739
public TeXFormula addPhantom(TeXFormula phantom) {
740
return add(new PhantomAtom((phantom == null ? null : phantom.root)));
744
* Inserts the given TeXFormula as a phantom TeXFormula at the
745
* end of the current TeXFormula. Only the dimensions set to true will be taken into
746
* account for drawing the whitespace. Although the inserted formula is invisible, it's
747
* still treated as a normal visible formula when it comes to inserting glue.
749
* @param phantom the TeXFormula to be inserted as a phantom TeXFormula
750
* @param width whether the width of the TeXFormula's box should be used (<-> width 0)
751
* @param height whether the height of the TeXFormula's box should be used (<-> height 0)
752
* @param depth whether the depth of the TeXFormula's box should be used (<-> depth 0)
753
* @return the modified TeXFormula
755
public TeXFormula addPhantom(TeXFormula phantom, boolean width,
756
boolean height, boolean depth) {
757
return add(new PhantomAtom((phantom == null ? null : phantom.root),
758
width, height, depth));
762
* Parses the given string into a TeXFormula that will be displayed under a root
763
* sign and inserts the result at the end of the current TeXFormula.
765
* @param base the string to be parsed into a TeXFormula that will be displayed
767
* @return the modified TeXFormula
768
* @throws ParseException if the string could not be parsed correctly
770
public TeXFormula addSqrt(String base) throws ParseException {
771
return addSqrt(new TeXFormula(base));
775
* Displays the given TeXFormula under a root
776
* sign and inserts the result at the end of the current TeXFormula.
778
* @param base the TeXFormula that will be displayed
780
* @return the modified TeXFormula
782
public TeXFormula addSqrt(TeXFormula base) {
783
return addNthRoot(base, (TeXFormula) null);
787
* Inserts a strut box (whitespace) with the given width, height and depth (in
788
* the given unit) at the end of the current TeXFormula.
790
* @param unit a unit constant (from {@link TeXConstants})
791
* @param width the width of the strut box
792
* @param height the height of the strut box
793
* @param depth the depth of the strut box
794
* @return the modified TeXFormula
795
* @throws InvalidUnitException if the given integer value does not represent
798
public TeXFormula addStrut(int unit, float width, float height, float depth)
799
throws InvalidUnitException {
800
return add(new SpaceAtom(unit, width, height, depth));
804
* Inserts a strut box (whitespace) with the given width (in widthUnits), height
805
* (in heightUnits) and depth (in depthUnits) at the end of the current TeXFormula.
807
* @param widthUnit a unit constant used for the width (from {@link TeXConstants})
808
* @param width the width of the strut box
809
* @param heightUnit a unit constant used for the height (from TeXConstants)
810
* @param height the height of the strut box
811
* @param depthUnit a unit constant used for the depth (from TeXConstants)
812
* @param depth the depth of the strut box
813
* @return the modified TeXFormula
814
* @throws InvalidUnitException if the given integer value does not represent
817
public TeXFormula addStrut(int widthUnit, float width, int heightUnit,
818
float height, int depthUnit, float depth) throws InvalidUnitException {
819
return add(new SpaceAtom(widthUnit, width, heightUnit, height, depthUnit,
824
* Inserts the symbol with the given name at the end of the current TeXFormula.
826
* @param name the name of the symbol
827
* @return the modified TeXFormula
828
* @throws SymbolNotFoundException if there's no symbol defined with the given name
830
public TeXFormula addSymbol(String name) throws SymbolNotFoundException {
831
return add(SymbolAtom.get(name));
835
* Inserts the symbol with the given name at the end of the current TeXFormula
836
* as a symbol of the given symbol type. This type can be (and is meant to be)
837
* different from the symbol's defined type.
839
* @param name the name of the symbol
840
* @param type a symbol type constant (from {@link TeXConstants})
841
* @return the modified TeXFormula
842
* @throws SymbolNotFoundException if there's no symbol defined with the given name
843
* @throws InvalidSymbolTypeException if the given integer value does not represent
844
* a valid symbol type
846
public TeXFormula addSymbol(String name, int type)
847
throws SymbolNotFoundException, InvalidSymbolTypeException {
848
return add(new SymbolAtom(SymbolAtom.get(name), type));
852
* Look for scripts at the current position in the parse string
853
* and attach them to the given atom (if found)
855
private Atom attachScripts(Atom atom) throws ParseException {
859
if (pos < parseString.length()) {
860
// attach script(s) if present
861
char ch = parseString.charAt(pos);
863
// ' = ^{\prime... so first replace this, then attach this script
866
ch = parseString.charAt(pos);
869
// look for scripts and attach them
870
if (ch == SUPER_SCRIPT || ch == SUB_SCRIPT) {
872
if (ch == SUPER_SCRIPT) { // superscript
873
TeXFormula sup = getScript(), sub = new TeXFormula();
875
if (pos < parseString.length()
876
&& parseString.charAt(pos) == SUB_SCRIPT) { // both
880
if(f.getRightType() == TeXConstants.TYPE_BIG_OPERATOR)
881
f = new BigOperatorAtom(f, sub.root, sup.root);
883
f = new ScriptsAtom(f, sub.root, sup.root);
884
} else { // subscript
885
TeXFormula sub = getScript(), sup = new TeXFormula();
887
if (pos < parseString.length()
888
&& parseString.charAt(pos) == SUPER_SCRIPT) { // both
892
if(f.getRightType() == TeXConstants.TYPE_BIG_OPERATOR)
893
f = new BigOperatorAtom(f, sub.root, sup.root);
895
f = new ScriptsAtom(f, sub.root, sup.root);
903
* Converts a character (from the parse string) to an atom (CharAtom or Symbol)
905
private Atom convertCharacter(char c) throws ParseException {
908
String symbolName = symbolMappings[c];
909
if (symbolName == null)
910
throw new ParseException("Unknown character : '"
911
+ Character.toString(c) + "'");
914
return SymbolAtom.get(symbolName);
915
} catch (SymbolNotFoundException e) {
916
throw new ParseException("The character '"
917
+ Character.toString(c)
918
+ "' was mapped to an unknown symbol with the name '"
919
+ (String) symbolName + "'!", e);
922
// alphanumeric character
923
return new CharAtom(c, textStyle);
927
* Convert this TeXFormula into a box, starting form the given style
929
private Box createBox(TeXEnvironment style) {
931
return new StrutBox(0, 0, 0, 0);
933
return root.createBox(style);
937
* Creates a TeXIcon from this TeXFormula using the default TeXFont in the given
938
* point size and starting from the given TeX style. If the given integer value
939
* does not represent a valid TeX style, the default style
940
* TeXConstants.STYLE_DISPLAY will be used.
942
* @param style a TeX style constant (from {@link TeXConstants}) to start from
943
* @param size the default TeXFont's point size
944
* @return the created TeXIcon
946
public TeXIcon createTeXIcon(int style, float size) {
947
return new TeXIcon(createBox(new TeXEnvironment(style,
948
new DefaultTeXFont(size))), size);
952
* Surrounds this TeXFormula with the given delimiters.
954
* @param left the left delimiter character
955
* @param right the right delimiter character
956
* @return the modified TeXFormula
957
* @throws SymbolNotFoundException if one of the delimiter characters is mapped
958
* to an unknown symbol
959
* @throws InvalidDelimiterException if one of the delimiter characters is mapped
960
* to a symbol that is not defined as a delimiter symbol
961
* @throws DelimiterMappingNotFoundException if no character-to-symbol mapping is
962
* found for one of the delimiter characters
964
public TeXFormula embrace(char left, char right)
965
throws SymbolNotFoundException, InvalidDelimiterException,
966
DelimiterMappingNotFoundException {
967
return embrace(getCharacterToDelimiterMapping(left),
968
getCharacterToDelimiterMapping(right));
972
* Surrounds this TeXFormula with the given delimiters (if not null).
974
* @param left the symbol name of the left delimiter (or null: no delimiter)
975
* @param right the symbol name of the right delimiter (or null: no delimiter)
976
* @return the modified TeXFormula
977
* @throws SymbolNotFoundException if no symbol is defined for one of the
979
* @throws InvalidDelimiterException if one of the symbols is not defined as a
982
public TeXFormula embrace(String left, String right)
983
throws SymbolNotFoundException, InvalidDelimiterException {
984
root = new FencedAtom(root, getDelimiterSymbol(left),
985
getDelimiterSymbol(right));
990
* Uses the current TeXFormula as the numerator of a fraction, parses the given string
991
* into a TeXFormula that will represent the denominator of the fraction, draws a line
992
* between them depending on "rule" and changes the current TeXFormula
993
* into this resulting fraction.
995
* @param s the string to be parsed into a TeXFormula that will represent the
996
* denominator of the fraction
997
* @param rule whether a line should be drawn between numerator and denominator
998
* @return the modified TeXFormula
999
* @throws ParseException if the string could not be parsed correctly
1001
public TeXFormula fraction(String s, boolean rule) throws ParseException {
1002
return fraction(new TeXFormula(s), rule);
1006
* Uses the current TeXFormula as the numerator of a fraction, parses the given string
1007
* into a TeXFormula that will represent the denominator of the fraction, possibly
1008
* draws a line between them depending on "rule", aligns the numerator and
1009
* denominator in comparison with each other (indicated by numAlign and denomAlign)
1010
* and changes the current TeXFormula into this resulting fraction.
1012
* @param s the string to be parsed into a TeXFormula that will represent the
1013
* denominator of the fraction
1014
* @param rule whether a line should be drawn between numerator and denominator
1015
* @param numAlign an alignment constant (from {@link TeXConstants}) indicating
1016
* how the numerator should be aligned in comparison with the (larger)
1018
* @param denomAlign an alignment constant (from TeXConstants) indicating
1019
* how the denominator should be aligned in comparison with the (larger)
1021
* @return the modified TeXFormula
1022
* @throws ParseException if the string could not be parsed correctly
1024
public TeXFormula fraction(String s, boolean rule, int numAlign,
1025
int denomAlign) throws ParseException {
1026
return fraction(new TeXFormula(s), rule, numAlign, denomAlign);
1030
* Uses the current TeXFormula as the numerator of a fraction, the given TeXFormula
1031
* as the denominator of the fraction, draws a line between them depending on "rule"
1032
* and changes the current TeXFormula into this resulting fraction.
1034
* @param f the TeXFormula that will represent the
1035
* denominator of the fraction
1036
* @param rule whether a line should be drawn between numerator and denominator
1037
* @return the modified TeXFormula
1039
public TeXFormula fraction(TeXFormula f, boolean rule) {
1040
root = new FractionAtom(root, (f == null ? null : f.root), rule);
1045
* Uses the current TeXFormula as the numerator of a fraction, the given TeXFormula
1046
* as the denominator of the fraction, draws a line between them with the given
1047
* thickness (in the given unit)
1048
* and changes the current TeXFormula into this resulting fraction.
1050
* @param f the TeXFormula that will represent the
1051
* denominator of the fraction
1052
* @param unit a unit constant (from {@link TeXConstants})
1053
* @param thickness the thickness (in the given unit) of the line to be put between
1054
* the numerator and denominator
1055
* @return the modified TeXFormula
1056
* @throws InvalidUnitException if the given integer value does not
1057
* represent a valid unit
1059
public TeXFormula fraction(TeXFormula f, int unit, float thickness)
1060
throws InvalidUnitException {
1061
root = new FractionAtom(root, (f == null ? null : f.root), unit,
1067
* Uses the current TeXFormula as the numerator of a fraction, the given TeXFormula
1068
* as the denominator of the fraction, draws a line between them depending on "rule",
1069
* aligns the numerator and denominator in comparison with
1070
* each other (indicated by numAlign and denomAlign) and changes the current
1071
* TeXFormula into this resulting fraction.
1073
* @param f the TeXFormula that will represent the
1074
* denominator of the fraction
1075
* @param unit a unit constant (from {@link TeXConstants})
1076
* @param thickness the thickness (in the given unit) of the line to be put between
1077
* the numerator and denominator
1078
* @param numAlign an alignment constant (from TeXConstants) indicating
1079
* how the numerator should be aligned in comparison with the (larger)
1081
* @param denomAlign an alignment constant (from TeXConstants) indicating
1082
* how the denominator should be aligned in comparison with the (larger)
1084
* @return the modified TeXFormula
1085
* @throws InvalidUnitException if the given integer value does not
1086
* represent a valid unit
1088
public TeXFormula fraction(TeXFormula f, int unit, float thickness,
1089
int numAlign, int denomAlign) throws InvalidUnitException {
1090
root = new FractionAtom(root, (f == null ? null : f.root), unit,
1091
thickness, numAlign, denomAlign);
1096
* Uses the current TeXFormula as the numerator of a fraction, the given TeXFormula
1097
* as the denominator of the fraction, draws a line between them with a thickness
1098
* of "defaultFactor" times the default rule thickness,
1099
* aligns the numerator and denominator in comparison with
1100
* each other (indicated by numAlign and denomAlign) and changes the current
1101
* TeXFormula into this resulting fraction.
1103
* @param f the TeXFormula that will represent the
1104
* denominator of the fraction
1105
* @param defaultFactor the thickness factor (to be multiplied by the default
1107
* @param numAlign an alignment constant (from TeXConstants) indicating
1108
* how the numerator should be aligned in comparison with the (larger)
1110
* @param denomAlign an alignment constant (from TeXConstants) indicating
1111
* how the denominator should be aligned in comparison with the (larger)
1113
* @return the modified TeXFormula
1115
public TeXFormula fraction(TeXFormula f, float defaultFactor, int numAlign,
1117
root = new FractionAtom(root, (f == null ? null : f.root), defaultFactor,
1118
numAlign, denomAlign);
1123
* Uses the current TeXFormula as the numerator of a fraction, the given TeXFormula
1124
* as the denominator of the fraction, draws a line between them depending on "rule",
1125
* aligns the numerator and denominator in comparison with
1126
* each other (indicated by numAlign and denomAlign) and changes the current
1127
* TeXFormula into this resulting fraction.
1129
* @param f the TeXFormula that will represent the
1130
* denominator of the fraction
1131
* @param rule whether a line should be drawn between numerator and denominator
1132
* @param numAlign an alignment constant (from {@link TeXConstants}) indicating
1133
* how the numerator should be aligned in comparison with the (larger)
1135
* @param denomAlign an alignment constant (from TeXConstants) indicating
1136
* how the denominator should be aligned in comparison with the (larger)
1138
* @return the modified TeXFormula
1140
public TeXFormula fraction(TeXFormula f, boolean rule, int numAlign,
1142
root = new FractionAtom(root, (f == null ? null : f.root), rule,
1143
numAlign, denomAlign);
1148
* Uses the current TeXFormula as the denominator of a fraction, parses the given string
1149
* into a TeXFormula that will represent the numerator of the fraction, draws a line
1150
* between them depending on "rule" and changes the current TeXFormula
1151
* into this resulting fraction.
1153
* @param s the string to be parsed into a TeXFormula that will represent the
1154
* numerator of the fraction
1155
* @param rule whether a line should be drawn between numerator and denominator
1156
* @return the modified TeXFormula
1157
* @throws ParseException if the string could not be parsed correctly
1159
public TeXFormula fractionInvert(String s, boolean rule)
1160
throws ParseException {
1161
return fractionInvert(new TeXFormula(s), rule);
1165
* Uses the current TeXFormula as the denominator of a fraction, parses the given string
1166
* into a TeXFormula that will represent the numerator of the fraction, draws a line
1167
* between them depending on "rule", aligns the numerator and
1168
* denominator in comparison with each other (indicated by numAlign and denomAlign)
1169
* and changes the current TeXFormula into this resulting fraction.
1171
* @param s the string to be parsed into a TeXFormula that will represent the
1172
* numerator of the fraction
1173
* @param rule whether a line should be drawn between numerator and denominator
1174
* @param numAlign an alignment constant (from {@link TeXConstants}) indicating
1175
* how the numerator should be aligned in comparison with the (larger)
1177
* @param denomAlign an alignment constant (from TeXConstants) indicating
1178
* how the denominator should be aligned in comparison with the (larger)
1180
* @return the modified TeXFormula
1181
* @throws ParseException if the string could not be parsed correctly
1183
public TeXFormula fractionInvert(String s, boolean rule, int numAlign,
1184
int denomAlign) throws ParseException {
1185
return fractionInvert(new TeXFormula(s), rule, numAlign, denomAlign);
1189
* Uses the current TeXFormula as the denominator of a fraction, the given TeXFormula
1190
* as the numerator of the fraction, draws a line between them depending on "rule"
1191
* and changes the current TeXFormula into this resulting fraction.
1193
* @param f the TeXFormula that will represent the
1194
* numerator of the fraction
1195
* @param rule whether a line should be drawn between numerator and denominator
1196
* @return the modified TeXFormula
1198
public TeXFormula fractionInvert(TeXFormula f, boolean rule) {
1199
root = new FractionAtom((f == null ? null : f.root), root, rule);
1204
* Uses the current TeXFormula as the denominator of a fraction, the given TeXFormula
1205
* as the numerator of the fraction, draws a line between them depending on "rule",
1206
* aligns the numerator and denominator in comparison with
1207
* each other (indicated by numAlign and denomAlign) and changes the current
1208
* TeXFormula into this resulting fraction.
1210
* @param f the TeXFormula that will represent the
1211
* numerator of the fraction
1212
* @param rule whether a line should be drawn between numerator and denominator
1213
* @param numAlign an alignment constant (from {@link TeXConstants}) indicating
1214
* how the numerator should be aligned in comparison with the (larger)
1216
* @param denomAlign an alignment constant (from TeXConstants) indicating
1217
* how the denominator should be aligned in comparison with the (larger)
1219
* @return the modified TeXFormula
1221
public TeXFormula fractionInvert(TeXFormula f, boolean rule, int numAlign,
1223
root = new FractionAtom((f == null ? null : f.root), root, rule,
1224
numAlign, denomAlign);
1229
* Get the next group (between the given opening and closing characters)
1230
* at the current position in the parse string, return it as a string and
1231
* adjust the current position (after the group).
1233
private String getGroup(char open, char close) throws ParseException {
1235
if (pos < parseString.length()) {
1236
char ch = parseString.charAt(pos);
1239
StringBuffer buf = new StringBuffer();
1240
while (pos < parseString.length()
1241
&& !(parseString.charAt(pos) == close && group == 0)) {
1242
if (parseString.charAt(pos) == open)
1244
else if (parseString.charAt(pos) == close)
1246
buf.append(parseString.charAt(pos));
1249
if (pos == parseString.length())
1250
// end of string reached, but not processed properly
1251
throw new ParseException("Illegal end, missing '" + close
1253
else { // end of group
1255
return buf.toString();
1258
throw new ParseException("missing '" + open + "'!");
1260
// end of string reached, but not processed properly
1261
throw new ParseException("Illegal end, missing '" + close + "'!");
1265
* Get the next script at the current position in the parse string.
1266
* If a group opening character is found, this is the next group, otherwise
1267
* the next character. Parse it, return it as a TeXFormula and adjust
1268
* the current position.
1270
private TeXFormula getScript() throws ParseException {
1273
if (pos < parseString.length()) {
1274
ch = parseString.charAt(pos);
1275
if (ch == L_GROUP) {
1276
return new TeXFormula(getGroup(L_GROUP, R_GROUP));
1279
return new TeXFormula(Character.toString(ch));
1282
// end of string reached, but not processed properly
1283
throw new ParseException("illegal end, missing script!");
1287
* Changes this TeXFormula into a phantom TeXFormula. It will be rendered invisibly.
1288
* This means that a strut box (whitespace) will be displayed instead of the current
1289
* TeXFormula, with the same width, height and depth as the current TeXFormula's
1290
* box would have. Although this formula is now made invisible, it's
1291
* still treated as a normal visible formula when it comes to inserting glue.
1293
* @return the modified TeXFormula
1295
public TeXFormula makePhantom() {
1296
root = new PhantomAtom(root);
1301
* Changes this TeXFormula into a phantom TeXFormula. Only the dimensions set to true will be taken into
1302
* account for drawing the whitespace. Although this formula is now made invisible, it's
1303
* still treated as a normal visible formula when it comes to inserting glue.
1305
* @param width whether the width of the TeXFormula's box should be used (<-> width 0)
1306
* @param height whether the height of the TeXFormula's box should be used (<-> height 0)
1307
* @param depth whether the depth of the TeXFormula's box should be used (<-> depth 0)
1308
* @return the modified TeXFormula
1310
public TeXFormula makePhantom(boolean width, boolean height, boolean depth) {
1311
root = new PhantomAtom(root, width, height, depth);
1316
* Parses the given string into a TeXFormula, puts it in the upper
1317
* left corner over a root sign (nthRoot), puts the current TeXFormula under this
1318
* root sign and changes the current TeXFormula into this resulting root construction.
1320
* @param nthRoot the string to be parsed into a TeXFormula that will be put
1321
* in the upper left corner over the root sign
1322
* @return the modified TeXFormula
1323
* @throws ParseException if the string could not be parsed correctly
1325
public TeXFormula nthRoot(String nthRoot) throws ParseException {
1326
return nthRoot(new TeXFormula(nthRoot));
1330
* Puts the given TeXFormula in the upper left corner over a root sign, puts the
1331
* current TeXFormula under this root sign and changes the current TeXFormula
1332
* into this resulting root construction.
1334
* @param nthRoot the TeXFormula that will be put
1335
* in the upper left corner over the root sign
1336
* @return the modified TeXFormula
1338
public TeXFormula nthRoot(TeXFormula nthRoot) {
1339
root = new NthRoot(root, (nthRoot == null ? null : nthRoot.root));
1344
* Puts a line over the current TeXFormula and changes the current TeXFormula into
1345
* the resulting construction.
1347
* @return the modified TeXFormula
1349
public TeXFormula overline() {
1350
root = new OverlinedAtom(root);
1355
* Starts parsing the given string (at position 0).
1357
private void parse(String s) throws ParseException {
1359
if (parseString.length() != 0) {
1360
while (pos < parseString.length()) {
1361
char ch = parseString.charAt(pos);
1362
if (isWhiteSpace(ch))
1363
pos++; // ignore white space
1364
else if (ch == ESCAPE)
1366
else if (ch == L_GROUP)
1367
add(attachScripts(new TeXFormula(getGroup(L_GROUP, R_GROUP)).root));
1368
else if (ch == R_GROUP)
1369
throw new ParseException("Found a closing '" + R_GROUP
1370
+ "' without an opening '" + L_GROUP + "'!");
1371
else if (ch == SUPER_SCRIPT || ch == SUB_SCRIPT || ch == PRIME) // ' = ^{\prime...
1372
if (pos == 0) // first character
1373
throw new ParseException("Every script needs a base: \""
1374
+ SUPER_SCRIPT + "\", \"" + SUB_SCRIPT + "\" and \""
1375
+ PRIME + "\" can't be the first character!");
1377
throw new ParseException(
1378
"Double scripts found! Try using more braces.");
1380
add(attachScripts(convertCharacter(ch)));
1386
* Processes the given TeX command (by parsing following command arguments
1387
* in the parse string).
1389
private Atom processCommands(String command) throws ParseException {
1391
if ("frac".equals(command)) {
1392
TeXFormula num = new TeXFormula(getGroup(L_GROUP, R_GROUP));
1394
TeXFormula denom = new TeXFormula(getGroup(L_GROUP, R_GROUP));
1395
if (num.root == null || denom.root == null)
1396
throw new ParseException(
1397
"Both numerator and denominator of a fraction can't be empty!");
1398
return new FractionAtom(num.root, denom.root, true);
1401
if (pos == parseString.length())
1402
// end of string reached, but not processed properly
1403
throw new ParseException("illegal end!");
1405
TeXFormula nRoot = new TeXFormula();
1406
if (parseString.charAt(pos) == L_BRACK) { // n-th root
1407
nRoot = new TeXFormula(getGroup(L_BRACK, R_BRACK));
1410
return new NthRoot(new TeXFormula(getGroup(L_GROUP, R_GROUP)).root,
1417
* Tries to find a TeX command or TeX symbol name at the current position
1418
* in the parse string (just after an escape character was found).
1420
private void processEscape() throws ParseException {
1422
StringBuffer buf = new StringBuffer();
1423
// no longer symbol name or predefined TeXFormula name possible
1424
boolean endOfEscape = false;
1425
// temporarily save symbol
1426
SymbolAtom symbolFound = null;
1428
// temporarily save predefined TeXFormula
1429
TeXFormula predefFound = null;
1431
// what was the longest match: symbol or predefined TeXFormula?
1432
boolean symbolLongest = true;
1434
while (pos < parseString.length()) {
1435
char ch = parseString.charAt(pos);
1436
boolean isEnd = (pos == parseString.length() - 1);
1438
// the following characters can't be part of a command or symbol, so
1439
// if there's no command or symbol found, then an exception is
1441
if (isWhiteSpace(ch) || ch == ESCAPE || ch == SUB_SCRIPT
1442
|| ch == SUPER_SCRIPT || isEnd) {
1453
String command = buf.toString();
1455
SymbolAtom s = null;
1456
TeXFormula predef = null;
1457
try { // check if 'command' is a valid symbolname
1458
s = SymbolAtom.get(command);
1459
} catch (SymbolNotFoundException e) { // symbol not found
1460
// check if a predefined TeXFormula exists with that name
1462
predef = TeXFormula.get(command);
1463
} catch (FormulaNotFoundException e1) {
1464
predef = null; // none found
1468
if (s != null) { // symbol found! // NOPMD
1470
// no longer symbol name or predefined TeXFormula name possible
1471
add(attachScripts(s));
1473
} else { // could be part of another valid symbolname, like "in" and "infty"
1476
symbolLongest = true;
1478
} else if (predef != null) { // predefined TeXFormula found! // NOPMD
1480
// no longer symbol name or predefined TeXFormula name possible
1481
add(attachScripts(predef.root));
1483
} else { // could be part of another valid symbolname, like "in" and "infty"
1484
predefFound = predef;
1486
symbolLongest = false;
1488
} else if ("nbsp".equals(command)) { // space found (for MathML-purposes!)
1489
add(attachScripts(new SpaceAtom()));
1491
} else if (textStyles.contains(command)) { // textstyle found
1493
add(attachScripts(new TeXFormula(getGroup(L_GROUP, R_GROUP),
1496
} else if (commands.contains(command)) { // command found
1497
add(attachScripts(processCommands(command)));
1499
} else if (endOfEscape) { // searching is over
1500
if (symbolLongest && symbolFound != null) {
1501
// go back to that position and add that symbol
1503
add(attachScripts(symbolFound));
1505
} else if (!symbolLongest && predefFound != null) { // NOPMD
1506
// go back to that position and add that predefined TeXFormula
1508
add(attachScripts(predefFound.root));
1511
// not a valid command or symbol or predefined TeXFormula found
1512
throw new ParseException(
1513
"Unknown symbol or command or predefined TeXFormula: '"
1518
// escape-char found at the end of the string
1519
throw new ParseException("The escape-character '" + ESCAPE
1520
+ "' can't be the last one!");
1524
* Puts the given accent above the current TeXFormula and changes the current
1525
* TeXFormula into the resulting accent construction.
1527
* @param accentName the name of the accent symbol
1528
* @return the modified TeXFormula
1529
* @throws InvalidSymbolTypeException if the symbol is not defined as an accent
1530
* @throws SymbolNotFoundException if there's no symbol defined with the given name
1532
public TeXFormula putAccentOver(String accentName)
1533
throws InvalidSymbolTypeException, SymbolNotFoundException {
1534
root = new AccentedAtom(root, accentName);
1539
* Puts the delimiter symbol represented by the given delimiter type constant above the
1540
* current TeXFormula and changes the current TeXFormula into the resulting construction.
1542
* @param delimiter a delimiter type constant (from {@link TeXConstants}) that represents
1543
* a delimiter symbol that will be put above the current TeXFormula
1544
* @return the modified TeXFormula
1545
* @throws InvalidDelimiterTypeException if the given integer value does not represent
1546
* a valid delimiter type
1547
* @throws SymbolNotFoundException if the definition of the symbol represented
1548
* by the delimiter constant was not found (due to user-made changes!)
1550
public TeXFormula putDelimiterOver(int delimiter)
1551
throws InvalidDelimiterTypeException, SymbolNotFoundException {
1552
if (delimiter < 0 || delimiter >= delimiterNames.length)
1553
throw new InvalidDelimiterTypeException();
1555
String name = delimiterNames[delimiter][OVER_DEL];
1556
root = new OverUnderDelimiter(root, null, SymbolAtom.get(name),
1557
TeXConstants.UNIT_EX, 0, true);
1562
* Puts the delimiter symbol represented by the given delimiter type constant above the
1563
* current TeXFormula, parses the given string into a TeXFormula and
1564
* puts it above the delimiter symbol (seperated by an amount of vertical space defined
1565
* by the given float value and unit) in a smaller size (unless the current TeXFormula
1566
* will be displayed in the smallest possible size: the script_script style's size)
1567
* and finally changes the current TeXFormula into the resulting construction.
1569
* @param delimiter a delimiter type constant (from {@link TeXConstants}) that represents
1570
* a delimiter symbol that will be put above the current TeXFormula
1571
* @param sup the string to be parsed into a TeXFormula that will be put above the
1572
* delimiter symbol, in a smaller size if possible
1573
* @param kernUnit a unit constant (from {@link TeXConstants})
1574
* @param kern amount of vertical space (in kernUnit) to be put between the delimiter
1575
* and the given TeXFormula sub
1576
* @return the modified TeXFormula
1577
* @throws InvalidDelimiterTypeException if the given integer value does not represent
1578
* a valid delimiter type
1579
* @throws InvalidUnitException if the given integer value (kernUnit) does not
1580
* represent a valid unit
1581
* @throws ParseException if the given string could not be parsed correctly
1582
* @throws SymbolNotFoundException if the definition of the symbol represented
1583
* by the delimiter constant was not found (due to user-made changes!)
1585
public TeXFormula putDelimiterOver(int delimiter, String sup, int kernUnit,
1586
float kern) throws InvalidDelimiterTypeException,
1587
InvalidUnitException, ParseException, SymbolNotFoundException {
1588
return putDelimiterOver(delimiter, new TeXFormula(sup), kernUnit, kern);
1592
* Puts the delimiter symbol represented by the given delimiter type constant above the
1593
* current TeXFormula, puts the given TeXFormula above the delimiter symbol (seperated
1594
* by an amount of vertical space defined by the given float value and unit) in a
1595
* smaller size (unless the current TeXFormula will be displayed in the smallest
1596
* possible size: the "script_script" style's size) and finally changes the current
1597
* TeXFormula into the resulting construction.
1599
* @param delimiter a delimiter type constant (from {@link TeXConstants}) that represents
1600
* a delimiter symbol that will be put above the current TeXFormula
1601
* @param sup the TeXFormula that will be put above the
1602
* delimiter symbol, in a smaller size if possible
1603
* @param kernUnit a unit constant (from {@link TeXConstants})
1604
* @param kern amount of vertical space (in kernUnit) to be put between the delimiter
1605
* and the given TeXFormula sub
1606
* @return the modified TeXFormula
1607
* @throws InvalidDelimiterTypeException if the given integer value does not represent
1608
* a valid delimiter type
1609
* @throws InvalidUnitException if the given integer value (kernUnit) does not
1610
* represent a valid unit
1611
* @throws SymbolNotFoundException if the definition of the symbol represented
1612
* by the delimiter constant was not found (due to user-made changes!)
1614
public TeXFormula putDelimiterOver(int delimiter, TeXFormula sup,
1615
int kernUnit, float kern) throws InvalidDelimiterTypeException,
1616
InvalidUnitException, SymbolNotFoundException {
1617
if (delimiter < 0 || delimiter >= delimiterNames.length)
1618
throw new InvalidDelimiterTypeException();
1620
String name = delimiterNames[delimiter][OVER_DEL];
1621
root = new OverUnderDelimiter(root, (sup == null ? null : sup.root),
1622
SymbolAtom.get(name), kernUnit, kern, true);
1627
* Puts the delimiter symbol represented by the given delimiter type constant under the
1628
* current TeXFormula and changes the current
1629
* TeXFormula into the resulting construction.
1631
* @param delimiter a delimiter type constant (from {@link TeXConstants}) that represents
1632
* a delimiter symbol that will be put under the current TeXFormula
1633
* @return the modified TeXFormula
1634
* @throws InvalidDelimiterTypeException if the given integer value does not represent
1635
* a valid delimiter type
1636
* @throws SymbolNotFoundException if the definition of the symbol represented
1637
* by the delimiter constant was not found (due to user-made changes!)
1639
public TeXFormula putDelimiterUnder(int delimiter)
1640
throws InvalidDelimiterTypeException, SymbolNotFoundException {
1641
if (delimiter < 0 || delimiter >= delimiterNames.length)
1642
throw new InvalidDelimiterTypeException();
1644
String name = delimiterNames[delimiter][UNDER_DEL];
1645
root = new OverUnderDelimiter(root, null, SymbolAtom.get(name),
1646
TeXConstants.UNIT_EX, 0, false);
1651
* Puts the delimiter symbol represented by the given delimiter type constant under the
1652
* current TeXFormula, parses the given string into a TeXFormula and puts
1653
* it under the delimiter symbol (seperated by an amount of vertical space defined
1654
* by the given float value and unit) in a smaller size (unless the current TeXFormula
1655
* will be displayed in the smallest possible size: the script_script style's size)
1656
* and finally changes the current TeXFormula into the resulting construction.
1658
* @param delimiter a delimiter type constant (from {@link TeXConstants}) that represents
1659
* a delimiter symbol that will be put under the current TeXFormula
1660
* @param sub the string to be parsed into a TeXFormula that will be put under the
1661
* delimiter symbol, in a smaller size if possible
1662
* @param kernUnit a unit constant (from {@link TeXConstants})
1663
* @param kern amount of vertical space (in kernUnit) to be put between the delimiter
1664
* and the given TeXFormula sub
1665
* @return the modified TeXFormula
1666
* @throws InvalidDelimiterTypeException if the given integer value does not represent
1667
* a valid delimiter type
1668
* @throws InvalidUnitException if the given integer value (kernUnit) does not
1669
* represent a valid unit
1670
* @throws ParseException if the given string could not be parsed correctly
1671
* @throws SymbolNotFoundException if the definition of the symbol represented
1672
* by the delimiter constant was not found (due to user-made changes!)
1674
public TeXFormula putDelimiterUnder(int delimiter, String sub, int kernUnit,
1675
float kern) throws InvalidDelimiterTypeException,
1676
InvalidUnitException, ParseException, SymbolNotFoundException {
1677
return putDelimiterUnder(delimiter, new TeXFormula(sub), kernUnit, kern);
1681
* Puts the delimiter symbol represented by the given delimiter type constant under the
1682
* current TeXFormula, puts the given TeXFormula under the delimiter symbol (seperated
1683
* by an amount of vertical space defined by the given float value and unit) in a
1684
* smaller size (unless the current TeXFormula will be displayed in the smallest
1685
* possible size: the "script_script" style's size) and finally changes the current
1686
* TeXFormula into the resulting construction.
1688
* @param delimiter a delimiter type constant (from {@link TeXConstants}) that represents
1689
* a delimiter symbol that will be put under the current TeXFormula
1690
* @param sub the TeXFormula that will be put under the
1691
* delimiter symbol, in a smaller size if possible
1692
* @param kernUnit a unit constant (from {@link TeXConstants})
1693
* @param kern amount of vertical space (in kernUnit) to be put between the delimiter
1694
* and the given TeXFormula sub
1695
* @return the modified TeXFormula
1696
* @throws InvalidDelimiterTypeException if the given integer value (delimiter)
1697
* does not represent a valid delimiter type
1698
* @throws InvalidUnitException if the given integer value (kernUnit) does not
1699
* represent a valid unit
1700
* @throws SymbolNotFoundException if the definition of the symbol represented
1701
* by the delimiter constant was not found (due to user-made changes!)
1703
public TeXFormula putDelimiterUnder(int delimiter, TeXFormula sub,
1704
int kernUnit, float kern) throws InvalidDelimiterTypeException,
1705
InvalidUnitException, SymbolNotFoundException {
1706
if (delimiter < 0 || delimiter >= delimiterNames.length)
1707
throw new InvalidDelimiterTypeException();
1709
String name = delimiterNames[delimiter][UNDER_DEL];
1710
root = new OverUnderDelimiter(root, (sub == null ? null : sub.root),
1711
SymbolAtom.get(name), kernUnit, kern, false);
1716
* Puts the given TeXFormula
1717
* above the current TeXFormula, in a smaller size
1718
* depending on "overScriptSize" and seperated by a vertical space of size
1719
* "overSpace" in "overUnit" and changes the current TeXFormula into the
1720
* resulting construction.
1722
* @param over the TeXFormula to be put over the current TeXFormula
1723
* @param overUnit a unit constant (from TeXConstants)
1724
* @param overSpace the size (in overUnit) of the vertical space between the
1725
* current TeXFormula and the TeXFormula (over) that will be put over it
1726
* @param overScriptSize whether the TeXFormula (over) that will be put over the
1727
* current TeXFormula should be displayed in a smaller size (if possible)
1728
* @return the modified TeXFormula
1729
* @throws InvalidUnitException if the given unit integer values doesn't
1730
* represent a valid unit
1732
public TeXFormula putOver(TeXFormula over, int overUnit, float overSpace,
1733
boolean overScriptSize) throws InvalidUnitException {
1734
root = new UnderOverAtom(root, (over == null ? null : over.root),
1735
overUnit, overSpace, overScriptSize, true);
1740
* Parses the given string into a TeXFormula that will be put
1742
* TeXFormula, in a smaller size
1743
* depending on "overScriptSize" and seperated by a vertical space of size
1744
* "overSpace" in "overUnit" and changes the current TeXFormula into the
1745
* resulting construction.
1747
* @param over the string to be parsed into a TeXFormula that will be put over the
1748
* current TeXFormula
1749
* @param overUnit a unit constant (from TeXConstants)
1750
* @param overSpace the size (in overUnit) of the vertical space between the
1751
* current TeXFormula and the TeXFormula (over) that will be put over it
1752
* @param overScriptSize whether the TeXFormula (over) that will be put over the
1753
* current TeXFormula should be displayed in a smaller size (if possible)
1754
* @return the modified TeXFormula
1755
* @throws InvalidUnitException if one of the given unit integer values doesn't
1756
* represent a valid unit
1757
* @throws parseException if the given string could not be parsed correctly
1759
public TeXFormula putOver(String over, int overUnit, float overSpace,
1760
boolean overScriptSize) throws InvalidUnitException {
1761
return putOver((over == null ? null : new TeXFormula(over)), overUnit,
1762
overSpace, overScriptSize);
1766
* Parses the given string into a TeXFormula that will be put
1767
* under the current TeXFormula,
1769
* depending on "underScriptSize" and seperated by a
1770
* vertical space of size "underSpace" in "underUnit" and changes the current
1771
* TeXFormula into the resulting construction.
1773
* @param under the string to be parsed into a TeXFormula that will be put under
1774
* the current TeXFormula, or null to put nothing under it
1775
* @param underUnit a unit constant (from {@link TeXConstants})
1776
* @param underSpace the size (in underUnit) of the vertical space between the
1777
* current TeXFormula and the TeXFormula (under) that will be put under it
1778
* @param underScriptSize whether the TeXFormula (under) that will be put under the
1779
* current TeXFormula should be displayed in a smaller size (if possible)
1780
* @return the modified TeXFormula
1781
* @throws InvalidUnitException if one of the given unit integer values doesn't
1782
* represent a valid unit
1783
* @throws parseException if the given string could not be parsed correctly
1785
public TeXFormula putUnder(String under, int underUnit, float underSpace,
1786
boolean underScriptSize) throws InvalidUnitException {
1787
return putUnder((under == null ? null : new TeXFormula(under)),
1788
underUnit, underSpace, underScriptSize);
1792
* Puts the given TeXFormula under the current TeXFormula,
1794
* depending on "underScriptSize" and seperated by a
1795
* vertical space of size "underSpace" in "underUnit" and changes the current
1796
* TeXFormula into the resulting construction.
1798
* @param under the TeXFormula to be put under the current TeXFormula
1799
* @param underUnit a unit constant (from {@link TeXConstants})
1800
* @param underSpace the size (in underUnit) of the vertical space between the
1801
* current TeXFormula and the TeXFormula (under) that will be put under it
1803
* @param underScriptSize whether the TeXFormula (under) that will be put under the
1804
* current TeXFormula should be displayed in a smaller size (if possible)
1805
* @return the modified TeXFormula
1806
* @throws InvalidUnitException if the given unit integer values doesn't
1807
* represent a valid unit
1809
public TeXFormula putUnder(TeXFormula under, int underUnit,
1810
float underSpace, boolean underScriptSize) throws InvalidUnitException {
1811
root = new UnderOverAtom(root, (under == null ? null : under.root),
1812
underUnit, underSpace, underScriptSize, false);
1817
* Parses the given string "under" into a TeXFormula that will be put
1818
* under the current TeXFormula,
1820
* depending on "underScriptSize" and seperated by a
1821
* vertical space of size "underSpace" in "underUnit", parses the given string
1822
* "over" into a TeXFormula that will be put above the current
1823
* TeXFormula, in a smaller size
1824
* depending on "overScriptSize" and seperated by a vertical space of size
1825
* "overSpace" in "overUnit" and finally changes the current TeXFormula into the
1826
* resulting construction.
1828
* @param under the string to be parsed into a TeXFormula that will be put under
1829
* the current TeXFormula, or null to put nothing under it
1830
* @param underUnit a unit constant (from {@link TeXConstants})
1831
* @param underSpace the size (in underUnit) of the vertical space between the
1832
* current TeXFormula and the TeXFormula (under) that will be put under it
1833
* @param underScriptSize whether the TeXFormula (under) that will be put under the
1834
* current TeXFormula should be displayed in a smaller size (if possible)
1835
* @param over the string to be parsed into a TeXFormula that will be put over the
1836
* current TeXFormula, or null to put nothing over it
1837
* @param overUnit a unit constant (from TeXConstants)
1838
* @param overSpace the size (in overUnit) of the vertical space between the
1839
* current TeXFormula and the TeXFormula (over) that will be put over it
1840
* @param overScriptSize whether the TeXFormula (over) that will be put over the
1841
* current TeXFormula should be displayed in a smaller size (if possible)
1842
* @return the modified TeXFormula
1843
* @throws InvalidUnitException if one of the given unit integer values doesn't
1844
* represent a valid unit
1845
* @throws parseException if one of the given strings could not be parsed correctly
1847
public TeXFormula putUnderAndOver(String under, int underUnit,
1848
float underSpace, boolean underScriptSize, String over, int overUnit,
1849
float overSpace, boolean overScriptSize) throws InvalidUnitException,
1851
return putUnderAndOver((under == null ? null : new TeXFormula(under)),
1852
underUnit, underSpace, underScriptSize, (over == null ? null
1853
: new TeXFormula(over)), overUnit, overSpace, overScriptSize);
1857
* Puts the given TeXFormula "under" under the current TeXFormula,
1859
* depending on "underScriptSize" and seperated by a
1860
* vertical space of size "underSpace" in "underUnit", puts the given TeXFormula
1861
* "over" above the current TeXFormula, in a smaller size
1862
* depending on "overScriptSize" and seperated by a vertical space of size
1863
* "overSpace" in "overUnit" and finally changes the current TeXFormula into the
1864
* resulting construction.
1866
* @param under the TeXFormula to be put under the current TeXFormula
1867
* @param underUnit a unit constant (from {@link TeXConstants})
1868
* @param underSpace the size (in underUnit) of the vertical space between the
1869
* current TeXFormula and the TeXFormula (under) that will be put under it
1870
* @param underScriptSize whether the TeXFormula (under) that will be put under the
1871
* current TeXFormula should be displayed in a smaller size (if possible)
1872
* @param over the TeXFormula to be put over the current TeXFormula
1873
* @param overUnit a unit constant (from TeXConstants)
1874
* @param overSpace the size (in overUnit) of the vertical space between the
1875
* current TeXFormula and the TeXFormula (over) that will be put over it
1876
* @param overScriptSize whether the TeXFormula (over) that will be put over the
1877
* current TeXFormula should be displayed in a smaller size (if possible)
1878
* @return the modified TeXFormula
1879
* @throws InvalidUnitException if one of the given unit integer values doesn't
1880
* represent a valid unit
1882
public TeXFormula putUnderAndOver(TeXFormula under, int underUnit,
1883
float underSpace, boolean underScriptSize, TeXFormula over,
1884
int overUnit, float overSpace, boolean overScriptSize)
1885
throws InvalidUnitException {
1886
root = new UnderOverAtom(root, (under == null ? null : under.root),
1887
underUnit, underSpace, underScriptSize, (over == null ? null
1888
: over.root), overUnit, overSpace, overScriptSize);
1893
* Replaces "'" with "^{\prime}", "''" with "^{\prime\prime}", etc. at the
1894
* current position in the parse string.
1896
private void replaceAccents() {
1897
StringBuffer buf = new StringBuffer(SUPER_SCRIPT);
1898
buf.append(L_GROUP);
1899
buf.append("\\prime");
1901
while (i < parseString.length()) {
1902
if (parseString.charAt(i) == PRIME)
1903
buf.append("\\prime");
1904
else if (!isWhiteSpace(parseString.charAt(i)))
1908
buf.append(R_GROUP);
1909
// construct the new parsing string
1910
parseString = parseString.substring(0, pos) + buf.toString()
1911
+ parseString.substring(i);
1915
* Changes the background color of the <i>current</i> TeXFormula into the given color.
1916
* By default, a TeXFormula has no background color, it's transparent.
1917
* The backgrounds of subformula's will be painted on top of the background of
1918
* the whole formula! Any changes that will be made to this TeXFormula after this
1919
* background color was set, will have the default background color (unless it will
1920
* also be changed into another color afterwards)!
1922
* @param c the desired background color for the <i>current</i> TeXFormula
1923
* @return the modified TeXFormula
1925
public TeXFormula setBackground(Color c) {
1927
if (root instanceof ColorAtom)
1928
root = new ColorAtom(c, null, (ColorAtom) root);
1930
root = new ColorAtom(root, c, null);
1936
* Changes the (foreground) color of the <i>current</i> TeXFormula into the given color.
1937
* By default, the foreground color of a TeXFormula is the foreground color of the
1938
* component on which the TeXIcon (created from this TeXFormula) will be painted. The
1939
* color of subformula's overrides the color of the whole formula.
1940
* Any changes that will be made to this TeXFormula after this color was set, will be
1941
* painted in the default color (unless the color will also be changed afterwards into
1944
* @param c the desired foreground color for the <i>current</i> TeXFormula
1945
* @return the modified TeXFormula
1947
public TeXFormula setColor(Color c) {
1949
if (root instanceof ColorAtom)
1950
root = new ColorAtom(null, c, (ColorAtom) root);
1952
root = new ColorAtom(root, null, c);
1958
* Sets a fixed left and right type of the current TeXFormula. This has an influence
1959
* on the glue that will be inserted before and after this TeXFormula.
1961
* @param leftType atom type constant (from {@link TeXConstants})
1962
* @param rightType atom type constant (from TeXConstants)
1963
* @return the modified TeXFormula
1964
* @throws InvalidAtomTypeException if the given integer value does not represent
1967
public TeXFormula setFixedTypes(int leftType, int rightType)
1968
throws InvalidAtomTypeException {
1969
root = new TypedAtom(leftType, rightType, root);
1974
* Parses the given strings into TeXFormula's and attaches them <i>together</i> to
1975
* the <i>current</i> TeXFormula as a subscript (sub) and a superscript (sup).
1977
* same as attaching both scripts seperately one after another (in either order) using
1978
* the setSubscript(String) and the setSuperscript(String) methods!
1980
* @param sub the string to be parsed into a TeXFormula that will be attached to
1981
* the current TeXFormula as a subscript
1982
* @param sup the string to be parsed into a TeXFormula that will be attached to
1983
* the current TeXFormula as a superscript
1984
* @return the modified TeXFormula
1985
* @throws ParseException if one of the given strings could not be parsed correctly
1987
public TeXFormula setScripts(String sub, String sup) throws ParseException {
1988
return setScripts(new TeXFormula(sub), new TeXFormula(sup));
1992
* Parses the given string into a TeXFormula's and attaches it to
1993
* the <i>current</i> TeXFormula as a subscript <i>together</i> with the given
1995
* (as a superscript). This is not the same as attaching both scripts seperately
1996
* one after another (in either order) using the setSubscript(String)
1997
* and the setSuperscript(TeXFormula) methods!
1999
* @param sub the string to be parsed into a TeXFormula that will be attached to
2000
* the current TeXFormula as a subscript
2001
* @param sup the TeXFormula that will be attached to
2002
* the current TeXFormula as a superscript
2003
* @return the modified TeXFormula
2004
* @throws ParseException if the given string could not be parsed correctly
2006
public TeXFormula setScripts(String sub, TeXFormula sup)
2007
throws ParseException {
2008
return setScripts(new TeXFormula(sub), sup);
2012
* Parses the given string into a TeXFormula's and attaches it to
2013
* the <i>current</i> TeXFormula as a superscript <i>together</i> with the given TeXFormula
2014
* (as a subscript). This is not the same as attaching both scripts seperately
2015
* one after another (in either order) using the setSubscript(TeXFormula)
2016
* and the setSuperscript(String) methods!
2018
* @param sub the TeXFormula that will be attached to
2019
* the current TeXFormula as a subscript
2020
* @param sup the string to be parsed into a TeXFormula that will be attached to
2021
* the current TeXFormula as a superscript
2022
* @return the modified TeXFormula
2023
* @throws ParseException if the given string could not be parsed correctly
2025
public TeXFormula setScripts(TeXFormula sub, String sup)
2026
throws ParseException {
2027
return setScripts(sub, new TeXFormula(sup));
2031
* Attaches the given TeXFormula's <i>together</i> to the <i>current</i> TeXFormula as a subscript
2032
* (sub) and a superscript (sup). This is not the same as attaching both scripts seperately
2033
* one after another (in either order) using the setSubscript(TeXFormula)
2034
* and the setSuperscript(TeXFormula) methods!
2036
* @param sub the TeXFormula that will be attached to
2037
* the current TeXFormula as a subscript
2038
* @param sup the TeXFormula that will be attached to
2039
* the current TeXFormula as a superscript
2040
* @return the modified TeXFormula
2042
public TeXFormula setScripts(TeXFormula sub, TeXFormula sup) {
2043
root = new ScriptsAtom(root, (sub == null ? null : sub.root),
2044
(sup == null ? null : sup.root));
2049
* Parses the given string into a TeXFormula and attaches it to the <i>current</i>
2050
* TeXFormula as a subscript.
2052
* @param sub the string to be parsed into a TeXFormula that will be attached
2053
* to the current TeXFormula as a subscript
2054
* @return the modified TeXFormula
2055
* @throws ParseException if the given string could not be parsed correctly
2057
public TeXFormula setSubscript(String sub) throws ParseException {
2058
return setSubscript(new TeXFormula(sub));
2062
* Attaches the given TeXFormula to the <i>current</i> TeXFormula as a subscript.
2064
* @param sub the TeXFormula that will be attached
2065
* to the current TeXFormula as a subscript
2066
* @return the modified TeXFormula
2068
public TeXFormula setSubscript(TeXFormula sub) {
2069
root = new ScriptsAtom(root, (sub == null ? null : sub.root), null);
2074
* Parses the given string into a TeXFormula and attaches it to the <i>current</i>
2075
* TeXFormula as a superscript.
2077
* @param sup the string to be parsed into a TeXFormula that will be attached
2078
* to the current TeXFormula as a superscript
2079
* @return the modified TeXFormula
2080
* @throws ParseException if the given string could not be parsed correctly
2082
public TeXFormula setSuperscript(String sup) throws ParseException {
2083
return setSuperscript(new TeXFormula(sup));
2087
* Attaches the given TeXFormula to the <i>current</i> TeXFormula as a superscript.
2089
* @param sup the TeXFormula that will be attached
2090
* to the current TeXFormula as a superscript
2091
* @return the modified TeXFormula
2093
public TeXFormula setSuperscript(TeXFormula sup) {
2094
root = new ScriptsAtom(root, null, (sup == null ? null : sup.root));
2099
* change the current position (in the parse string) to the first following
2100
* non-whitespace character
2102
private void skipWhiteSpace() {
2103
while (pos < parseString.length()
2104
&& isWhiteSpace(parseString.charAt(pos)))
2109
* Puts the current TeXFormula under a root sign and changes the current TeXFormula
2110
* into the resulting square root construction.
2112
* @return the modified TeXFormula
2114
public TeXFormula sqrt() {
2115
return nthRoot((TeXFormula) null);
2119
* Puts a line under the current TeXFormula and changes the current TeXFormula into
2120
* the resulting construction.
2122
* @return the modified TeXFormula
2124
public TeXFormula underline() {
2125
root = new UnderlinedAtom(root);
2130
* Get a predefined TeXFormula.
2132
* @param name the name of the predefined TeXFormula
2133
* @return a copy of the predefined TeXFormula
2134
* @throws FormulaNotFoundException if no predefined TeXFormula is found with the
2137
public static TeXFormula get(String name) throws FormulaNotFoundException {
2138
Object formula = predefinedTeXFormulas.get(name);
2139
if (formula == null)
2140
throw new FormulaNotFoundException(name);
2142
return new TeXFormula((TeXFormula) formula);
2146
* Retrieves the delimiter mapping (a symbol name) of the given character
2147
* from a hash table.
2149
private static String getCharacterToDelimiterMapping(char ch)
2150
throws DelimiterMappingNotFoundException {
2151
String str = delimiterMappings[ch];
2153
throw new DelimiterMappingNotFoundException(ch);
2159
* Retrieves the delimiter symbol with the given name from a hash table
2160
* and checks if it's a valid delimiter.
2162
private static SymbolAtom getDelimiterSymbol(String delName)
2163
throws SymbolNotFoundException, InvalidDelimiterException {
2164
SymbolAtom res = null;
2165
// null means no delimiter
2166
if (delName != null) {
2167
res = SymbolAtom.get(delName);
2168
// check if the symbol is a delimiter
2169
if (!res.isDelimiter())
2170
throw new InvalidDelimiterException(delName);
2176
* Tests if the given character is a symbol character. A character is a
2177
* symbol character if it is not alphanumeric.
2179
private static boolean isSymbol(char c) {
2180
return !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
2184
* Tests if the given character is a whitespace character.
2186
private static boolean isWhiteSpace(char ch) {
2187
return (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');