Source code: jaxe/equations/element/MathElement.java
1 /*
2 Jaxe - Editeur XML en Java
3
4 Copyright (C) 2003 Observatoire de Paris-Meudon
5
6 Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier conformément aux dispositions de la Licence Publique Générale GNU, telle que publiée par la Free Software Foundation ; version 2 de la licence, ou encore (à votre choix) toute version ultérieure.
7
8 Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION A UN OBJET PARTICULIER. Pour plus de détail, voir la Licence Publique Générale GNU .
9
10 Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis.
11 */
12
13 package jaxe.equations.element;
14
15 import java.awt.*;
16 import java.awt.font.GlyphVector;
17 import java.util.Vector;
18 import java.util.Enumeration;
19
20 import org.xml.sax.ContentHandler;
21 import org.xml.sax.SAXException;
22 import org.xml.sax.helpers.AttributesImpl;
23
24 import jaxe.equations.MathBase;
25
26 /**
27 * The basic class the the math elements. From this class
28 * elements inherits.
29 *
30 * @author <a href="mailto:stephan@vern.chem.tu-berlin.de">Stephan Michels</a>
31 * @author <a href="mailto:sielaff@vern.chem.tu-berlin.de">Marco Sielaff</a>
32 * @version 1.5
33 */
34 public class MathElement
35 {
36
37 /** The URI from MathML */
38 public final static String URI = "http://www.w3.org/1998/Math/MathML";
39
40 /** The URI from SVG */
41 public final static String SVG_URI = "http://www.w3.org/2000/svg";
42
43 /** The URI from FO */
44 public final static String FO_URI = "http://www.w3.org/1999/XSL/Format";
45
46 private MathBase base;
47 private MathElement parent;
48 private int fontsize = 14;
49 private Vector childs = new Vector();
50
51 private StringBuffer text = new StringBuffer();
52
53 /**
54 * Creates a math element
55 *
56 * @param base The base for the math element tree
57 * @param fontsize The font size for this element
58 */
59 public MathElement(MathBase base, int fontsize)
60 {
61 setMathBase(base);
62 setParent(parent);
63 setFontSize(fontsize);
64 }
65
66 /**
67 * Creates a math element
68 *
69 * @param base The base for the math element tree
70 */
71 public MathElement(MathBase base)
72 {
73 setMathBase(base);
74 }
75
76 /**
77 * Creates a math element
78 */
79 public MathElement()
80 {
81 }
82
83 /**
84 * Add a math element as a child
85 *
86 * @param child Math element
87 */
88 public void addMathElement(MathElement child)
89 {
90 if (child != null)
91 {
92 childs.addElement(child);
93 child.setMathBase(base);
94 child.setParent(this);
95 child.setFontSize(fontsize);
96 }
97 }
98
99 /**
100 * Gets a child from this element
101 *
102 * @param index Index of the child
103 *
104 * @return The child
105 */
106 public MathElement getMathElement(int index)
107 {
108 if ((index>=0) && (index<childs.size()))
109 return (MathElement) childs.elementAt(index);
110 return null;
111 }
112
113 /**
114 * Returns the count of childs from this element
115 *
116 * @return Count of childs
117 */
118 public int getMathElementCount()
119 {
120 return childs.size();
121 }
122
123 /**
124 * Add the content of a String to this element
125 *
126 * @param text Text
127 */
128 public void addText(String text)
129 {
130 //String textdummy = text.trim();
131
132 for (int i = 0; i < text.length(); i++)
133 if (" \t\n\r".indexOf(text.charAt(i)) < 0)
134 this.text.append(text.charAt(i));
135 else if ((' ' == text.charAt(i)) && (i>0) && (' ' != text.charAt(i - 1)))
136 this.text.append(text.charAt(i));
137 }
138
139 /**
140 * Returns the text contentof this element
141 *
142 * @return Text content
143 */
144 public String getText()
145 {
146 return text.toString().trim();
147 }
148
149 /**
150 * Sets the base for this element
151 *
152 * @param base Math base
153 */
154 public void setMathBase(MathBase base)
155 {
156 this.base = base;
157 for (Enumeration e = childs.elements(); e.hasMoreElements(); )
158 ((MathElement) e.nextElement()).setMathBase(base);
159 }
160
161 /**
162 * Gets the math base
163 *
164 * @return Math base
165 */
166 public MathBase getMathBase()
167 {
168 return base;
169 }
170
171 /**
172 * Sets the parent of this element
173 *
174 * @param parent Parent element
175 */
176 public void setParent(MathElement parent)
177 {
178 this.parent = parent;
179 }
180
181 /**
182 * Returns get parent of this element
183 *
184 * @return Parent element
185 */
186 public MathElement getParent()
187 {
188 return parent;
189 }
190
191 /**
192 * Sets the font size for this component
193 *
194 * @param fontsize Font size
195 */
196 public void setFontSize(int fontsize)
197 {
198 this.fontsize = Math.max(fontsize, 8);
199 for (Enumeration e = childs.elements(); e.hasMoreElements(); )
200 ((MathElement) e.nextElement()).setFontSize(this.fontsize);
201 }
202
203 /**
204 * Gets the used font size
205 *
206 * @return Font Size
207 */
208 public int getFontSize()
209 {
210 return fontsize;
211 }
212
213 /**
214 * Gets the used font
215 *
216 * @return Font
217 */
218 public Font getFont()
219 {
220 if (base!=null)
221 return base.getFont(fontsize);
222 return null;
223 }
224
225 /**
226 * Gets the font metrics of the used font
227 *
228 * @return Font metrics
229 */
230 public FontMetrics getFontMetrics()
231 {
232 if (base!=null)
233 return base.getFontMetrics(fontsize);
234 return null;
235 }
236
237 /**
238 * Gets the used symbol font size
239 *
240 * @return Font
241 */
242 public Font getSymbolFont()
243 {
244 if (base!=null)
245 return base.getSymbolFont(fontsize);
246 return null;
247 }
248
249 /**
250 * Gets the font metrics of the used symbol font
251 *
252 * @return Font metrics
253 */
254 public FontMetrics getSymbolFontMetrics()
255 {
256 if (base!=null)
257 return base.getSymbolFontMetrics(fontsize);
258 return null;
259 }
260
261 /**
262 * Get a glyph vector of the symbol font
263 *
264 * @param g2d The graphic context presented by a Graphics2D
265 * @param index Index of the glyph vector
266 *
267 * @return Glyph vector
268 */
269 public GlyphVector getSymbolGlyphVector(Graphics2D g2d, char c)
270 {
271 if (base!=null)
272 return base.getSymbolGlyphVector(g2d, fontsize, c);
273 return null;
274 }
275
276 /**
277 * Paints a border around this element as debug information
278 *
279 * @param g The graphics context to use for painting
280 * @param posX The first left position for painting
281 * @param posY The position of the baseline
282 */
283 public void debug(Graphics g, int posX, int posY)
284 {
285 g.setColor(Color.blue);
286 g.drawLine(posX, posY - getAscentHeight(true), posX + getWidth(true),
287 posY - getAscentHeight(true));
288 g.drawLine(posX + getWidth(true), posY - getAscentHeight(true),
289 posX + getWidth(true), posY + getDescentHeight(true));
290 g.drawLine(posX, posY + getDescentHeight(true), posX + getWidth(true),
291 posY + getDescentHeight(true));
292 g.drawLine(posX, posY - getAscentHeight(true), posX,
293 posY + getDescentHeight(true));
294 g.setColor(Color.red);
295 g.drawLine(posX, posY, posX + getWidth(true), posY);
296 g.setColor(Color.black);
297 }
298
299 /**
300 * Paints this element
301 *
302 * @param g The graphics context to use for painting
303 * @param posX The first left position for painting
304 * @param posY The position of the baseline
305 */
306 public void paint(Graphics g, int posX, int posY)
307 {
308 if (base.isDebug())
309 debug(g, posX, posY);
310
311 int pos = posX;
312 MathElement child;
313
314 for (int i = 0; i < getMathElementCount(); i++)
315 {
316 child = getMathElement(i);
317 child.paint(g, pos, posY);
318 pos += child.getWidth(true);
319 }
320 }
321
322 // public abstarct void toFO(ContentHandler handler) throws SAXException;
323
324 /*public void toFO(ContentHandler handler) throws SAXException
325 {
326 AttributesImpl attributes = new AttributesImpl();
327 handler.startElement(FO_URI, "block", "fo:block", attributes);
328 for (Enumeration e = childs.elements() ; e.hasMoreElements() ;)
329 ((MathRow)e.nextElement()).toSAX(handler);
330 handler.endElement(FO_URI, "block", "fo:block");
331 }*/
332
333 // public abstract void toSVG(ContentHandler handler) throws SAXException;
334
335 /**
336 * Return the current width of this element
337 *
338 * @param dynamicParts
339 *
340 * @return Width of this element
341 */
342 public int getWidth(boolean dynamicParts)
343 {
344 int width = 0;
345
346 for (Enumeration e = childs.elements(); e.hasMoreElements(); )
347 width += ((MathElement) e.nextElement()).getWidth(dynamicParts);
348 return width;
349 }
350
351 /**
352 * Return the current height of this element
353 *
354 * @param dynamicParts Should be true, if the calculation consider the elements,
355 * which has not fixed sizes
356 *
357 * @return Height of this element
358 */
359 public int getHeight(boolean dynamicParts)
360 {
361 int height = 0;
362
363 for (Enumeration e = childs.elements(); e.hasMoreElements(); )
364 {
365 MathElement element = (MathElement) e.nextElement();
366
367 height = Math.max(height, element.getHeight(dynamicParts));
368 }
369 return height;
370 }
371
372 // used for mover and accents
373 public int getRealHeight(Graphics g, boolean dynamicParts) {
374 return(getHeight(dynamicParts));
375 }
376
377 /**
378 * Return the current height of the upper part
379 * of this component from the baseline
380 *
381 * @param dynamicParts Should be true, if the calculation consider the elements,
382 * which has not fixed sizes
383 *
384 * @return Height of the upper part
385 */
386 public int getAscentHeight(boolean dynamicParts)
387 {
388 int height = 0;
389
390 for (Enumeration e = childs.elements(); e.hasMoreElements(); )
391 {
392 MathElement element = (MathElement) e.nextElement();
393
394 height = Math.max(height, element.getAscentHeight(dynamicParts));
395 }
396 return height;
397 }
398
399 /**
400 * Return the current height of the lower part
401 * of this component from the baseline
402 *
403 * @param dynamicParts Should be true, if the calculation consider the elements,
404 * which has not fixed sizes
405 *
406 * @return Height of the lower part
407 */
408 public int getDescentHeight(boolean dynamicParts)
409 {
410 int height = 0;
411
412 for (Enumeration e = childs.elements(); e.hasMoreElements(); )
413 {
414 MathElement element = (MathElement) e.nextElement();
415
416 height = Math.max(height, element.getDescentHeight(dynamicParts));
417 }
418 return height;
419 }
420
421 /**
422 * Returns the distance of the baseline and the middleline
423 *
424 * @return Distance
425 */
426 protected int getMiddleShift()
427 {
428 return (int) (base.getFontMetrics(getFontSize()).getAscent() * 0.43);
429 }
430 }