/* SpaceAtom.java
* =========================================================================
* This file is originally part of the JMathTeX Library - http://jmathtex.sourceforge.net
*
* Copyright (C) 2004-2007 Universiteit Gent
* Copyright (C) 2009 DENIZET Calixte
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* A copy of the GNU General Public License can be found in the file
* LICENSE.txt provided with the source distribution of this program (see
* the META-INF directory in the source jar). This license can also be
* found on the GNU website at http://www.gnu.org/licenses/gpl.html.
*
* If you did not receive a copy of the GNU General Public License along
* with this program, contact the lead developer, or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* Linking this library statically or dynamically with other modules
* is making a combined work based on this library. Thus, the terms
* and conditions of the GNU General Public License cover the whole
* combination.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce
* an executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under terms
* of your choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module.
* An independent module is a module which is not derived from or based
* on this library. If you modify this library, you may extend this exception
* to your version of the library, but you are not obliged to do so.
* If you do not wish to do so, delete this exception statement from your
* version.
*
*/
/* Modified by Calixte Denizet */
package com.himamis.retex.renderer.share;
import java.util.HashMap;
import java.util.Map;
import com.himamis.retex.renderer.share.exception.InvalidUnitException;
/**
* An atom representing whitespace. The dimension values can be set using different unit types.
*/
public class SpaceAtom extends Atom {
private static Map<String, Integer> units = new HashMap<String, Integer>();
static {
units.put("em", TeXConstants.UNIT_EM);
units.put("ex", TeXConstants.UNIT_EX);
units.put("px", TeXConstants.UNIT_PIXEL);
units.put("pix", TeXConstants.UNIT_PIXEL);
units.put("pixel", TeXConstants.UNIT_PIXEL);
units.put("pt", TeXConstants.UNIT_PT);
units.put("bp", TeXConstants.UNIT_POINT);
units.put("pica", TeXConstants.UNIT_PICA);
units.put("pc", TeXConstants.UNIT_PICA);
units.put("mu", TeXConstants.UNIT_MU);
units.put("cm", TeXConstants.UNIT_CM);
units.put("mm", TeXConstants.UNIT_MM);
units.put("in", TeXConstants.UNIT_IN);
units.put("sp", TeXConstants.UNIT_SP);
units.put("dd", TeXConstants.UNIT_DD);
units.put("cc", TeXConstants.UNIT_CC);
}
private static interface UnitConversion { // NOPMD
public double getPixelConversion(TeXEnvironment env);
}
private static UnitConversion[] unitConversions = new UnitConversion[] {
new UnitConversion() {// EM
@Override
public double getPixelConversion(TeXEnvironment env) {
return env.getTeXFont().getEM(env.getStyle());
}
},
new UnitConversion() {// EX
@Override
public double getPixelConversion(TeXEnvironment env) {
return env.getTeXFont().getXHeight(env.getStyle(), env.getLastFontId());
}
},
new UnitConversion() {// PIXEL
@Override
public double getPixelConversion(TeXEnvironment env) {
return 1 / env.getSize();
}
},
new UnitConversion() {// BP (or PostScript point)
@Override
public double getPixelConversion(TeXEnvironment env) {
return TeXFormula.PIXELS_PER_POINT / env.getSize();
}
},
new UnitConversion() {// PICA
@Override
public double getPixelConversion(TeXEnvironment env) {
return (12 * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// MU
@Override
public double getPixelConversion(TeXEnvironment env) {
TeXFont tf = env.getTeXFont();
return tf.getQuad(env.getStyle(), tf.getMuFontId()) / 18;
}
},
new UnitConversion() {// CM
@Override
public double getPixelConversion(TeXEnvironment env) {
return (28.346456693f * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// MM
@Override
public double getPixelConversion(TeXEnvironment env) {
return (2.8346456693f * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// IN
@Override
public double getPixelConversion(TeXEnvironment env) {
return (72 * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// SP
@Override
public double getPixelConversion(TeXEnvironment env) {
return (65536 * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// PT (or Standard Anglo-American point)
@Override
public double getPixelConversion(TeXEnvironment env) {
return (.9962640099f * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// DD
@Override
public double getPixelConversion(TeXEnvironment env) {
return (1.0660349422f * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
},
new UnitConversion() {// CC
@Override
public double getPixelConversion(TeXEnvironment env) {
return (12.7924193070f * TeXFormula.PIXELS_PER_POINT) / env.getSize();
}
} };
// whether a hard space should be represented
private boolean blankSpace;
// thinmuskip, medmuskip, thickmuskip
private int blankType;
// dimensions
private double width;
private double height;
private double depth;
// units for the dimensions
private int wUnit;
private int hUnit;
private int dUnit;
@Override
final public Atom duplicate() {
SpaceAtom ret = new SpaceAtom();
ret.blankSpace = blankSpace;
ret.blankType = blankType;
ret.width = width;
ret.height = height;
ret.depth = depth;
ret.wUnit = wUnit;
ret.hUnit = hUnit;
ret.dUnit = dUnit;
return setFields(ret);
}
public SpaceAtom() {
blankSpace = true;
}
public SpaceAtom(int type) {
blankSpace = true;
blankType = type;
}
public SpaceAtom(int unit, double width, double height, double depth) throws InvalidUnitException {
// check if unit is valid
checkUnit(unit);
// unit valid
this.wUnit = unit;
this.hUnit = unit;
this.dUnit = unit;
this.width = width;
this.height = height;
this.depth = depth;
}
/**
* Check if the given unit is valid
*
* @param unit the unit's integer representation (a constant)
* @throws InvalidUnitException if the given integer value does not represent a valid unit
*/
public static void checkUnit(int unit) throws InvalidUnitException {
if (unit < 0 || unit >= unitConversions.length) {
throw new InvalidUnitException();
}
}
public SpaceAtom(int widthUnit, double width, int heightUnit, double height, int depthUnit, double depth)
throws InvalidUnitException {
// check if units are valid
checkUnit(widthUnit);
checkUnit(heightUnit);
checkUnit(depthUnit);
// all units valid
wUnit = widthUnit;
hUnit = heightUnit;
dUnit = depthUnit;
this.width = width;
this.height = height;
this.depth = depth;
}
public static int getUnit(String unit) {
Integer u = units.get(unit);
return u == null ? TeXConstants.UNIT_PIXEL : u.intValue();
}
public static double[] getLength(String lgth) {
if (lgth == null) {
return new double[] { TeXConstants.UNIT_PIXEL, 0f };
}
int i = 0;
for (; i < lgth.length() && !Character.isLetter(lgth.charAt(i)); i++) {
;
}
double f = 0;
try {
f = Double.parseDouble(lgth.substring(0, i));
} catch (NumberFormatException e) {
return new double[] { Double.NaN };
}
int unit;
if (i != lgth.length()) {
unit = getUnit(lgth.substring(i).toLowerCase());
} else {
unit = TeXConstants.UNIT_PIXEL;
}
return new double[] { unit, f };
}
@Override
public Box createBox(TeXEnvironment env) {
if (blankSpace) {
if (blankType == 0) {
return new StrutBox(env.getSpace(), 0, 0, 0);
}
int bl = blankType < 0 ? -blankType : blankType;
Box b;
if (bl == TeXConstants.THINMUSKIP) {
b = Glue.get(TeXConstants.TYPE_INNER,
TeXConstants.TYPE_BIG_OPERATOR, env);
} else if (bl == TeXConstants.MEDMUSKIP) {
b = Glue.get(TeXConstants.TYPE_BINARY_OPERATOR,
TeXConstants.TYPE_BIG_OPERATOR, env);
} else {
b = Glue.get(TeXConstants.TYPE_RELATION,
TeXConstants.TYPE_BIG_OPERATOR, env);
}
if (blankType < 0) {
b.negWidth();
}
return b;
}
return new StrutBox(width * getFactor(wUnit, env),
height * getFactor(hUnit, env), depth * getFactor(dUnit, env),
0);
}
public static double getFactor(int unit, TeXEnvironment env) {
return unitConversions[unit].getPixelConversion(env);
}
}