/*
* This file is part of LaTeXDraw.
* Copyright (c) 2005-2017 Arnaud BLOUIN
* LaTeXDraw 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.
* LaTeXDraw is distributed 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.
*/
package net.sf.latexdraw.parsers.svg.parsers;
import java.text.ParseException;
import net.sf.latexdraw.parsers.svg.parsers.SVGLength.LengthType;
/**
* Defines a parser that parses SVG length code.
* @author Arnaud BLOUIN
*/
public class SVGLengthParser extends SVGNumberParser {
/**
* Describes textual value for the font-size attribute.
*/
public enum FontSize {
XXSMALL {
@Override
public float getPointValue() {
return XSMALL.getPointValue()/SCALING_FACTOR;
}
@Override
public String getToken() {
return "xx-small"; //$NON-NLS-1$
}
}, XSMALL {
@Override
public float getPointValue() {
return SMALL.getPointValue()/SCALING_FACTOR;
}
@Override
public String getToken() {
return "x-small"; //$NON-NLS-1$
}
}, SMALL {
@Override
public float getPointValue() {
return MEDIUM.getPointValue()/SCALING_FACTOR;
}
@Override
public String getToken() {
return "small"; //$NON-NLS-1$
}
}, MEDIUM {
@Override
public float getPointValue() {
return 12f;
}
@Override
public String getToken() {
return "medium"; //$NON-NLS-1$
}
}, LARGE {
@Override
public float getPointValue() {
return MEDIUM.getPointValue()*SCALING_FACTOR;
}
@Override
public String getToken() {
return "large"; //$NON-NLS-1$
}
}, XLARGE {
@Override
public float getPointValue() {
return LARGE.getPointValue()*SCALING_FACTOR;
}
@Override
public String getToken() {
return "x-large"; //$NON-NLS-1$
}
}, XXLARGE {
@Override
public float getPointValue() {
return XLARGE.getPointValue()*SCALING_FACTOR;
}
@Override
public String getToken() {
return "xx-large"; //$NON-NLS-1$
}
};
/**
* @return The value in point of the token.
*/
public abstract float getPointValue();
/**
* @return The token of the current font-size used in SVG documents.
*/
public abstract String getToken();
/**
* @param token The token to test.
* @return The value in point of the font-size given as argument, or -1
* if 'token' is not valid.
*/
public static float getFontSize(final String token) {
if(token==null)
return -1f;
if(token.equals(XXSMALL.getToken()))
return XXSMALL.getPointValue();
if(token.equals(XSMALL.getToken()))
return XSMALL.getPointValue();
if(token.equals(SMALL.getToken()))
return SMALL.getPointValue();
if(token.equals(MEDIUM.getToken()))
return MEDIUM.getPointValue();
if(token.equals(LARGE.getToken()))
return LARGE.getPointValue();
if(token.equals(XLARGE.getToken()))
return XLARGE.getPointValue();
if(token.equals(XXLARGE.getToken()))
return XXLARGE.getPointValue();
return -1f;
}
public static final float SCALING_FACTOR=1.2f;
}
/**
* Converts the font-size string value in point value.
* @param fontSize The font-size value to convert.
* @return the font-size value in point, or -1 if a
* problem occurs.
*/
public static float fontSizetoPoint(final String fontSize) {
if(fontSize==null)
return -1f;
float value;
try {
value = Double.valueOf(fontSize).floatValue();
}catch(final NumberFormatException e) {
try {
final SVGLength lgth = new SVGLengthParser(fontSize).parseLength();
value = (float)UnitProcessor.INSTANCE.toPoint(lgth.getValue(), lgth.getLengthType());
}
catch(final ParseException ex) {
value = FontSize.getFontSize(fontSize);
}
}
return value;
}
/**
* The constructor.
* @param code The code to parse.
*/
public SVGLengthParser(final String code) {
super(code);
}
/**
* Parses an SVG length.
* @return An SVGLength. The length is always converted in PX.
* @throws ParseException If a problem occurs or if not managed unit are parsed (%, em and ex).
*/
public SVGLength parseLength() throws ParseException {
final double value = parseNumber(false);
final LengthType lgthType;
final String errorUnit = "Invalid unit";//$NON-NLS-1$
final String valueAsStr;
setPosition(0);
valueAsStr = parseNumberAsString(false);
skipWSP();
switch(getChar()) {
case EOC:
lgthType = LengthType.NUMBER;
break;
case 'p':
switch(nextChar()) {
case 't':
lgthType = LengthType.PT;
break;
case 'x':
lgthType = LengthType.PX;
break;
case 'c':
lgthType = LengthType.PC;
break;
case EOC:
default:
throw new ParseException(errorUnit, getPosition());
}
break;
case '%':
throw new ParseException("Not yet managed: %", getPosition());//$NON-NLS-1$
case 'c':
if(nextChar()=='m')
lgthType = LengthType.CM;
else
throw new ParseException(errorUnit, getPosition());
break;
case 'm':
if(nextChar()=='m')
lgthType = LengthType.MM;
else
throw new ParseException(errorUnit, getPosition());
break;
case 'i':
if(nextChar()=='n')
lgthType = LengthType.IN;
else
throw new ParseException(errorUnit, getPosition());
break;
case 'e':
switch(nextChar()) {
case EOC:
case 'm':
throw new ParseException("Not yet managed: em", getPosition());//$NON-NLS-1$
case 'x':
throw new ParseException("Not yet managed: ex", getPosition());//$NON-NLS-1$
default:
throw new ParseException(errorUnit, getPosition());
}
default:
throw new ParseException(errorUnit, getPosition());
}
return new SVGLength(UnitProcessor.INSTANCE.toUserUnit(value, lgthType), LengthType.PX, valueAsStr);
}
/**
* Parses an SVG coordinate.
* @return An SVGLength.
* @throws ParseException If a problem occurs or if not managed unit are parsed (%, em and ex).
*/
public SVGLength parseCoordinate() throws ParseException {
return parseLength();
}
/**
* Parses a number or a percentage (not yet managed).
* @return An SVGLength.
* @throws ParseException If a problem occurs or if a percentage is parsed.
*/
public SVGLength parseNumberOrPercent() throws ParseException {
final double value = parseNumber(false);
final LengthType type;
final String valueAsStr;
setPosition(0);
valueAsStr = parseNumberAsString(false);
skipWSP();
switch(getChar()) {
case '%':
throw new ParseException("Not yet managed: %", getPosition());//$NON-NLS-1$
case EOC:
default:
type = LengthType.NUMBER;
break;
}
return new SVGLength(UnitProcessor.INSTANCE.toUserUnit(value, type), type, valueAsStr);
}
}