/*
* 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.awt.geom.Point2D;
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>linearGradient</code>.
* @author Arnaud BLOUIN
*/
public class SVGLinearGradientElement extends SVGElement {
/**
* {@link SVGElement#SVGElement(Node, SVGElement)}
*/
public SVGLinearGradientElement(final Node n, final SVGElement p) throws MalformedSVGDocument {
super(n, p);
}
/**
* Creates an simple SVGLinearGradientElement with the owner document.
* @param owner The owner document.
* @throws IllegalArgumentException If owner is null.
* @since 0.1
*/
public SVGLinearGradientElement(final SVGDocument owner) {
super(owner);
setNodeName(SVGElements.SVG_LINEAR_GRADIENT);
}
@Override
public boolean checkAttributes() {
return true;
}
@Override
public boolean enableRendering() {
return true;
}
/**
* @return The coordinate system for attributes x1, y1, x2 and y2.
* @since 0.1
*/
public String getGradientUnits() {
final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_GRADIENT_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 value of the X1 attribute (0 if there it does not exist or it is not a length).
* @since 0.1
*/
public double getX1() {
final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_X1);
double x1;
try { x1 = v==null ? 0 : new SVGLengthParser(v).parseCoordinate().getValue(); }
catch(final ParseException e) { x1 = 0; }
return x1;
}
/**
* @return The value of the Y1 attribute (0 if there it does not exist or it is not a length).
* @since 0.1
*/
public double getY1() {
final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_Y1);
double y1;
try { y1 = v==null ? 0 : new SVGLengthParser(v).parseCoordinate().getValue(); }
catch(final ParseException e) { y1 = 0; }
return y1;
}
/**
* @return The value of the X2 attribute (0 if there it does not exist or it is not a length).
* @since 0.1
*/
public double getX2() {
final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_X2);
double x2;
try { x2 = v==null ? 0 : new SVGLengthParser(v).parseCoordinate().getValue(); }
catch(final ParseException e) { x2 = 0; }
return x2;
}
/**
* @return The value of the Y2 attribute (0 if there it does not exist or it is not a length).
* @since 0.1
*/
public double getY2() {
final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_Y2);
double y2;
try { y2 = v==null ? 0 : new SVGLengthParser(v).parseCoordinate().getValue(); }
catch(final ParseException e) { y2 = 0; }
return y2;
}
/**
* @return The start colour of the gradient or null.
* @since 0.1
*/
public Color getStartColor() {
final SVGNodeList nl = getChildren(SVGElements.SVG_STOP);
if(nl.getLength()==2) {
if(((SVGStopElement)nl.item(0)).getOffset()<((SVGStopElement)nl.item(1)).getOffset())
return ((SVGStopElement)nl.item(0)).getStopColor();
return ((SVGStopElement)nl.item(1)).getStopColor();
}
else
if(nl.getLength()==3) {
final SVGStopElement s1 = (SVGStopElement)nl.item(0);
final SVGStopElement s2 = (SVGStopElement)nl.item(1);
final SVGStopElement s3 = (SVGStopElement)nl.item(2);
if(s1.getOffset()<s2.getOffset()) {
if(s1.getOffset()<s3.getOffset())
return s1.getStopColor();
return s3.getStopColor();
}
if(s2.getOffset()<s3.getOffset())
return s2.getStopColor();
return s3.getStopColor();
}
return null;
}
/**
* @return The end colour of the gradient or null.
* @since 0.1
*/
public Color getEndColor() {
final SVGNodeList nl = getChildren(SVGElements.SVG_STOP);
if(nl.getLength()==2) {
if(((SVGStopElement)nl.item(0)).getOffset()>((SVGStopElement)nl.item(1)).getOffset())
return ((SVGStopElement)nl.item(0)).getStopColor();
return ((SVGStopElement)nl.item(1)).getStopColor();
}
else
if(nl.getLength()==3) {
final SVGStopElement s1 = (SVGStopElement)nl.item(0);
final SVGStopElement s2 = (SVGStopElement)nl.item(1);
final SVGStopElement s3 = (SVGStopElement)nl.item(2);
if(s1.getOffset()>s2.getOffset()) {
if(s1.getOffset()<s3.getOffset())
return s1.getStopColor();
return s3.getStopColor();
}
if(s2.getOffset()<s3.getOffset())
return s2.getStopColor();
return s3.getStopColor();
}
return null;
}
/**
* @return The middle point of the gradient (between 0 and 1 inclued) or NaN.
* @since 0.1
*/
public double getMiddlePoint() {
double midPoint = Double.NaN;
final SVGNodeList nl = getChildren(SVGElements.SVG_STOP);
if(nl.getLength()==2)
midPoint = Math.max(((SVGStopElement)nl.item(0)).getOffset(), ((SVGStopElement)nl.item(1)).getOffset());
else
if(nl.getLength()==3) {
final SVGStopElement s1 = (SVGStopElement)nl.item(0);
final SVGStopElement s2 = (SVGStopElement)nl.item(1);
final SVGStopElement s3 = (SVGStopElement)nl.item(2);
if(s1.getOffset()>s2.getOffset())
if(s1.getOffset()<s3.getOffset())
midPoint = s1.getOffset();
else
midPoint = s3.getOffset();
else
if(s2.getOffset()<s3.getOffset())
midPoint = s2.getOffset();
else
midPoint = s3.getOffset();
}
return midPoint;
}
/**
* @return The angle of the gradient in radian or NaN.
* @since 0.1
*/
public double getAngle() {
final double x1 = getX1();
final double x2 = getX2();
final double y1 = getY1();
final double y2 = getY2();
double angle = Double.NaN;
if(MathUtils.INST.equalsDouble(x1, x2))
if(SVGAttributes.SVG_UNITS_VALUE_OBJ.equals(getGradientUnits()))
angle = Math.PI/2.;
else
angle = 0.;
else
if(MathUtils.INST.equalsDouble(y1, y2))
angle = Math.PI;
if(Double.isNaN(angle)) {
final Point2D.Double c = new Point2D.Double((x1+x2)/2., (y1+y2)/2.);
angle = Math.asin(c.distance(x1, c.y)/c.distance(x1, y1));
}
return angle%(2*Math.PI);
}
/**
* Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle.
* @return pad | reflect | repeat
* @since 0.1
*/
public String getSpreadMethod() {
final String v = getAttribute(getUsablePrefix()+SVGAttributes.SVG_SPREAD_METHOD);
return v==null || !SVGAttributes.SVG_PAD.equals(v) && !SVGAttributes.SVG_REFLECT.equals(v) &&
!SVGAttributes.SVG_REPEAT.equals(v) ? SVGAttributes.SVG_PAD : v;
}
}