/* * 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; import java.text.ParseException; import net.sf.latexdraw.models.MathUtils; import net.sf.latexdraw.models.interfaces.shape.Color; import net.sf.latexdraw.parsers.svg.parsers.SVGLengthParser; import org.w3c.dom.Node; /** * Defines the SVG tag <code>pattern</code>. * @author Arnaud BLOUIN * @since 0.1 */ public class SVGPatternElement extends SVGElement { /** * See {@link SVGElement#SVGElement(Node, SVGElement)}. * @throws MalformedSVGDocument If the element is not well formed. */ public SVGPatternElement(final Node n, final SVGElement p) throws MalformedSVGDocument { super(n, p); } /** * Creates a new empty SVG Pattern element. * @param doc The owner document. */ public SVGPatternElement(final SVGDocument doc) { super(doc); setNodeName(SVGElements.SVG_PATTERN); } @Override public boolean checkAttributes() { return !(getWidth()<0. || getHeight()<0.); } @Override public boolean enableRendering() { return !(MathUtils.INST.equalsDouble(getWidth(), 0.) || MathUtils.INST.equalsDouble(getHeight(), 0.)); } /** * @return The value of the X attribute (0 if there it does not exist or it is not a length). * @since 0.1 */ public double getX() { final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_X); double x; try { x = v==null ? 0. : new SVGLengthParser(v).parseCoordinate().getValue(); } catch(final ParseException e) { x = 0.; } return x; } /** * @return The value of the Y attribute (0 if there it does not exist or it is not a length). * @since 0.1 */ public double getY() { final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_Y); double y; try { y = v==null ? 0. : new SVGLengthParser(v).parseCoordinate().getValue(); } catch(final ParseException e) { y = 0.; } return y; } /** * @return The value of the <code>width</code> attribute. * @since 0.1 */ public double getWidth() { final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_WIDTH); double width; try { width = v==null ? 0. : new SVGLengthParser(v).parseLength().getValue(); } catch(final ParseException e) { width = 0.; } return width; } /** * @return The value of the <code>height</code> attribute. * @since 0.1 */ public double getHeight() { final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_HEIGHT); double height; try { height = v==null ? 0. : new SVGLengthParser(v).parseLength().getValue(); } catch(final ParseException e) { height = 0.; } return height; } /** * @return The coordinate system for the contents of the 'pattern'. * @since 0.1 */ public String getPatternContentUnits() { final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_PATTERN_CONTENTS_UNITS); return v==null || !SVGAttributes.SVG_UNITS_VALUE_OBJ.equals(v) && !SVGAttributes.SVG_UNITS_VALUE_USR.equals(v) ? SVGAttributes.SVG_UNITS_VALUE_USR : v; } /** * @return The coordinate system for attributes x, y, width and height. * @since 0.1 */ public String getPatternUnits() { final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_PATTERN_UNITS); return v==null || !SVGAttributes.SVG_UNITS_VALUE_OBJ.equals(v) && !SVGAttributes.SVG_UNITS_VALUE_USR.equals(v) ? SVGAttributes.SVG_UNITS_VALUE_OBJ : v; } /** * @return The g element of the pattern if there is a one (used to define if there is hatching). * @since 0.1 */ protected SVGGElement getGElement() { int i=0; final int size = children.getLength(); SVGGElement g = null; while(g==null && i<size) if(children.getNodes().get(i) instanceof SVGGElement) g = (SVGGElement)children.getNodes().get(i); else i++; return g; } /** * @return The background colour of the pattern if there is a one. * @since 0.1 */ public Color getBackgroundColor() { int i=0; final int size = children.getLength(); SVGRectElement rec = null; while(rec==null && i<size) if(children.getNodes().get(i) instanceof SVGRectElement) rec = (SVGRectElement)children.getNodes().get(i); else i++; return rec==null ? null : CSSColors.INSTANCE.getRGBColour(rec.getFill()); } /** * @return The separation between each line of the hatching if there is an hatching (based on the two first lines of the possible * hatching). * @since 2.0.0 */ public double getHatchingSep() { final SVGGElement g = getGElement(); if(g==null) return Double.NaN; SVGPathElement p = null; int i = 0; final int size = g.children.getLength(); int j=-1; while(p==null && i<size) if(g.children.getNodes().get(i) instanceof SVGPathElement) p = (SVGPathElement)g.children.getNodes().get(i); else i++; if(p==null) return Double.NaN; final String path = p.getPathData(); i = path.indexOf('L'); if(i!=-1) j = path.indexOf('L', i+1); if(i==-1 || j==-1) return Double.NaN; final String[] coord1 = path.substring(i, j).split(" ");//$NON-NLS-1$ final String[] coord2 = path.substring(j).split(" ");//$NON-NLS-1$ if(coord1.length<3 || coord2.length<3) return Double.NaN; try { final float l1x; final float l2x; final float l1y; final float l2y; l1x = Double.valueOf(coord1[1]).floatValue(); l1y = Double.valueOf(coord1[2]).floatValue(); l2x = Double.valueOf(coord2[1]).floatValue(); l2y = Double.valueOf(coord2[2]).floatValue(); if(MathUtils.INST.equalsDouble(l1x, l2x)) return Math.abs(l1y-l2y)-getHatchingStrokeWidth(); return Math.abs(l1x-l2x)-getHatchingStrokeWidth(); } catch(final NumberFormatException e) { /* To ignore. */ } return Double.NaN; } /** * @return The colour of the possible hatching if there is a one. * @since 0.1 */ public Color getHatchingColor() { final SVGGElement g = getGElement(); return g==null ? null : CSSColors.INSTANCE.getRGBColour(g.getAttribute(getUsablePrefix()+SVGAttributes.SVG_STROKE)); } /** * @return The stroke width of the possible hatching. * @since 0.1 */ public double getHatchingStrokeWidth() { final SVGGElement g = getGElement(); final String code = g==null ? null : g.getAttribute(getUsablePrefix()+SVGAttributes.SVG_STROKE_WIDTH); try { return code==null ? Double.NaN : new SVGLengthParser(code).parseLength().getValue(); } catch(final ParseException e){ return Double.NaN; } } }