/*
* $Id: SVGAttributes.java 341 2012-06-18 14:38:54Z blowagie $
*
* This file is part of the iText (R) project.
* Copyright (c) 1998-2012 1T3XT BVBA
* Authors: VVB, Bruno Lowagie, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
* 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://itextpdf.com/terms-of-use/
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* In accordance with Section 7(b) of the GNU Affero General Public License,
* a covered work must retain the producer line in every PDF that is created
* or manipulated using iText.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the iText software without
* disclosing the source code of your own applications.
* These activities include: offering paid services to customers as an ASP,
* serving PDFs on the fly in a web application, shipping iText with a closed
* source product.
*
* For more information, please contact iText Software Corp. at this
* address: sales@itextpdf.com
*/
package com.itextpdf.tool.xml.svg.graphic;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.html.HtmlUtilities;
import com.itextpdf.tool.xml.svg.tags.TagUtils;
/*fill-opacity 1
fill-rule nonzero
fill-opacity 1
stroke-opacity 1
stroke-miterlimit 4
stroke-dasharray 0,11,8,1
stroke-opacity 1
stroke-miterlimit 10*/
public class SVGAttributes {
public final static int TYPE_OTHER = 0;
public final static int TYPE_COLOR = 1;
public final static int TYPE_LINE = 2;
public final static int TYPE_LINE_CAP = 3;
public final static int TYPE_LINE_JOIN = 4;
public final static int TYPE_LINE_DASH = 5; //a list of integer values
final static String STROKE = "stroke";
final static String STROKE_WIDTH = "stroke-width";
final static String FILL = "fill";
final static String LINE_CAP = "stroke-linecap";
final static String LINE_JOIN = "stroke-linejoin";
final static String FILL_OPACITY = "fill-opacity";
final static String STROKE_OPACITY = "stroke-opacity";
final static String FILL_RULE = "fill-rule";
final static String STROKE_MASTERLIMIT = "stroke-miterlimit";
final static String STROKE_DASHARRAY = "stroke-dasharray";
final static String FONT_SIZE = "font-size";
final static String FONT_FAMILY = "font-family";
final static String[] LINE_CAP_VALUES = {"butt", "round", "square"};
final static String[] LINE_JOIN_VALUES = {"miter", "round", "bevel"};
//TODo make this an instance
public static Map<String, Integer> getSVGAttributesList(){
Map<String, Integer> attributes = new HashMap<String, Integer>();
attributes.put(STROKE, TYPE_COLOR);
attributes.put(STROKE_WIDTH, TYPE_LINE);
attributes.put(FILL, TYPE_COLOR);
attributes.put(LINE_CAP, TYPE_LINE_CAP);
attributes.put(LINE_JOIN, TYPE_LINE_JOIN);
attributes.put(STROKE_DASHARRAY, TYPE_LINE_DASH);
attributes.put(FONT_SIZE, TYPE_LINE);
attributes.put(FONT_FAMILY, TYPE_OTHER);
return attributes;
}
public static boolean isValidAttribute(String key, String value, Map<String, Integer> attributes){
if( attributes.get(key) != null){
switch ((int) attributes.get(key)) {
case SVGAttributes.TYPE_LINE:
return isValidValueForLine(value);
case SVGAttributes.TYPE_COLOR:
return isValidColor(value);
case SVGAttributes.TYPE_LINE_CAP:
return isValidString(value, LINE_CAP_VALUES);
case SVGAttributes.TYPE_LINE_JOIN:
return isValidString(value, LINE_JOIN_VALUES);
case SVGAttributes.TYPE_LINE_DASH:
return isValidDashArray(value);
case SVGAttributes.TYPE_OTHER:
return true;
default:
//System.out.println(key);
break;
}
}
return false;
}
public static boolean isValidDashArray(String value){
//comma or space separated list of integers or NONE?
if(value.equalsIgnoreCase("none")) return true;
List<String> list = TagUtils.splitValueList(value);
for (String str : list) {
try{
int result = Integer.parseInt(str);
if(result < 0){
return false;
}
}catch(Exception exp){
return false;
}
}
return true;
}
public static boolean isValidString(String value, String[] possibleValues){
if(value == null) return false;
for (int i = 0; i < possibleValues.length; i++) {
if(possibleValues[i].equals(value)){
return true;
}
}
return false;
}
public static boolean isValidColor(String value){
if(value == null) return false;
if(value.equals("none")){
return true;
}
if(HtmlUtilities.decodeColor(value) != null){
return true;
}
if(cleanColorString(value) != null){
return true;
}
return false;
}
//TODO: dit is echt zwaar foefelen
//gecopieerd van WebColors and aangepast omdat in de SVG van openstreetmap, kleuren staan met decimale waarden ipv integers
public static BaseColor cleanColorString(String name){
int[] c = { 0, 0, 0, 255 };
name = name.toLowerCase();
if (name.startsWith("rgb(")) {
StringTokenizer tok = new StringTokenizer(name, "rgb(), \t\r\n\f");
for (int k = 0; k < 3; ++k) {
String v = tok.nextToken();
if (v.endsWith("%"))
c[k] = (int)Double.parseDouble(v.substring(0, v.length() - 1)) * 255 / 100;
else
c[k] = (int)Double.parseDouble(v);
if (c[k] < 0)
c[k] = 0;
else if (c[k] > 255)
c[k] = 255;
}
return new BaseColor(c[0], c[1], c[2], c[3]);
}
return null;
}
public static boolean isValidValueForLine(String value){
if(value == null) return false;
try{
double result = Double.parseDouble(value);
if(result >= 0){
return true;
}
}catch(Exception exp){
return false;
}
return false;
}
}