/*
* $Id: QuadraticSegment.java,v 1.1 2004/12/15 11:54:18 eed3si9n Exp $
*
* $Copyright: copyright (c) 2004, e.e d3si9n $
* $License:
* This source code is part of DoubleType.
* DoubleType is a graphical typeface designer.
*
* This program 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.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, e.e d3si9n gives permission to
* link the code of this program with any Java Platform that is available
* to public with free of charge, including but not limited to
* Sun Microsystem's JAVA(TM) 2 RUNTIME ENVIRONMENT (J2RE),
* and distribute linked combinations including the two.
* You must obey the GNU General Public License in all respects for all
* of the code used other than Java Platform. If you modify this file,
* you may extend this exception to your version of the file, but you are not
* obligated to do so. If you do not wish to do so, delete this exception
* statement from your version.
* $
*/
package org.doubletype.ossa.adapter;
import java.util.ArrayList;
/**
* @author e.e
*/
public class QuadraticSegment {
public static final int LINE = 0;
public static final int CURVE = 1;
/**
* converts quadratic contour into a list of quadratic segments.
*
* @param a_contour
* @return
*/
public static ArrayList<QuadraticSegment> toSegments(EContour a_contour) {
ArrayList<QuadraticSegment> retval = new ArrayList<>();
ArrayList points = toConcreatePoints(a_contour);
if (points.size() < 3) {
return retval;
}
for (int i = 0; i < points.size() - 1; i++) {
EContourPoint startPoint = (EContourPoint) points.get(i);
EContourPoint nextPoint = (EContourPoint) points.get(i + 1);
// if this is a line segment
if (nextPoint.isOn()) {
retval.add(new QuadraticSegment(startPoint, null, nextPoint));
} else {
EContourPoint offCurvePoint = nextPoint;
i++;
nextPoint = (EContourPoint) points.get(i + 1);
retval.add(new QuadraticSegment(startPoint, offCurvePoint, nextPoint));
}
}
return retval;
}
/**
* converts a list of quadratic segments into a quadratic contour.
*
* @param a_segments
* @return
*/
public static EContour toContour(ArrayList<QuadraticSegment> a_segments) {
EContour retval = new EContour();
retval.setType(EContour.k_quadratic);
for (QuadraticSegment segment : a_segments) {
EContourPoint p = segment.m_startPoint;
EContourPoint startPoint = new EContourPoint(p.getX(), p.getY(), p.isOn());
startPoint.setControlPoint1(null);
startPoint.setControlPoint2(null);
if (segment.m_type == LINE) {
retval.addContourPoint(startPoint);
} else {
retval.addContourPoint(startPoint);
retval.addContourPoint(segment.m_offCurvePoint);
}
}
return retval;
}
/**
* converts quadratic contour to concreate points by inserting
* on-curve point between off-curve points.
*
* @param a_contour
* @return
*/
private static ArrayList<EContourPoint> toConcreatePoints(EContour a_contour) {
ArrayList<EContourPoint> retval = new ArrayList<>();
ArrayList<EContourPoint> points = a_contour.getContourPoints();
if (points.size() < 3) {
return retval;
}
EContourPoint fromPoint = (EContourPoint) points.get(points.size() - 1);
for (EContourPoint point : points) {
EContourPoint toPoint = (EContourPoint) point;
if (!toPoint.isOn() && !fromPoint.isOn()) {
double xMidpoint = (toPoint.getX() + fromPoint.getX()) / 2;
double yMidpoint = (toPoint.getY() + fromPoint.getY()) / 2;
retval.add(new EContourPoint(xMidpoint, yMidpoint, true));
}
retval.add(toPoint);
fromPoint = toPoint;
}
// all contours should start with on-curve point
// move off-curve point to the end if a contour starts with one.
EContourPoint firstPoint = (EContourPoint) retval.get(0);
if (!firstPoint.isOn()) {
retval.remove(0);
retval.add(firstPoint);
}
retval.add(retval.get(0));
return retval;
}
private EContourPoint m_startPoint;
private EContourPoint m_offCurvePoint;
private EContourPoint m_endPoint;
private int m_type = LINE;
/**
*
*/
public QuadraticSegment(EContourPoint a_startPoint, EContourPoint a_offCurvePoint,
EContourPoint a_endPoint) {
m_startPoint = a_startPoint;
m_offCurvePoint = a_offCurvePoint;
m_endPoint = a_endPoint;
if (m_offCurvePoint != null) {
m_type = CURVE;
}
}
/**
* Convert quadratic segment to cubic.
*
* @param a_segment
* @return
*/
public CubicSegment toCubicSegment() {
// if the segment is a line
if (m_type == LINE) {
return new CubicSegment(m_startPoint, m_endPoint);
}
double x, y;
x = m_startPoint.getX() + 2.0 / 3.0 * (m_offCurvePoint.getX() - m_startPoint.getX());
y = m_startPoint.getY() + 2.0 / 3.0 * (m_offCurvePoint.getY() - m_startPoint.getY());
EContourPoint controlPoint1 = new EContourPoint(x, y, false);
x = m_offCurvePoint.getX() + 1.0 / 3.0 * (m_endPoint.getX() - m_offCurvePoint.getX());
y = m_offCurvePoint.getY() + 1.0 / 3.0 * (m_endPoint.getY() - m_offCurvePoint.getY());
EContourPoint controlPoint2 = new EContourPoint(x, y, false);
return new CubicSegment(m_startPoint, controlPoint1, controlPoint2, m_endPoint);
}
}