public static List<ShapeRecord> cubicToQuadratic(final double startX,final double startY,final double control1X,final double control1Y,final double control2X,final double control2Y,final double anchorX,final double anchorY){
  double ratio=3.0 / 4.0;
  double pax=startX + ((control1X - startX) * ratio);
  double pay=startY + ((control1Y - startY) * ratio);
  double pbx=anchorX + ((control2X - anchorX) * ratio);
  double pby=anchorY + ((control2Y - anchorY) * ratio);
  double dx=(anchorX - startX) / 16.0;
  double dy=(anchorY - startY) / 16.0;
  ratio=3.0 / 8.0;
  double c1x=startX + ((control1X - startX) * ratio);
  double c1y=startY + ((control1Y - startY) * ratio);
  double c2x=pax + ((pbx - pax) * ratio);
  double c2y=pay + ((pby - pay) * ratio);
  c2x=c2x - dx;
  c2y=c2y - dy;
  double c3x=pbx + ((pax - pbx) * ratio);
  double c3y=pby + ((pay - pby) * ratio);
  c3x=c3x + dx;
  c3y=c3y + dy;
  double c4x=anchorX + ((control2X - anchorX) * ratio);
  double c4y=anchorY + ((control2Y - anchorY) * ratio);
  double a1x=(c1x + c2x) / 2.0;
  double a1y=(c1y + c2y) / 2.0;
  double a2x=(pax + pbx) / 2.0;
  double a2y=(pay + pby) / 2.0;
  double a3x=(c3x + c4x) / 2.0;
  double a3y=(c3y + c4y) / 2.0;
  List<ShapeRecord> shapeRecords=new ArrayList<ShapeRecord>(4);
  shapeRecords.add(curvedEdge(startX,startY,c1x,c1y,a1x,a1y));
  shapeRecords.add(curvedEdge(a1x,a1y,c2x,c2y,a2x,a2y));
  shapeRecords.add(curvedEdge(a2x,a2y,c3x,c3y,a3x,a3y));
  shapeRecords.add(curvedEdge(a3x,a3y,c4x,c4y,anchorX,anchorY));
  return shapeRecords;
}

public static List < ShapeRecord > cubicToQuadratic ( final double startX , final double startY , final double control1X , final double control1Y , final double control2X , final double control2Y , final double anchorX , final double anchorY ) { double ratio = 3.0 / 4.0 ; double pax = startX + ( ( control1X - startX ) * ratio ) ; double pay = startY + ( ( control1Y - startY ) * ratio ) ; double pbx = anchorX + ( ( control2X - anchorX ) * ratio ) ; double pby = anchorY + ( ( control2Y - anchorY ) * ratio ) ; double dx = ( anchorX - startX ) / 16.0 ; double dy = ( anchorY - startY ) / 16.0 ; ratio = 3.0 / 8.0 ; double c1x = startX + ( ( control1X - startX ) * ratio ) ; double c1y = startY + ( ( control1Y - startY ) * ratio ) ; double c2x = pax + ( ( pbx - pax ) * ratio ) ; double c2y = pay + ( ( pby - pay ) * ratio ) ; c2x = c2x - dx ; c2y = c2y - dy ; double c3x = pbx + ( ( pax - pbx ) * ratio ) ; double c3y = pby + ( ( pay - pby ) * ratio ) ; c3x = c3x + dx ; c3y = c3y + dy ; double c4x = anchorX + ( ( control2X - anchorX ) * ratio ) ; double c4y = anchorY + ( ( control2Y - anchorY ) * ratio ) ; double a1x = ( c1x + c2x ) / 2.0 ; double a1y = ( c1y + c2y ) / 2.0 ; double a2x = ( pax + pbx ) / 2.0 ; double a2y = ( pay + pby ) / 2.0 ; double a3x = ( c3x + c4x ) / 2.0 ; double a3y = ( c3y + c4y ) / 2.0 ; List < ShapeRecord > shapeRecords = new ArrayList < ShapeRecord > ( 4 ) ; shapeRecords . add ( curvedEdge ( startX , startY , c1x , c1y , a1x , a1y ) ) ; shapeRecords . add ( curvedEdge ( a1x , a1y , c2x , c2y , a2x , a2y ) ) ; shapeRecords . add ( curvedEdge ( a2x , a2y , c3x , c3y , a3x , a3y ) ) ; shapeRecords . add ( curvedEdge ( a3x , a3y , c4x , c4y , anchorX , anchorY ) ) ; return shapeRecords ; }
approximates a cubic bezier as a series of 4 quadratic curvededgerecord with the method outlined by timothee groleau in actionscript ( which was based on helen triolo ' s approach of using casteljau ' s approximation ) . using a fixed level of 4 quadratic curves should be a fast way of achieving a reasonable approximation of the original curve . all coordinates are to be specified in pixels and will be converted to twips .
