/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2013 by Alexander Heusel
*
* This file is part of svgfx.
*
* svgfx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* as published by the Free Software Foundation.
*
* see: http://opensource.org/licenses/LGPL-3.0
*
* svgfx 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 Lesser General Public License for more details.
*
* This version of svgfx includes copyright notice and attribution requirements.
* According to the LGPL this information must be displayed even if you modify
* the source code of svgfx. Neither the copyright statement nor the attribution
* may be removed.
*
* Attribution Requirements:
*
* If you create derived work you must do two things regarding copyright notice
* and author attribution.
*
* First, the copyright notice must remain. It must be reproduced in any program
* that uses svgfx.
*
* Second, add an additional notice, stating that you modified svgfx. A suitable
* notice might read "svgfx source code modified by YourName 2012".
*
* Note, that these requirements are in full accordance with the LGPL v3
* (see 7. Additional Terms, b).
*
*/
package svg2fx;
import javafx.scene.shape.ArcTo;
import javafx.scene.shape.ClosePath;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.HLineTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import javafx.scene.shape.QuadCurveTo;
import javafx.scene.shape.VLineTo;
import org.w3c.dom.svg.*;
import svg2fx.interfaces.PathSegVisitor;
/**
*
* @author Alexander Heusel
*/
public class PathBuilder implements PathSegVisitor
{
private double x;
private double y;
private Path path;
public PathBuilder()
{
this.x = 0.0;
this.y = 0.0;
path = null;
}
public void pushPath(Path path)
{
this.x = 0.0;
this.y = 0.0;
this.path = path;
}
private static PathElement last(Path p)
{
return p.getElements().get(p.getElements().size());
}
private void update(ArcTo pe)
{
if(pe.isAbsolute())
{
x = pe.getX();
y = pe.getY();
}
else
{
x += pe.getX();
y += pe.getY();
}
path.getElements().add(pe);
}
private void update(CubicCurveTo pe)
{
if(pe.isAbsolute())
{
x = pe.getX();
y = pe.getY();
}
else
{
x += pe.getX();
y += pe.getY();
}
path.getElements().add(pe);
}
private void update(HLineTo pe)
{
if(pe.isAbsolute())
{
x = pe.getX();
}
else
{
x += pe.getX();
}
path.getElements().add(pe);
}
private void update(LineTo pe)
{
if(pe.isAbsolute())
{
x = pe.getX();
y = pe.getY();
}
else
{
x += pe.getX();
y += pe.getY();
}
path.getElements().add(pe);
}
private void update(MoveTo pe)
{
if(pe.isAbsolute())
{
x = pe.getX();
y = pe.getY();
}
else
{
x += pe.getX();
y += pe.getY();
}
path.getElements().add(pe);
}
private void update(QuadCurveTo pe)
{
if(pe.isAbsolute())
{
x = pe.getX();
y = pe.getY();
}
else
{
x += pe.getX();
y += pe.getY();
}
path.getElements().add(pe);
}
private void update(VLineTo pe)
{
if(pe.isAbsolute())
{
y = pe.getY();
}
else
{
y += pe.getY();
}
path.getElements().add(pe);
}
private void update(ClosePath pe)
{
path.getElements().add(pe);
}
@Override
public void visitSVGPathSegMovetoAbs(SVGPathSegMovetoAbs svgPathSegm)
{
MoveTo mt = new MoveTo(svgPathSegm.getX(), svgPathSegm.getY());
mt.setAbsolute(true);
update(mt);
}
@Override
public void visitSVGPathSegMovetoRel(SVGPathSegMovetoRel svgPathSegm)
{
MoveTo mt = new MoveTo(svgPathSegm.getX(), svgPathSegm.getY());
mt.setAbsolute(path.getElements().isEmpty());
update(mt);
}
@Override
public void visitSVGPathSegLinetoAbs(SVGPathSegLinetoAbs svgPathSegm)
{
LineTo lt = new LineTo(svgPathSegm.getX(), svgPathSegm.getY());
lt.setAbsolute(true);
update(lt);
}
@Override
public void visitSVGPathSegLinetoRel(SVGPathSegLinetoRel svgPathSegm)
{
LineTo lt = new LineTo(svgPathSegm.getX(), svgPathSegm.getY());
lt.setAbsolute(false);
update(lt);
}
@Override
public void visitSVGPathSegLinetoHorizontalAbs(SVGPathSegLinetoHorizontalAbs svgPathSegm)
{
HLineTo hlt = new HLineTo(svgPathSegm.getX());
hlt.setAbsolute(true);
update(hlt);
}
@Override
public void visitSVGPathSegLinetoHorizontalRel(SVGPathSegLinetoHorizontalRel svgPathSegm)
{
HLineTo hlt = new HLineTo(svgPathSegm.getX());
hlt.setAbsolute(false);
update(hlt);
}
@Override
public void visitSVGPathSegLinetoVerticalAbs(SVGPathSegLinetoVerticalAbs svgPathSegm)
{
VLineTo vlt = new VLineTo(svgPathSegm.getY());
vlt.setAbsolute(true);
update(vlt);
}
@Override
public void visitSVGPathSegLinetoVerticalRel(SVGPathSegLinetoVerticalRel svgPathSegm)
{
VLineTo vlt = new VLineTo(svgPathSegm.getY());
vlt.setAbsolute(false);
update(vlt);
}
@Override
public void visitSVGPathSegCurvetoCubicAbs(SVGPathSegCurvetoCubicAbs svgPathSegm)
{
CubicCurveTo cct = new CubicCurveTo(svgPathSegm.getX1(), svgPathSegm.getY1(),
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
cct.setAbsolute(true);
update(cct);
}
@Override
public void visitSVGPathSegCurvetoCubicRel(SVGPathSegCurvetoCubicRel svgPathSegm)
{
CubicCurveTo cct = new CubicCurveTo(svgPathSegm.getX1(), svgPathSegm.getY1(),
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
cct.setAbsolute(false);
update(cct);
}
@Override
public void visitSVGPathSegCurvetoCubicSmoothAbs(SVGPathSegCurvetoCubicSmoothAbs svgPathSegm)
{
PathElement pathElement = last(path);
CubicCurveTo cct = null;
CubicCurveTo pcct = null;
if(pathElement instanceof CubicCurveTo)
{
pcct = (CubicCurveTo)pathElement;
if(pcct.isAbsolute())
{
cct = new CubicCurveTo( 2*x - pcct.getControlX2(), 2*y - pcct.getControlY2(),
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
}
else
{
cct = new CubicCurveTo( x + pcct.getX() - pcct.getControlX2(), y + pcct.getY() - pcct.getControlY2(),
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
}
}
else
{
cct = new CubicCurveTo( x, y,
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
}
cct.setAbsolute(true);
update(cct);
}
@Override
public void visitSVGPathSegCurvetoCubicSmoothRel(SVGPathSegCurvetoCubicSmoothRel svgPathSegm)
{
PathElement pathElement = last(path);
CubicCurveTo cct = null;
CubicCurveTo pcct = null;
if(pathElement instanceof CubicCurveTo)
{
pcct = (CubicCurveTo)pathElement;
if(pcct.isAbsolute())
{
cct = new CubicCurveTo( x - pcct.getControlX2(), y - pcct.getControlY2(),
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
}
else
{
cct = new CubicCurveTo( pcct.getX() - pcct.getControlX2(), pcct.getY() - pcct.getControlY2(),
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
}
}
else
{
cct = new CubicCurveTo( 0.0, 0.0,
svgPathSegm.getX2(), svgPathSegm.getY2(),
svgPathSegm.getX(), svgPathSegm.getY());
}
cct.setAbsolute(false);
update(cct);
}
@Override
public void visitSVGPathSegCurvetoQuadraticAbs(SVGPathSegCurvetoQuadraticAbs svgPathSegm)
{
QuadCurveTo qct = new QuadCurveTo(svgPathSegm.getX1(), svgPathSegm.getY1(), svgPathSegm.getX(), svgPathSegm.getY());
qct.setAbsolute(true);
update(qct);
}
@Override
public void visitSVGPathSegCurvetoQuadraticRel(SVGPathSegCurvetoQuadraticRel svgPathSegm)
{
QuadCurveTo qct = new QuadCurveTo(svgPathSegm.getX1(), svgPathSegm.getY1(), svgPathSegm.getX(), svgPathSegm.getY());
qct.setAbsolute(false);
update(qct);
}
@Override
public void visitSVGPathSegCurvetoQuadraticSmoothAbs(SVGPathSegCurvetoQuadraticSmoothAbs svgPathSegm)
{
PathElement pathElement = last(path);
QuadCurveTo qct = null;
QuadCurveTo pqct = null;
if(pathElement instanceof QuadCurveTo)
{
pqct = (QuadCurveTo)pathElement;
if(pqct.isAbsolute())
{
qct = new QuadCurveTo( 2*x - pqct.getControlX(),
2*y - pqct.getControlY(),
svgPathSegm.getX(), svgPathSegm.getY());
}
else
{
qct = new QuadCurveTo( x + pqct.getX() - pqct.getControlX(),
y + pqct.getY() - pqct.getControlY(),
svgPathSegm.getX(), svgPathSegm.getY());
}
}
else
{
qct = new QuadCurveTo(x, y, svgPathSegm.getX(), svgPathSegm.getY());
}
qct.setAbsolute(true);
update(qct);
}
@Override
public void visitSVGPathSegCurvetoQuadraticSmoothRel(SVGPathSegCurvetoQuadraticSmoothRel svgPathSegm)
{
PathElement pathElement = last(path);
QuadCurveTo qct = null;
QuadCurveTo pqct = null;
if(pathElement instanceof QuadCurveTo)
{
pqct = (QuadCurveTo)pathElement;
if(pqct.isAbsolute())
{
qct = new QuadCurveTo( 2*x - pqct.getControlX(),
2*y - pqct.getControlY(),
svgPathSegm.getX(), svgPathSegm.getY());
}
else
{
qct = new QuadCurveTo( x + pqct.getX() - pqct.getControlX(),
y + pqct.getY() - pqct.getControlY(),
svgPathSegm.getX(), svgPathSegm.getY());
}
}
else
{
qct = new QuadCurveTo(0.0, 0.0, svgPathSegm.getX(), svgPathSegm.getY());
}
qct.setAbsolute(false);
update(qct);
}
@Override
public void visitSVGPathSegArcAbs(SVGPathSegArcAbs svgPathSegm)
{
ArcTo art = new ArcTo( svgPathSegm.getR1() , svgPathSegm.getR2(),
svgPathSegm.getAngle(), svgPathSegm.getX(), svgPathSegm.getY(),
svgPathSegm.getLargeArcFlag(), svgPathSegm.getSweepFlag());
art.setAbsolute(true);
update(art);
}
@Override
public void visitSVGPathSegArcRel(SVGPathSegArcRel svgPathSegm)
{
ArcTo art = new ArcTo( svgPathSegm.getR1() , svgPathSegm.getR2(),
svgPathSegm.getAngle(), svgPathSegm.getX(), svgPathSegm.getY(),
svgPathSegm.getLargeArcFlag(), svgPathSegm.getSweepFlag());
art.setAbsolute(false);
update(art);
}
@Override
public void visitSVGPathSegClosePath(SVGPathSegClosePath svgPathSegm)
{
update(new ClosePath());
}
}