001 /*
002 * Copyright 2002 - 2010 JEuclid, http://jeuclid.sf.net
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 /* $Id: LayoutTest.java,v 92b6a7c39d7f 2010/08/11 20:23:17 max $ */
018
019 package net.sourceforge.jeuclid.test;
020
021 import java.util.List;
022
023 import net.sourceforge.jeuclid.DOMBuilder;
024 import net.sourceforge.jeuclid.MathMLParserSupport;
025 import net.sourceforge.jeuclid.elements.presentation.general.Mfrac;
026 import net.sourceforge.jeuclid.elements.presentation.token.Mi;
027 import net.sourceforge.jeuclid.elements.presentation.token.Mn;
028 import net.sourceforge.jeuclid.layout.JEuclidView;
029 import net.sourceforge.jeuclid.layout.LayoutStage;
030 import net.sourceforge.jeuclid.layout.LayoutableNode;
031
032 import org.junit.Assert;
033 import org.junit.Test;
034 import org.w3c.dom.Node;
035 import org.w3c.dom.mathml.MathMLDocument;
036 import org.w3c.dom.mathml.MathMLFractionElement;
037 import org.w3c.dom.mathml.MathMLMathElement;
038 import org.w3c.dom.mathml.MathMLPresentationContainer;
039 import org.w3c.dom.mathml.MathMLPresentationToken;
040 import org.w3c.dom.views.DocumentView;
041
042 /**
043 * @version $Revision: 92b6a7c39d7f $
044 */
045 public class LayoutTest {
046
047 /**
048 * Test string with xml header.
049 */
050 final static public String TEST1 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math mode=\"display\">"
051 + "<mrow><mo>(</mo><mn>555</mn></mrow></math>";
052
053 /**
054 * Test if there is something in the view.
055 *
056 * @throws Exception
057 * if the test fails.
058 */
059 @Test
060 public void testViewNotEmpty() throws Exception {
061 final MathMLDocument docElement = DOMBuilder.getInstance()
062 .createJeuclidDom(
063 MathMLParserSupport.parseString(LayoutTest.TEST1));
064 final JEuclidView view = (JEuclidView) (((DocumentView) docElement)
065 .getDefaultView());
066 Assert.assertTrue(
067 "View has not enough ascent: " + view.getAscentHeight(),
068 view.getAscentHeight() > 1.0f);
069 Assert.assertTrue("View has not enoguh width: " + view.getWidth(),
070 view.getWidth() > 1.0f);
071 Assert.assertTrue("Descent Height < 0: " + view.getDescentHeight(),
072 view.getDescentHeight() >= 0.0f);
073 }
074
075 /**
076 * Tests if view modifies itself when DOM is modified.
077 *
078 * @throws Exception
079 * if the test fails.
080 */
081 @Test
082 public void testViewMutable() throws Exception {
083 final MathMLDocument docElement = DOMBuilder.getInstance()
084 .createJeuclidDom(
085 MathMLParserSupport.parseString(LayoutTest.TEST1));
086 final JEuclidView view = (JEuclidView) (((DocumentView) docElement)
087 .getDefaultView());
088
089 final float oldAscent = view.getAscentHeight();
090 final float oldWidth = view.getWidth();
091
092 final MathMLMathElement mathElement = (MathMLMathElement) docElement
093 .getFirstChild();
094 final MathMLPresentationContainer mrow = (MathMLPresentationContainer) mathElement
095 .getFirstChild();
096 final LayoutableNode mop = (LayoutableNode) mrow.getFirstChild();
097 final float oldmopascent = view.getInfo(mop).getAscentHeight(
098 LayoutStage.STAGE2);
099
100 final MathMLFractionElement mfrac = (MathMLFractionElement) docElement
101 .createElement(Mfrac.ELEMENT);
102
103 final MathMLPresentationToken denom = (MathMLPresentationToken) docElement
104 .createElement(Mn.ELEMENT);
105
106 denom.setTextContent("123");
107 mfrac.setDenominator(denom);
108 final MathMLPresentationToken nom = (MathMLPresentationToken) docElement
109 .createElement(Mi.ELEMENT);
110 nom.setTextContent("X");
111 mfrac.setNumerator(nom);
112 mrow.appendChild(mfrac);
113
114 Assert.assertTrue("Width of view should increase: " + view.getWidth()
115 + " > " + oldWidth, view.getWidth() > oldWidth);
116 Assert.assertTrue(
117 "Heightof view should increase: " + view.getAscentHeight()
118 + " > " + oldAscent, view.getAscentHeight() > oldAscent);
119
120 final float newmopascent = view.getInfo(mop).getAscentHeight(
121 LayoutStage.STAGE2);
122 Assert.assertTrue("Operator should be larger: " + newmopascent + " > "
123 + oldmopascent, newmopascent > oldmopascent);
124 }
125
126 /**
127 * Test whitespace handling.
128 *
129 * @throws Exception
130 * if the test fails.
131 */
132 @Test
133 public void testWhitespace() throws Exception {
134 final MathMLDocument docElement = DOMBuilder
135 .getInstance()
136 .createJeuclidDom(
137 MathMLParserSupport
138 .parseString("<math><mtext>x x</mtext><mtext> x x </mtext><mtext>x x</mtext></math>"));
139 final JEuclidView view = (JEuclidView) (((DocumentView) docElement)
140 .getDefaultView());
141
142 final MathMLMathElement mathElement = (MathMLMathElement) docElement
143 .getFirstChild();
144 final LayoutableNode m1 = (LayoutableNode) mathElement
145 .getFirstChild();
146 final LayoutableNode m2 = (LayoutableNode) m1.getNextSibling();
147 final LayoutableNode m3 = (LayoutableNode) m2.getNextSibling();
148
149 // To trigger layout
150 view.getWidth();
151
152 final float w1 = view.getInfo(m1).getWidth(LayoutStage.STAGE2);
153 final float w2 = view.getInfo(m2).getWidth(LayoutStage.STAGE2);
154 final float w3 = view.getInfo(m3).getWidth(LayoutStage.STAGE2);
155
156 Assert.assertEquals("Whitespace around text should be trimmed to none",
157 w2, w1, 0.01);
158 Assert.assertEquals("Whitespace inside text should be trimmed to 1",
159 w3, w1, 0.01);
160
161 }
162
163 /**
164 * Test MO without math parent.
165 *
166 * @throws Exception
167 * if the test fails.
168 */
169 @Test
170 public void testMoWithoutParent() throws Exception {
171 final MathMLDocument docElement = DOMBuilder
172 .getInstance()
173 .createJeuclidDom(
174 MathMLParserSupport
175 .parseString("<mrow><mo>∑</mo></mrow>"));
176 final JEuclidView view = (JEuclidView) (((DocumentView) docElement)
177 .getDefaultView());
178
179 // To trigger layout
180 view.getWidth();
181 }
182
183 /**
184 * Test MO without any parent.
185 *
186 * @throws Exception
187 * if the test fails.
188 */
189 @Test
190 public void testMoWithoutParent2() throws Exception {
191 final MathMLDocument docElement = DOMBuilder.getInstance()
192 .createJeuclidDom(
193 MathMLParserSupport.parseString("<mo>∑</mo>"));
194 final JEuclidView view = (JEuclidView) (((DocumentView) docElement)
195 .getDefaultView());
196
197 // To trigger layout
198 view.getWidth();
199 }
200
201 /**
202 * Test if getNodesAt() works.
203 *
204 * @throws Exception
205 * if the test fails.
206 */
207 @Test
208 public void testGetNodesAt() throws Exception {
209 final MathMLDocument docElement = DOMBuilder.getInstance()
210 .createJeuclidDom(
211 MathMLParserSupport.parseString(LayoutTest.TEST1));
212 final JEuclidView view = (JEuclidView) (((DocumentView) docElement)
213 .getDefaultView());
214 final List<JEuclidView.NodeRect> rlist = view.getNodesAt(15, 0, 0, 0);
215 Assert.assertSame(rlist.get(0).getNode(), docElement);
216 final Node math = docElement.getFirstChild();
217 Assert.assertSame(rlist.get(1).getNode(), math);
218 final Node mrow = math.getFirstChild();
219 Assert.assertSame(rlist.get(2).getNode(), mrow);
220 final Node five = mrow.getFirstChild().getNextSibling();
221 Assert.assertSame(rlist.get(3).getNode(), five);
222 }
223 }