001package com.hfg.svg.path;
002
003import java.awt.geom.Path2D;
004import java.awt.geom.Point2D;
005import java.util.List;
006                        
007//------------------------------------------------------------------------------
008/**
009 * Object representation of an SVG (Scalable Vector Graphics) path quadratic curveTo ('Q' or 'q') command.
010 *
011 * @author J. Alex Taylor, hairyfatguy.com
012 */
013//------------------------------------------------------------------------------
014// com.hfg XML/HTML Coding Library
015//
016// This library is free software; you can redistribute it and/or
017// modify it under the terms of the GNU Lesser General Public
018// License as published by the Free Software Foundation; either
019// version 2.1 of the License, or (at your option) any later version.
020//
021// This library is distributed in the hope that it will be useful,
022// but WITHOUT ANY WARRANTY; without even the implied warranty of
023// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
024// Lesser General Public License for more details.
025//
026// You should have received a copy of the GNU Lesser General Public
027// License along with this library; if not, write to the Free Software
028// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
029//
030// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
031// jataylor@hairyfatguy.com
032//------------------------------------------------------------------------------
033               
034public class SvgPathQuadCurveToCmd extends SvgPathCmd
035{
036   private Point2D.Float mControlPoint;
037
038   //---------------------------------------------------------------------------
039   public SvgPathQuadCurveToCmd()
040   {
041      super('Q');
042   }
043
044   //---------------------------------------------------------------------------
045   protected SvgPathQuadCurveToCmd(char inCmdChar)
046   {
047      super(inCmdChar);
048   }
049
050
051   //---------------------------------------------------------------------------
052   @Override
053   public SvgPathQuadCurveToCmd setRawNumbers(List<Float> inValue)
054   {
055      if (inValue.size()%getExpectedNumPoints() != 0)
056      {
057         throw new SvgPathDataException(getExpectedNumPoints() + " value" + (getExpectedNumPoints() != 1 ? "s" : "") + " must be given to a quadratic path " + getCmdChar() + " command!");
058      }
059
060      setNumSteps(inValue.size() /getExpectedNumPoints());
061
062      super.setRawNumbers(inValue);
063      return this;
064   }
065
066   //---------------------------------------------------------------------------
067   protected int getExpectedNumPoints()
068   {
069      return 4;
070   }
071
072
073   //--------------------------------------------------------------------------
074   public Point2D.Float getControlPoint()
075   {
076      return mControlPoint;
077   }
078
079   //--------------------------------------------------------------------------
080   protected void setControlPoint(Point2D.Float inValue)
081   {
082      mControlPoint = inValue;
083   }
084
085   //--------------------------------------------------------------------------
086   // From http://www.w3.org/TR/SVG/paths.html
087   //
088   // Draws a quadratic Bézier curve from the current point to (x,y) using (x1,y1) as the control point.
089   // Q (uppercase) indicates that absolute coordinates will follow; q (lowercase) indicates that relative coordinates
090   // will follow. Multiple sets of coordinates may be specified to draw a polybézier. At the end of the command,
091   // the new current point becomes the final (x,y) coordinate pair used in the polybézier.
092   public Point2D.Float draw(Path2D.Float inPolyline)
093   {
094      List<Float> rawNumbers = getRawNumbers();
095      int numIndex = 0;
096
097      Point2D.Float currentPoint = getStartingPoint();
098
099      while (numIndex < rawNumbers.size() - 1)
100      {
101         Point2D.Float point1 = new Point2D.Float(rawNumbers.get(numIndex++), rawNumbers.get(numIndex++));
102         Point2D.Float point2 = new Point2D.Float(rawNumbers.get(numIndex++), rawNumbers.get(numIndex++));
103
104         if (isRelative())
105         {
106            point1.setLocation(point1.getX() + currentPoint.getX(), point1.getY() + currentPoint.getY());
107            point2.setLocation(point2.getX() + currentPoint.getX(), point2.getY() + currentPoint.getY());
108         }
109
110         inPolyline.quadTo(point1.getX(), point1.getY(), point2.getX(), point2.getY());
111
112         setControlPoint(point1);
113
114         currentPoint = point2;
115      }
116
117      // Return the last point.
118      return currentPoint;
119   }
120}