Coverage Report - net.sourceforge.jeuclid.elements.presentation.general.Mfrac
 
Classes in this File Line Coverage Branch Coverage Complexity
Mfrac
62%
48/77
28%
4/14
1,421
 
 1  
 /*
 2  
  * Copyright 2002 - 2007 JEuclid, http://jeuclid.sf.net
 3  
  * 
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 /* $Id: Mfrac.java,v bc1d5fde7b73 2009/06/01 14:40:54 maxberger $ */
 18  
 
 19  
 package net.sourceforge.jeuclid.elements.presentation.general;
 20  
 
 21  
 import java.awt.Color;
 22  
 import java.awt.Graphics2D;
 23  
 import java.awt.geom.Dimension2D;
 24  
 
 25  
 import net.sourceforge.jeuclid.LayoutContext;
 26  
 import net.sourceforge.jeuclid.context.InlineLayoutContext;
 27  
 import net.sourceforge.jeuclid.context.Parameter;
 28  
 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
 29  
 import net.sourceforge.jeuclid.elements.support.Dimension2DImpl;
 30  
 import net.sourceforge.jeuclid.elements.support.ElementListSupport;
 31  
 import net.sourceforge.jeuclid.elements.support.GraphicsSupport;
 32  
 import net.sourceforge.jeuclid.elements.support.attributes.AttributesHelper;
 33  
 import net.sourceforge.jeuclid.elements.support.attributes.HAlign;
 34  
 import net.sourceforge.jeuclid.layout.GraphicsObject;
 35  
 import net.sourceforge.jeuclid.layout.LayoutInfo;
 36  
 import net.sourceforge.jeuclid.layout.LayoutStage;
 37  
 import net.sourceforge.jeuclid.layout.LayoutView;
 38  
 import net.sourceforge.jeuclid.layout.LayoutableNode;
 39  
 import net.sourceforge.jeuclid.layout.LineObject;
 40  
 
 41  
 import org.apache.batik.dom.AbstractDocument;
 42  
 import org.w3c.dom.Node;
 43  
 import org.w3c.dom.mathml.MathMLElement;
 44  
 import org.w3c.dom.mathml.MathMLFractionElement;
 45  
 
 46  
 /**
 47  
  * This math element presents a mathematical fraction.
 48  
  * 
 49  
  * @version $Revision: bc1d5fde7b73 $
 50  
  */
 51  
 public final class Mfrac extends AbstractJEuclidElement implements
 52  
         MathMLFractionElement {
 53  
 
 54  
     /**
 55  
      * The XML element from this class.
 56  
      */
 57  
     public static final String ELEMENT = "mfrac";
 58  
 
 59  
     /**
 60  
      * Tilt angle for frac.
 61  
      */
 62  
     public static final float FRAC_TILT_ANGLE = 0.577f;
 63  
 
 64  
     /**
 65  
      * Attribute name of the linethickness property.
 66  
      */
 67  
     public static final String ATTR_LINETHICKNESS = "linethickness";
 68  
 
 69  
     /** The wrong beveled attribute. */
 70  
     public static final String ATTR_BEVELED_WRONG = "beveled";
 71  
 
 72  
     /** The real beveled attribute. */
 73  
     public static final String ATTR_BEVELLED = "bevelled";
 74  
 
 75  
     /** The numalign attribute. */
 76  
     public static final String ATTR_NUMALIGN = "numalign";
 77  
 
 78  
     /** The denomalign attribute. */
 79  
     public static final String ATTR_DENOMALIGN = "denomalign";
 80  
 
 81  
     private static final String EXTRA_SPACE_AROUND = "0.1em";
 82  
 
 83  
     private static final long serialVersionUID = 1L;
 84  
 
 85  
     /**
 86  
      * Lines thinner than this are ignored.
 87  
      */
 88  
     private static final float NOLINE_THRESHHOLD = 0.001f;
 89  
 
 90  
     /**
 91  
      * Default constructor. Sets MathML Namespace.
 92  
      * 
 93  
      * @param qname
 94  
      *            Qualified name.
 95  
      * @param odoc
 96  
      *            Owner Document.
 97  
      */
 98  
     public Mfrac(final String qname, final AbstractDocument odoc) {
 99  5225
         super(qname, odoc);
 100  
 
 101  5225
         this.setDefaultMathAttribute(Mfrac.ATTR_LINETHICKNESS, "1");
 102  5225
         this.setDefaultMathAttribute(Mfrac.ATTR_BEVELLED, Boolean.FALSE
 103  
                 .toString());
 104  5225
         this.setDefaultMathAttribute(Mfrac.ATTR_NUMALIGN, HAlign.ALIGN_CENTER);
 105  5225
         this
 106  
                 .setDefaultMathAttribute(Mfrac.ATTR_DENOMALIGN,
 107  
                         HAlign.ALIGN_CENTER);
 108  5225
     }
 109  
 
 110  
     /** {@inheritDoc} */
 111  
     @Override
 112  
     protected Node newNode() {
 113  0
         return new Mfrac(this.nodeName, this.ownerDocument);
 114  
     }
 115  
 
 116  
     /** {@inheritDoc} */
 117  
     @Override
 118  
     public LayoutContext getChildLayoutContext(final int childNum,
 119  
             final LayoutContext context) {
 120  5016
         return new InlineLayoutContext(this
 121  
                 .applyLocalAttributesToContext(context), !((Boolean) context
 122  
                 .getParameter(Parameter.MFRAC_KEEP_SCRIPTLEVEL)).booleanValue());
 123  
     }
 124  
 
 125  
     /**
 126  
      * Sets the thickness of the fraction line.
 127  
      * 
 128  
      * @param newLinethickness
 129  
      *            Thickness
 130  
      */
 131  
     public void setLinethickness(final String newLinethickness) {
 132  0
         this.setAttribute(Mfrac.ATTR_LINETHICKNESS, newLinethickness);
 133  0
     }
 134  
 
 135  
     /**
 136  
      * @return thickness of the fraction line
 137  
      * @param context
 138  
      *            LayoutContext to use
 139  
      * @param g
 140  
      *            Graphics2D context to use.
 141  
      */
 142  
     public float getLinethickness(final Graphics2D g,
 143  
             final LayoutContext context) {
 144  2508
         final String sThickness = this.getLinethickness();
 145  
         float thickness;
 146  
         try {
 147  2508
             thickness = Float.parseFloat(sThickness);
 148  2508
             thickness *= GraphicsSupport.lineWidth(context);
 149  0
         } catch (final NumberFormatException nfe) {
 150  0
             thickness = AttributesHelper.convertSizeToPt(sThickness, this
 151  
                     .applyLocalAttributesToContext(context),
 152  
                     AttributesHelper.PT);
 153  0
             if ((thickness < GraphicsSupport.MIN_LINEWIDTH)
 154  
                     && (thickness >= Mfrac.NOLINE_THRESHHOLD)) {
 155  0
                 thickness = GraphicsSupport.MIN_LINEWIDTH;
 156  
             }
 157  2508
         }
 158  2508
         return thickness;
 159  
     }
 160  
 
 161  
     /**
 162  
      * Set value of the beveled attribute.
 163  
      * 
 164  
      * @param bevelled
 165  
      *            Value
 166  
      */
 167  
     public void setBevelled(final String bevelled) {
 168  0
         this.setAttribute(Mfrac.ATTR_BEVELLED, bevelled);
 169  0
     }
 170  
 
 171  
     /**
 172  
      * @return Value of beveled attribute
 173  
      */
 174  
     public String getBevelled() {
 175  2508
         final String wrongAttr = this.getMathAttribute(
 176  
                 Mfrac.ATTR_BEVELED_WRONG, false);
 177  2508
         if (wrongAttr == null) {
 178  2508
             return this.getMathAttribute(Mfrac.ATTR_BEVELLED);
 179  
         } else {
 180  0
             return wrongAttr;
 181  
         }
 182  
     }
 183  
 
 184  
     /** {@inheritDoc} */
 185  
     public MathMLElement getDenominator() {
 186  2926
         return this.getMathElement(1);
 187  
     }
 188  
 
 189  
     /** {@inheritDoc} */
 190  
     public String getLinethickness() {
 191  2508
         return this.getMathAttribute(Mfrac.ATTR_LINETHICKNESS);
 192  
     }
 193  
 
 194  
     /** {@inheritDoc} */
 195  
     public MathMLElement getNumerator() {
 196  2926
         return this.getMathElement(0);
 197  
     }
 198  
 
 199  
     /** {@inheritDoc} */
 200  
     public void setDenominator(final MathMLElement denominator) {
 201  418
         this.setMathElement(1, denominator);
 202  418
     }
 203  
 
 204  
     /** {@inheritDoc} */
 205  
     public void setNumerator(final MathMLElement numerator) {
 206  627
         this.setMathElement(0, numerator);
 207  627
     }
 208  
 
 209  
     /** {@inheritDoc} */
 210  
     public String getDenomalign() {
 211  2508
         return this.getMathAttribute(Mfrac.ATTR_DENOMALIGN);
 212  
     }
 213  
 
 214  
     /** {@inheritDoc} */
 215  
     public String getNumalign() {
 216  2508
         return this.getMathAttribute(Mfrac.ATTR_NUMALIGN);
 217  
     }
 218  
 
 219  
     /** {@inheritDoc} */
 220  
     public void setDenomalign(final String denomalign) {
 221  0
         this.setAttribute(Mfrac.ATTR_DENOMALIGN, denomalign);
 222  0
     }
 223  
 
 224  
     /** {@inheritDoc} */
 225  
     public void setNumalign(final String numalign) {
 226  0
         this.setAttribute(Mfrac.ATTR_NUMALIGN, numalign);
 227  0
     }
 228  
 
 229  
     /** {@inheritDoc} */
 230  
     @Override
 231  
     protected void layoutStageInvariant(final LayoutView view,
 232  
             final LayoutInfo info, final LayoutStage stage,
 233  
             final LayoutContext context) {
 234  2508
         final Graphics2D g = view.getGraphics();
 235  
 
 236  2508
         final float middleShift = this.getMiddleShift(g, context);
 237  2508
         final boolean beveled = Boolean.parseBoolean(this.getBevelled());
 238  2508
         final float linethickness = this.getLinethickness(g, context);
 239  2508
         final float extraSpace = AttributesHelper.convertSizeToPt(
 240  
                 Mfrac.EXTRA_SPACE_AROUND, this
 241  
                         .applyLocalAttributesToContext(context), "");
 242  
 
 243  2508
         final LayoutInfo numerator = view.getInfo((LayoutableNode) this
 244  
                 .getNumerator());
 245  2508
         final LayoutInfo denominator = view.getInfo((LayoutableNode) this
 246  
                 .getDenominator());
 247  
 
 248  2508
         if (beveled) {
 249  0
             this.layoutBeveled(info, stage, middleShift, linethickness,
 250  
                     extraSpace, numerator, denominator, context);
 251  
         } else {
 252  2508
             this.layoutStacked(info, stage, middleShift, linethickness,
 253  
                     extraSpace, numerator, denominator, context);
 254  
         }
 255  
 
 256  2508
         final Dimension2D borderLeftTop = new Dimension2DImpl(extraSpace
 257  
                 + linethickness, 0.0f);
 258  2508
         final Dimension2D borderRightBottom = new Dimension2DImpl(extraSpace
 259  
                 + linethickness, 0.0f);
 260  2508
         ElementListSupport.fillInfoFromChildren(view, info, this, stage,
 261  
                 borderLeftTop, borderRightBottom);
 262  2508
     }
 263  
 
 264  
     // CHECKSTYLE:OFF
 265  
     // More than 7 parameters - but only used here, so this is ok.
 266  
     private void layoutStacked(final LayoutInfo info, final LayoutStage stage,
 267  
             final float middleShift, final float linethickness,
 268  
             final float extraSpace, final LayoutInfo numerator,
 269  
             final LayoutInfo denominator, final LayoutContext context) {
 270  
         // CHECKSTLYE:ON
 271  2508
         final float numWidth = numerator.getWidth(stage);
 272  2508
         final float denumWidth = denominator.getWidth(stage);
 273  2508
         final float width = Math.max(denumWidth, numWidth);
 274  
 
 275  2508
         final float numOffset = HAlign.parseString(this.getNumalign(),
 276  
                 HAlign.CENTER).getHAlignOffset(stage, numerator, width);
 277  2508
         final float denumOffset = HAlign.parseString(this.getDenomalign(),
 278  
                 HAlign.CENTER).getHAlignOffset(stage, denominator, width);
 279  
 
 280  2508
         numerator
 281  
                 .moveTo(
 282  
                         numOffset + extraSpace,
 283  
                         -(middleShift + linethickness / 2.0f + extraSpace + numerator
 284  
                                 .getDescentHeight(stage)), stage);
 285  
 
 286  2508
         denominator.moveTo(denumOffset + extraSpace, -middleShift
 287  
                 + linethickness / 2.0f + extraSpace
 288  
                 + denominator.getAscentHeight(stage), stage);
 289  
 
 290  2508
         if (linethickness > Mfrac.NOLINE_THRESHHOLD) {
 291  2508
             final GraphicsObject line = new LineObject(extraSpace,
 292  
                     -middleShift, extraSpace + width, -middleShift,
 293  
                     linethickness, (Color) this.applyLocalAttributesToContext(
 294  
                             context).getParameter(Parameter.MATHCOLOR));
 295  2508
             info.setGraphicsObject(line);
 296  
         }
 297  2508
     }
 298  
 
 299  
     // CHECKSTYLE:OFF
 300  
     // More than 7 parameters - but only used here, so this is ok.
 301  
     private void layoutBeveled(final LayoutInfo info, final LayoutStage stage,
 302  
             final float middleShift, final float linethickness,
 303  
             final float extraSpace, final LayoutInfo numerator,
 304  
             final LayoutInfo denominator, final LayoutContext context) {
 305  
         // CHECKSTYLE:ON
 306  0
         final float numPosY = -middleShift / 2.0f
 307  
                 + numerator.getDescentHeight(stage);
 308  0
         final float denPosY = middleShift / 2.0f
 309  
                 + denominator.getDescentHeight(stage);
 310  
 
 311  0
         final float totalAscent = Math.max(-numPosY
 312  
                 + numerator.getAscentHeight(stage), -denPosY
 313  
                 + denominator.getAscentHeight(stage));
 314  0
         final float totalDescent = Math.max(numPosY
 315  
                 + numerator.getDescentHeight(stage), denPosY
 316  
                 + denominator.getDescentHeight(stage));
 317  
 
 318  0
         final float totalHeight = totalAscent + totalDescent;
 319  0
         final float lineWidth = totalHeight * Mfrac.FRAC_TILT_ANGLE;
 320  
 
 321  0
         numerator.moveTo(extraSpace, numPosY, stage);
 322  0
         float posX = numerator.getWidth(stage) + extraSpace;
 323  0
         if (linethickness > Mfrac.NOLINE_THRESHHOLD) {
 324  0
             final GraphicsObject line = new LineObject(posX, totalDescent,
 325  
                     lineWidth + posX, totalDescent - totalHeight,
 326  
                     linethickness, (Color) this.applyLocalAttributesToContext(
 327  
                             context).getParameter(Parameter.MATHCOLOR));
 328  0
             info.setGraphicsObject(line);
 329  
         }
 330  0
         posX += lineWidth;
 331  0
         denominator.moveTo(posX, denPosY, stage);
 332  0
     }
 333  
 }