package com.kreative.paint.io;
import java.awt.Shape;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import com.kreative.paint.document.draw.Path;
import com.kreative.paint.document.draw.PathContour;
import com.kreative.paint.document.draw.PathPoint;
import com.kreative.paint.geom.*;
import com.kreative.paint.material.shape.*;
public class CKPGeomSerializer extends Serializer {
private static final int TYPE_BITMAP_SHAPE = fcc("BmSh");
private static final int TYPE_CYCLOID = fcc("Cycl");
private static final int TYPE_FLOWER = fcc("Flow");
private static final int TYPE_REGULAR_POLYGON = fcc("RPly");
private static final int TYPE_RIGHT_ARC = fcc("ArcR");
private static final int TYPE_SCALED_SHAPE = fcc("ScSh");
private static final int TYPE_SPIRAL = fcc("Spir");
private static final int TYPE_PARAMETER = fcc("pPrm");
private static final int TYPE_PARAMETERIZED_PATH = fcc("pPth");
private static final int TYPE_PARAMETERIZED_POINT = fcc("pPnt");
private static final int TYPE_PARAMETERIZED_SHAPE_ARC = fcc("pArc");
private static final int TYPE_PARAMETERIZED_SHAPE_CIRCLE = fcc("pCir");
private static final int TYPE_PARAMETERIZED_SHAPE_ELLIPSE = fcc("pEll");
private static final int TYPE_PARAMETERIZED_SHAPE_LINE = fcc("pLin");
private static final int TYPE_PARAMETERIZED_SHAPE_POLYGON = fcc("pPly");
private static final int TYPE_PARAMETERIZED_SHAPE_POLYLINE = fcc("pPLn");
private static final int TYPE_PARAMETERIZED_SHAPE_RECT = fcc("pRec");
private static final int TYPE_PARAMETERIZED_VALUE = fcc("pVal");
private static final int TYPE_PATH = fcc("^Pth");
private static final int TYPE_PATH_CONTOUR = fcc("^Cnt");
private static final int TYPE_PATH_POINT = fcc("^Pnt");
private static final int TYPE_POWERSHAPE = fcc("pShp");
private static final int TYPE_POWERSHAPE_LIST = fcc("SLst");
protected void loadRecognizedTypesAndClasses() {
addTypeAndClass(TYPE_BITMAP_SHAPE, 1, BitmapShape.class);
addTypeAndClass(TYPE_CYCLOID, 1, Cycloid.class);
addTypeAndClass(TYPE_FLOWER, 1, Flower.class);
addTypeAndClass(TYPE_REGULAR_POLYGON, 1, RegularPolygon.class);
addTypeAndClass(TYPE_RIGHT_ARC, 1, RightArc.class);
addTypeAndClass(TYPE_SCALED_SHAPE, 1, ScaledShape.class);
addTypeAndClass(TYPE_SPIRAL, 1, Spiral.class);
addTypeAndClass(TYPE_PARAMETER, 1, Parameter.class);
addTypeAndClass(TYPE_PARAMETERIZED_PATH, 2, ParameterizedPath.class);
addTypeAndClass(TYPE_PARAMETERIZED_POINT, 1, ParameterizedPoint.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_ARC, 1, ParameterizedShape.Arc.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_CIRCLE, 1, ParameterizedShape.Circle.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_ELLIPSE, 1, ParameterizedShape.Ellipse.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_LINE, 1, ParameterizedShape.Line.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_POLYGON, 1, ParameterizedShape.Polygon.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_POLYLINE, 1, ParameterizedShape.PolyLine.class);
addTypeAndClass(TYPE_PARAMETERIZED_SHAPE_RECT, 1, ParameterizedShape.Rect.class);
addTypeAndClass(TYPE_PARAMETERIZED_VALUE, 1, ParameterizedValue.class);
addTypeAndClass(TYPE_PATH, 1, Path.class);
addTypeAndClass(TYPE_PATH_CONTOUR, 1, PathContour.class);
addTypeAndClass(TYPE_PATH_POINT, 1, PathPoint.class);
addTypeAndClass(TYPE_POWERSHAPE, 2, PowerShape.class);
addTypeAndClass(TYPE_POWERSHAPE_LIST, 1, PowerShapeList.class);
}
public void serializeObject(Object o, DataOutputStream stream) throws IOException {
if (o instanceof BitmapShape) {
BitmapShape v = (BitmapShape)o;
stream.writeInt(v.getX());
stream.writeInt(v.getY());
stream.writeInt(v.getWidth());
stream.writeInt(v.getHeight());
int[] rgb = v.getBitmap();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(bos);
for (int p : rgb) dos.write((p >> 24) & 0xFF);
for (int p : rgb) dos.write((p >> 16) & 0xFF);
for (int p : rgb) dos.write((p >> 8) & 0xFF);
for (int p : rgb) dos.write(p & 0xFF);
dos.finish();
dos.close();
bos.close();
byte crgb[] = bos.toByteArray();
stream.writeInt(crgb.length);
stream.write(crgb);
} else if (o instanceof Cycloid) {
Cycloid v = (Cycloid)o;
stream.writeInt(v.isEpicycloid() ? 1 : 0);
stream.writeInt(v.getSmoothness());
stream.writeInt(v.getBegin());
stream.writeInt(v.getEnd());
stream.writeDouble(v.getR());
stream.writeDouble(v.getr());
stream.writeDouble(v.getd());
stream.writeFloat(v.getCenter().x);
stream.writeFloat(v.getCenter().y);
stream.writeFloat(v.getEndpoint().x);
stream.writeFloat(v.getEndpoint().y);
} else if (o instanceof Flower) {
Flower v = (Flower)o;
stream.writeInt(v.getPetals());
stream.writeDouble(v.getWidth());
stream.writeInt(v.getSmoothness());
stream.writeInt(v.getIncludeCenter() ? 1 : 0);
stream.writeFloat(v.getCenter().x);
stream.writeFloat(v.getCenter().y);
stream.writeFloat(v.getEndpoint().x);
stream.writeFloat(v.getEndpoint().y);
} else if (o instanceof RegularPolygon) {
RegularPolygon v = (RegularPolygon)o;
stream.writeInt(v.getSides());
stream.writeInt(v.getSkips());
Point2D c = v.getCenterInternal();
Point2D e1 = v.getFirstVertexInternal();
Point2D e2 = v.getSecondVertexInternal();
if (c == null && e2 != null) {
stream.writeInt(fcc("VtoV"));
stream.writeDouble(e1.getX());
stream.writeDouble(e1.getY());
stream.writeDouble(e2.getX());
stream.writeDouble(e2.getY());
}
else if (e2 == null && c != null) {
stream.writeInt(fcc("CtoV"));
stream.writeDouble(c.getX());
stream.writeDouble(c.getY());
stream.writeDouble(e1.getX());
stream.writeDouble(e1.getY());
}
else {
stream.writeInt(fcc("????"));
}
} else if (o instanceof RightArc) {
RightArc v = (RightArc)o;
stream.writeFloat((float)v.getX());
stream.writeFloat((float)v.getY());
stream.writeFloat((float)v.getWidth());
stream.writeFloat((float)v.getHeight());
} else if (o instanceof ScaledShape) {
ScaledShape v = (ScaledShape)o;
stream.writeDouble(v.getX());
stream.writeDouble(v.getY());
stream.writeDouble(v.getWidth());
stream.writeDouble(v.getHeight());
SerializationManager.writeObject(v.getOriginalShape(), stream);
} else if (o instanceof Spiral) {
Spiral v = (Spiral)o;
stream.writeInt(v.getSides());
stream.writeInt(v.getSpokes() ? 1 : 0);
stream.writeDouble(v.getSpacing());
stream.writeFloat(v.getCenter().x);
stream.writeFloat(v.getCenter().y);
stream.writeFloat(v.getEndpoint().x);
stream.writeFloat(v.getEndpoint().y);
} else if (o instanceof Parameter) {
Parameter v = (Parameter)o;
stream.writeInt(v.polar ? 0x706F6C72 : 0x72656374);
stream.writeDouble(v.originX);
stream.writeDouble(v.originY);
if (v.polar) {
stream.writeDouble(v.minR);
stream.writeDouble(v.minA);
stream.writeDouble(v.defR);
stream.writeDouble(v.defA);
stream.writeDouble(v.maxR);
stream.writeDouble(v.maxA);
} else {
stream.writeDouble(v.minX);
stream.writeDouble(v.minY);
stream.writeDouble(v.defX);
stream.writeDouble(v.defY);
stream.writeDouble(v.maxX);
stream.writeDouble(v.maxY);
}
stream.writeUTF(v.name);
} else if (o instanceof ParameterizedPath) {
ParameterizedPath v = (ParameterizedPath)o;
stream.writeInt(v.size());
for (int i = 0, n = v.size(); i < n; i++) {
stream.writeChar(v.getOpcode(i));
stream.writeShort(v.getOperands(i).size());
for (ParameterizedValue pv : v.getOperands(i)) {
SerializationManager.writeObject(pv, stream);
}
}
} else if (o instanceof ParameterizedPoint) {
ParameterizedPoint v = (ParameterizedPoint)o;
boolean xv = (v.x.expr instanceof Expression.Value);
boolean yv = (v.y.expr instanceof Expression.Value);
if (xv && yv) {
stream.writeInt(-2);
stream.writeInt(-2);
stream.writeDouble(((Expression.Value)v.x.expr).value);
stream.writeDouble(((Expression.Value)v.y.expr).value);
} else {
stream.writeInt(-1);
stream.writeInt(-1);
stream.writeUTF(v.x.source);
stream.writeUTF(v.y.source);
}
} else if (o instanceof ParameterizedShape.Arc) {
ParameterizedShape.Arc v = (ParameterizedShape.Arc)o;
SerializationManager.writeObject(v.cx, stream);
SerializationManager.writeObject(v.cy, stream);
SerializationManager.writeObject(v.rx, stream);
SerializationManager.writeObject(v.ry, stream);
SerializationManager.writeObject(v.start, stream);
SerializationManager.writeObject(v.extent, stream);
stream.writeInt((v.type != null) ? v.type.awtValue : -1);
} else if (o instanceof ParameterizedShape.Circle) {
ParameterizedShape.Circle v = (ParameterizedShape.Circle)o;
SerializationManager.writeObject(v.cx, stream);
SerializationManager.writeObject(v.cy, stream);
SerializationManager.writeObject(v.r, stream);
} else if (o instanceof ParameterizedShape.Ellipse) {
ParameterizedShape.Ellipse v = (ParameterizedShape.Ellipse)o;
SerializationManager.writeObject(v.cx, stream);
SerializationManager.writeObject(v.cy, stream);
SerializationManager.writeObject(v.rx, stream);
SerializationManager.writeObject(v.ry, stream);
} else if (o instanceof ParameterizedShape.Line) {
ParameterizedShape.Line v = (ParameterizedShape.Line)o;
SerializationManager.writeObject(v.x1, stream);
SerializationManager.writeObject(v.y1, stream);
SerializationManager.writeObject(v.x2, stream);
SerializationManager.writeObject(v.y2, stream);
} else if (o instanceof ParameterizedShape.Polygon) {
ParameterizedShape.Polygon v = (ParameterizedShape.Polygon)o;
stream.writeInt(v.points.length);
for (ParameterizedValue pv : v.points) {
SerializationManager.writeObject(pv, stream);
}
} else if (o instanceof ParameterizedShape.PolyLine) {
ParameterizedShape.PolyLine v = (ParameterizedShape.PolyLine)o;
stream.writeInt(v.points.length);
for (ParameterizedValue pv : v.points) {
SerializationManager.writeObject(pv, stream);
}
} else if (o instanceof ParameterizedShape.Rect) {
ParameterizedShape.Rect v = (ParameterizedShape.Rect)o;
SerializationManager.writeObject(v.x, stream);
SerializationManager.writeObject(v.y, stream);
SerializationManager.writeObject(v.width, stream);
SerializationManager.writeObject(v.height, stream);
SerializationManager.writeObject(v.rx, stream);
SerializationManager.writeObject(v.ry, stream);
} else if (o instanceof ParameterizedValue) {
ParameterizedValue v = (ParameterizedValue)o;
if (v.expr instanceof Expression.Value) {
stream.writeInt(-2);
stream.writeDouble(((Expression.Value)v.expr).value);
} else {
stream.writeInt(-1);
stream.writeUTF(v.source);
}
} else if (o instanceof Path) {
Path v = (Path)o;
stream.writeInt(v.size());
for (PathContour c : v) {
stream.writeInt(c.size());
for (PathPoint p : c) {
stream.writeDouble(p.getPreviousCtrl().getX());
stream.writeDouble(p.getPreviousCtrl().getY());
stream.writeDouble(p.getX());
stream.writeDouble(p.getY());
stream.writeDouble(p.getNextCtrl().getX());
stream.writeDouble(p.getNextCtrl().getY());
stream.writeBoolean(p.isPreviousQuadratic());
stream.writeBoolean(p.isAngleLocked());
stream.writeBoolean(p.isRadiusLocked());
stream.writeBoolean(p.isNextQuadratic());
}
stream.writeBoolean(c.isClosed());
}
} else if (o instanceof PathContour) {
PathContour v = (PathContour)o;
stream.writeInt(v.size());
for (PathPoint p : v) {
stream.writeDouble(p.getPreviousCtrl().getX());
stream.writeDouble(p.getPreviousCtrl().getY());
stream.writeDouble(p.getX());
stream.writeDouble(p.getY());
stream.writeDouble(p.getNextCtrl().getX());
stream.writeDouble(p.getNextCtrl().getY());
stream.writeBoolean(p.isPreviousQuadratic());
stream.writeBoolean(p.isAngleLocked());
stream.writeBoolean(p.isRadiusLocked());
stream.writeBoolean(p.isNextQuadratic());
}
stream.writeBoolean(v.isClosed());
} else if (o instanceof PathPoint) {
PathPoint v = (PathPoint)o;
stream.writeDouble(v.getPreviousCtrl().getX());
stream.writeDouble(v.getPreviousCtrl().getY());
stream.writeDouble(v.getX());
stream.writeDouble(v.getY());
stream.writeDouble(v.getNextCtrl().getX());
stream.writeDouble(v.getNextCtrl().getY());
stream.writeBoolean(v.isPreviousQuadratic());
stream.writeBoolean(v.isAngleLocked());
stream.writeBoolean(v.isRadiusLocked());
stream.writeBoolean(v.isNextQuadratic());
} else if (o instanceof PowerShape) {
PowerShape v = (PowerShape)o;
List<String> params = v.getParameterNames();
List<ParameterizedShape> shapes = v.getShapes();
stream.writeInt(params.size());
stream.writeInt(params.size());
stream.writeInt(shapes.size());
stream.writeInt((v.windingRule != null) ? v.windingRule.awtValue : -1);
stream.writeUTF((v.name != null) ? v.name : "");
for (String n : params) {
SerializationManager.writeObject(v.getParameter(n), stream);
}
for (String n : params) {
Point2D p = v.getParameterValue(n);
stream.writeDouble(p.getX());
stream.writeDouble(p.getY());
stream.writeUTF(n);
}
for (ParameterizedShape s : shapes) {
SerializationManager.writeObject(s, stream);
}
} else if (o instanceof PowerShapeList) {
PowerShapeList v = (PowerShapeList)o;
stream.writeInt(v.size());
stream.writeBoolean(v.name != null);
for (PowerShape shape : v) {
SerializationManager.writeObject(shape, stream);
}
if (v.name != null) {
stream.writeUTF(v.name);
}
}
}
public Object deserializeObject(int type, int version, DataInputStream stream) throws IOException {
if (type == TYPE_BITMAP_SHAPE) {
if (version != 1) throw new IOException("Invalid version number.");
int x = stream.readInt();
int y = stream.readInt();
int w = stream.readInt();
int h = stream.readInt();
int l = stream.readInt();
byte[] crgb = new byte[l];
stream.read(crgb);
int[] rgb = new int[w*h];
ByteArrayInputStream bis = new ByteArrayInputStream(crgb);
InflaterInputStream iis = new InflaterInputStream(bis);
for (int i = 0; i < rgb.length; i++) rgb[i] |= ((iis.read() << 24) & 0xFF000000);
for (int i = 0; i < rgb.length; i++) rgb[i] |= ((iis.read() << 16) & 0x00FF0000);
for (int i = 0; i < rgb.length; i++) rgb[i] |= ((iis.read() << 8) & 0xFF00);
for (int i = 0; i < rgb.length; i++) rgb[i] |= (iis.read() & 0xFF);
iis.close();
bis.close();
return new BitmapShape(rgb, x, y, w, h);
} else if (type == TYPE_CYCLOID) {
if (version != 1) throw new IOException("Invalid version number.");
boolean epi = (stream.readInt() != 0);
int smoothness = stream.readInt();
int begin = stream.readInt();
int end = stream.readInt();
double R = stream.readDouble();
double r = stream.readDouble();
double d = stream.readDouble();
float cx = stream.readFloat();
float cy = stream.readFloat();
float vx = stream.readFloat();
float vy = stream.readFloat();
return new Cycloid(epi, smoothness, begin, end, R, r, d, cx, cy, vx, vy);
} else if (type == TYPE_FLOWER) {
if (version != 1) throw new IOException("Invalid version number.");
int petals = stream.readInt();
double width = stream.readDouble();
int smoothness = stream.readInt();
boolean includeCenter = (stream.readInt() != 0);
float cx = stream.readFloat();
float cy = stream.readFloat();
float vx = stream.readFloat();
float vy = stream.readFloat();
return new Flower(petals, width, smoothness, includeCenter, cx, cy, vx, vy);
} else if (type == TYPE_REGULAR_POLYGON) {
if (version != 1) throw new IOException("Invalid version number.");
int sides = stream.readInt();
int skips = stream.readInt();
int t = stream.readInt();
if (t == fcc("VtoV")) {
double v1x = stream.readDouble();
double v1y = stream.readDouble();
double v2x = stream.readDouble();
double v2y = stream.readDouble();
return new RegularPolygon(v1x, v1y, v2x, v2y, sides, skips, false);
}
else if (t == fcc("CtoV")) {
double cx = stream.readDouble();
double cy = stream.readDouble();
double vx = stream.readDouble();
double vy = stream.readDouble();
return new RegularPolygon(cx, cy, vx, vy, sides, skips, true);
}
else return null;
} else if (type == TYPE_RIGHT_ARC) {
if (version != 1) throw new IOException("Invalid version number.");
float x = stream.readFloat();
float y = stream.readFloat();
float w = stream.readFloat();
float h = stream.readFloat();
return new RightArc(x, y, w, h);
} else if (type == TYPE_SCALED_SHAPE) {
if (version != 1) throw new IOException("Invalid version number.");
double x = stream.readDouble();
double y = stream.readDouble();
double w = stream.readDouble();
double h = stream.readDouble();
Shape shape = (Shape)SerializationManager.readObject(stream);
return new ScaledShape(x, y, w, h, shape);
} else if (type == TYPE_SPIRAL) {
if (version != 1) throw new IOException("Invalid version number.");
int sides = stream.readInt();
boolean spokes = (stream.readInt() != 0);
double spacing = stream.readDouble();
float cx = stream.readFloat();
float cy = stream.readFloat();
float vx = stream.readFloat();
float vy = stream.readFloat();
return new Spiral(sides, spacing, spokes, cx, cy, vx, vy);
} else if (type == TYPE_PARAMETER) {
if (version != 1) throw new IOException("Invalid version number.");
boolean polar = (stream.readInt() == 0x706F6C72);
double originX = stream.readDouble();
double originY = stream.readDouble();
double minX = stream.readDouble();
double minY = stream.readDouble();
double defX = stream.readDouble();
double defY = stream.readDouble();
double maxX = stream.readDouble();
double maxY = stream.readDouble();
String name = stream.readUTF();
return new Parameter(
name, originX, originY, polar,
minX, minY, minX, minY,
defX, defY, defX, defY,
maxX, maxY, maxX, maxY
);
} else if (type == TYPE_PARAMETERIZED_PATH) {
if (version < 1 || version > 2) throw new IOException("Invalid version number.");
if (version >= 2) {
ParameterizedPath path = new ParameterizedPath();
int nseg = stream.readInt();
while (nseg-- > 0) {
char t = stream.readChar();
int n = stream.readShort();
List<ParameterizedValue> v = new ArrayList<ParameterizedValue>();
while (n-- > 0) {
v.add((ParameterizedValue)SerializationManager.readObject(stream));
}
path.add(t, v);
}
return path;
} else {
ParameterizedPath path = new ParameterizedPath();
switch (stream.readShort()) {
case 0x454F: path.add('W', new ParameterizedValue(0.0)); break;
case 0x4E5A: path.add('W', new ParameterizedValue(1.0)); break;
}
stream.readShort();
int npp = stream.readInt();
while (npp-- > 0) {
Parameter pp = (Parameter)SerializationManager.readObject(stream);
path.add(
'P',
new ParameterizedValue(pp.name, new Expression.Binding(pp.name)),
new ParameterizedValue(pp.originX),
new ParameterizedValue(pp.originY),
new ParameterizedValue(pp.polar ? 1.0 : 0.0),
new ParameterizedValue(pp.polar ? pp.minR : pp.minX),
new ParameterizedValue(pp.polar ? pp.minA : pp.minY),
new ParameterizedValue(pp.polar ? pp.defR : pp.defX),
new ParameterizedValue(pp.polar ? pp.defA : pp.defY),
new ParameterizedValue(pp.polar ? pp.maxR : pp.maxX),
new ParameterizedValue(pp.polar ? pp.maxA : pp.maxY)
);
}
int nseg = stream.readInt();
while (nseg-- > 0) {
int t = stream.readShort();
int n = stream.readShort();
ParameterizedPoint[] c = new ParameterizedPoint[n];
for (int j = 0; j < n; j++) {
c[j] = (ParameterizedPoint)SerializationManager.readObject(stream);
}
switch (t) {
case 0x436C:
path.add('Z');
break;
case 0x4375:
path.add('C', c[0].x, c[0].y, c[1].x, c[1].y, c[2].x, c[2].y);
break;
case 0x4C69:
path.add('L', c[0].x, c[0].y);
break;
case 0x4D6F:
path.add('M', c[0].x, c[0].y);
break;
case 0x5175:
path.add('Q', c[0].x, c[0].y, c[1].x, c[1].y);
break;
case 0x4172:
path.add('G', c[0].x, c[0].y, c[1].x, c[1].y);
break;
case 0x6152: case 0x6352:
path.add(
'R', c[0].x, c[0].y, c[1].x, c[1].y,
new ParameterizedValue(0.0),
new ParameterizedValue(0.0)
);
break;
case 0x6144: case 0x6344:
path.add('R', c[0].x, c[0].y, c[1].x, c[1].y, c[2].x, c[2].y);
break;
case 0x6145: case 0x6345:
path.add(
'E', c[0].x, c[0].y, c[1].x, c[1].y,
new ParameterizedValue(0.0),
new ParameterizedValue(360.0),
new ParameterizedValue(0.0)
);
break;
case 0x6141:
path.add(
'E', c[0].x, c[0].y, c[1].x, c[1].y,
new ParameterizedValue("toDeg(" + c[2].x.source + ")"),
new ParameterizedValue("toDeg(" + c[2].y.source + ")"),
new ParameterizedValue(3.0)
);
break;
case 0x6341:
path.add(
'E', c[0].x, c[0].y, c[1].x, c[1].y,
new ParameterizedValue("toDeg(" + c[2].x.source + ")"),
new ParameterizedValue("toDeg(" + c[2].y.source + ")"),
new ParameterizedValue(4.0)
);
break;
}
}
return path;
}
} else if (type == TYPE_PARAMETERIZED_POINT) {
if (version != 1) throw new IOException("Invalid version number.");
int nx = stream.readInt();
int ny = stream.readInt();
if (nx < 0 || ny < 0) {
if (nx == -2) {
ParameterizedValue x = new ParameterizedValue(stream.readDouble());
ParameterizedValue y = new ParameterizedValue(stream.readDouble());
return new ParameterizedPoint(x, y);
} else {
ParameterizedValue x = new ParameterizedValue(stream.readUTF());
ParameterizedValue y = new ParameterizedValue(stream.readUTF());
return new ParameterizedPoint(x, y);
}
} else {
Expression xe = null;
Expression ye = null;
StringBuffer xs = new StringBuffer();
StringBuffer ys = new StringBuffer();
while (nx-- > 0) {
double v = stream.readDouble();
String k = stream.readUTF();
if (k.length() > 0) {
Expression ve = new Expression.Value(v);
Expression ke = new Expression.Binding(k);
Expression te = new Expression.Binary(Operator.mul, ve, ke);
xe = ((xe == null) ? te : new Expression.Binary(Operator.add, xe, te));
xs.append("+(" + ParameterizedValue.NUMBER_FORMAT.format(v) + "*(" + k + "))");
} else {
Expression te = new Expression.Value(v);
xe = ((xe == null) ? te : new Expression.Binary(Operator.add, xe, te));
xs.append("+(" + ParameterizedValue.NUMBER_FORMAT.format(v) + ")");
}
}
while (ny-- > 0) {
double v = stream.readDouble();
String k = stream.readUTF();
if (k.length() > 0) {
Expression ve = new Expression.Value(v);
Expression ke = new Expression.Binding(k);
Expression te = new Expression.Binary(Operator.mul, ve, ke);
ye = ((ye == null) ? te : new Expression.Binary(Operator.add, ye, te));
ys.append("+(" + ParameterizedValue.NUMBER_FORMAT.format(v) + "*(" + k + "))");
} else {
Expression te = new Expression.Value(v);
ye = ((ye == null) ? te : new Expression.Binary(Operator.add, ye, te));
ys.append("+(" + ParameterizedValue.NUMBER_FORMAT.format(v) + ")");
}
}
if (xe == null) {
xe = new Expression.Value(0);
xs.append("+0");
}
if (ye == null) {
ye = new Expression.Value(0);
ys.append("+0");
}
ParameterizedValue xp = new ParameterizedValue(xs.toString().substring(1), xe);
ParameterizedValue yp = new ParameterizedValue(ys.toString().substring(1), ye);
return new ParameterizedPoint(xp, yp);
}
} else if (type == TYPE_PARAMETERIZED_SHAPE_ARC) {
if (version != 1) throw new IOException("Invalid version number.");
ParameterizedValue cx = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue cy = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue rx = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue ry = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue start = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue extent = (ParameterizedValue)SerializationManager.readObject(stream);
ArcType arcType = ArcType.forAWTValue(stream.readInt());
return new ParameterizedShape.Arc(cx, cy, rx, ry, start, extent, arcType);
} else if (type == TYPE_PARAMETERIZED_SHAPE_CIRCLE) {
if (version != 1) throw new IOException("Invalid version number.");
ParameterizedValue cx = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue cy = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue r = (ParameterizedValue)SerializationManager.readObject(stream);
return new ParameterizedShape.Circle(cx, cy, r);
} else if (type == TYPE_PARAMETERIZED_SHAPE_ELLIPSE) {
if (version != 1) throw new IOException("Invalid version number.");
ParameterizedValue cx = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue cy = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue rx = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue ry = (ParameterizedValue)SerializationManager.readObject(stream);
return new ParameterizedShape.Ellipse(cx, cy, rx, ry);
} else if (type == TYPE_PARAMETERIZED_SHAPE_LINE) {
if (version != 1) throw new IOException("Invalid version number.");
ParameterizedValue x1 = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue y1 = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue x2 = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue y2 = (ParameterizedValue)SerializationManager.readObject(stream);
return new ParameterizedShape.Line(x1, y1, x2, y2);
} else if (type == TYPE_PARAMETERIZED_SHAPE_POLYGON) {
if (version != 1) throw new IOException("Invalid version number.");
int count = stream.readInt(); if (count < 0) count = 0;
ParameterizedValue[] points = new ParameterizedValue[count];
for (int i = 0; i < count; i++) {
points[i] = (ParameterizedValue)SerializationManager.readObject(stream);
}
return new ParameterizedShape.Polygon(points);
} else if (type == TYPE_PARAMETERIZED_SHAPE_POLYLINE) {
if (version != 1) throw new IOException("Invalid version number.");
int count = stream.readInt(); if (count < 0) count = 0;
ParameterizedValue[] points = new ParameterizedValue[count];
for (int i = 0; i < count; i++) {
points[i] = (ParameterizedValue)SerializationManager.readObject(stream);
}
return new ParameterizedShape.PolyLine(points);
} else if (type == TYPE_PARAMETERIZED_SHAPE_RECT) {
if (version != 1) throw new IOException("Invalid version number.");
ParameterizedValue x = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue y = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue width = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue height = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue rx = (ParameterizedValue)SerializationManager.readObject(stream);
ParameterizedValue ry = (ParameterizedValue)SerializationManager.readObject(stream);
return new ParameterizedShape.Rect(x, y, width, height, rx, ry);
} else if (type == TYPE_PARAMETERIZED_VALUE) {
if (version != 1) throw new IOException("Invalid version number.");
int n = stream.readInt();
if (n < 0) {
if (n == -2) {
return new ParameterizedValue(stream.readDouble());
} else {
return new ParameterizedValue(stream.readUTF());
}
} else {
Expression e = null;
StringBuffer s = new StringBuffer();
while (n-- > 0) {
double v = stream.readDouble();
String k = stream.readUTF();
if (k.length() > 0) {
Expression ve = new Expression.Value(v);
Expression ke = new Expression.Binding(k);
Expression te = new Expression.Binary(Operator.mul, ve, ke);
e = ((e == null) ? te : new Expression.Binary(Operator.add, e, te));
s.append("+(" + ParameterizedValue.NUMBER_FORMAT.format(v) + "*(" + k + "))");
} else {
Expression te = new Expression.Value(v);
e = ((e == null) ? te : new Expression.Binary(Operator.add, e, te));
s.append("+(" + ParameterizedValue.NUMBER_FORMAT.format(v) + ")");
}
}
if (e == null) {
e = new Expression.Value(0);
s.append("+0");
}
return new ParameterizedValue(s.toString().substring(1), e);
}
} else if (type == TYPE_PATH) {
if (version != 1) throw new IOException("Invalid version number.");
Path path = new Path();
int nc = stream.readInt();
for (int ci = 0; ci < nc; ci++) {
PathContour c = new PathContour();
int np = stream.readInt();
for (int pi = 0; pi < np; pi++) {
double px = stream.readDouble();
double py = stream.readDouble();
double x = stream.readDouble();
double y = stream.readDouble();
double nx = stream.readDouble();
double ny = stream.readDouble();
boolean pq = stream.readBoolean();
boolean al = stream.readBoolean();
boolean rl = stream.readBoolean();
boolean nq = stream.readBoolean();
PathPoint p = new PathPoint(x, y);
p.setPreviousCtrl(px, py);
p.setNextCtrl(nx, ny);
p.setPreviousQuadratic(pq);
p.setAngleLocked(al);
p.setRadiusLocked(rl);
p.setNextQuadratic(nq);
c.add(p);
}
c.setClosed(stream.readBoolean());
path.add(c);
}
return path;
} else if (type == TYPE_PATH_CONTOUR) {
if (version != 1) throw new IOException("Invalid version number.");
PathContour c = new PathContour();
int np = stream.readInt();
for (int pi = 0; pi < np; pi++) {
double px = stream.readDouble();
double py = stream.readDouble();
double x = stream.readDouble();
double y = stream.readDouble();
double nx = stream.readDouble();
double ny = stream.readDouble();
boolean pq = stream.readBoolean();
boolean al = stream.readBoolean();
boolean rl = stream.readBoolean();
boolean nq = stream.readBoolean();
PathPoint p = new PathPoint(x, y);
p.setPreviousCtrl(px, py);
p.setNextCtrl(nx, ny);
p.setPreviousQuadratic(pq);
p.setAngleLocked(al);
p.setRadiusLocked(rl);
p.setNextQuadratic(nq);
c.add(p);
}
c.setClosed(stream.readBoolean());
return c;
} else if (type == TYPE_PATH_POINT) {
if (version != 1) throw new IOException("Invalid version number.");
double px = stream.readDouble();
double py = stream.readDouble();
double x = stream.readDouble();
double y = stream.readDouble();
double nx = stream.readDouble();
double ny = stream.readDouble();
boolean pq = stream.readBoolean();
boolean al = stream.readBoolean();
boolean rl = stream.readBoolean();
boolean nq = stream.readBoolean();
PathPoint p = new PathPoint(x, y);
p.setPreviousCtrl(px, py);
p.setNextCtrl(nx, ny);
p.setPreviousQuadratic(pq);
p.setAngleLocked(al);
p.setRadiusLocked(rl);
p.setNextQuadratic(nq);
return p;
} else if (type == TYPE_POWERSHAPE) {
if (version < 1 || version > 2) throw new IOException("Invalid version number.");
if (version >= 2) {
int np = stream.readInt();
int nv = stream.readInt();
int ns = stream.readInt();
WindingRule winding = WindingRule.forAWTValue(stream.readInt());
String name = stream.readUTF();
PowerShape ps = new PowerShape(winding, name);
while (np-- > 0) {
ps.addParameter((Parameter)SerializationManager.readObject(stream));
}
while (nv-- > 0) {
double x = stream.readDouble();
double y = stream.readDouble();
String n = stream.readUTF();
ps.setParameterValue(n, x, y);
}
while (ns-- > 0) {
ps.addShape((ParameterizedShape)SerializationManager.readObject(stream));
}
return ps;
} else {
WindingRule winding = WindingRule.NON_ZERO;
List<Parameter> params = new ArrayList<Parameter>();
ParameterizedPath newPath = new ParameterizedPath();
ParameterizedPath oldPath = (ParameterizedPath)SerializationManager.readObject(stream);
for (int i = 0, n = oldPath.size(); i < n; i++) {
char inst = oldPath.getOpcode(i);
List<ParameterizedValue> args = oldPath.getOperands(i);
switch (inst) {
case 'W': case 'w':
double wdv = args.get(0).value(null);
int wiv = Math.abs((int)Math.round(wdv)) % 2;
winding = WindingRule.forAWTValue(wiv);
break;
case 'P': case 'p':
params.add(new Parameter(
args.get(0).source,
args.get(1).value(null),
args.get(2).value(null),
args.get(3).value(null) != 0,
args.get(4).value(null),
args.get(5).value(null),
args.get(4).value(null),
args.get(5).value(null),
args.get(6).value(null),
args.get(7).value(null),
args.get(6).value(null),
args.get(7).value(null),
args.get(8).value(null),
args.get(9).value(null),
args.get(8).value(null),
args.get(9).value(null)
));
break;
default:
newPath.add(inst, args);
break;
}
}
PowerShape ps = new PowerShape(winding, null);
for (Parameter param : params) ps.addParameter(param);
ps.addShape(newPath);
int npp = stream.readInt();
while (npp-- > 0) {
double x = stream.readDouble();
double y = stream.readDouble();
String n = stream.readUTF();
ps.setParameterValue(n, x, y);
}
return ps;
}
} else if (type == TYPE_POWERSHAPE_LIST) {
if (version != 1) throw new IOException("Invalid version number.");
int l = stream.readInt();
boolean n = stream.readBoolean();
PowerShape[] ps = new PowerShape[l];
for (int i = 0; i < l; i++) {
ps[i] = (PowerShape)SerializationManager.readObject(stream);
}
String name = n ? stream.readUTF() : null;
PowerShapeList list = new PowerShapeList(name);
for (PowerShape shape : ps) list.add(shape);
return list;
} else {
return null;
}
}
}