001: /*
002: * $RCSfile: ShapeState.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:55 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.rmi;
013:
014: import java.awt.RenderingHints;
015: import java.awt.Shape;
016: import java.awt.geom.Area;
017: import java.awt.geom.Arc2D;
018: import java.awt.geom.CubicCurve2D;
019: import java.awt.geom.Ellipse2D;
020: import java.awt.geom.GeneralPath;
021: import java.awt.geom.Line2D;
022: import java.awt.geom.QuadCurve2D;
023: import java.awt.geom.Rectangle2D;
024: import java.awt.geom.RoundRectangle2D;
025: import java.awt.geom.AffineTransform;
026: import java.awt.geom.PathIterator;
027: import java.io.IOException;
028: import java.io.ObjectInputStream;
029: import java.io.ObjectOutputStream;
030: import java.io.Serializable;
031: import javax.media.jai.remote.SerializableState;
032: import javax.media.jai.remote.SerializerFactory;
033:
034: /**
035: * This class is a serializable proxy for a Shape.
036: *
037: *
038: * @since 1.1
039: */
040: public class ShapeState extends SerializableStateImpl {
041: private final static int SHAPE_UNKNOWN = 0;
042: private final static int SHAPE_AREA = 1;
043: private final static int SHAPE_ARC_DOUBLE = 2;
044: private final static int SHAPE_ARC_FLOAT = 3;
045: private final static int SHAPE_CUBICCURVE_DOUBLE = 4;
046: private final static int SHAPE_CUBICCURVE_FLOAT = 5;
047: private final static int SHAPE_ELLIPSE_DOUBLE = 6;
048: private final static int SHAPE_ELLIPSE_FLOAT = 7;
049: private final static int SHAPE_GENERALPATH = 8;
050: private final static int SHAPE_LINE_DOUBLE = 9;
051: private final static int SHAPE_LINE_FLOAT = 10;
052: private final static int SHAPE_QUADCURVE_DOUBLE = 11;
053: private final static int SHAPE_QUADCURVE_FLOAT = 12;
054: private final static int SHAPE_ROUNDRECTANGLE_DOUBLE = 13;
055: private final static int SHAPE_ROUNDRECTANGLE_FLOAT = 14;
056: private final static int SHAPE_RECTANGLE_DOUBLE = 15;
057: private final static int SHAPE_RECTANGLE_FLOAT = 16;
058:
059: public static Class[] getSupportedClasses() {
060: return new Class[] { Shape.class };
061: }
062:
063: /**
064: * Constructs a <code>ShapeState</code> from a
065: * <code>Shape</code>.
066: *
067: * @param c The class of the object to be serialized.
068: * @param o The <code>Shape</code> to be serialized.
069: * @param h The <code>RenderingHints</code> (ignored).
070: */
071: public ShapeState(Class c, Object o, RenderingHints h) {
072: super (c, o, h);
073: }
074:
075: /**
076: * Serialize the <code>ShapeState</code>.
077: *
078: * @param out The <code>ObjectOutputStream</code>.
079: */
080: private void writeObject(ObjectOutputStream out) throws IOException {
081: boolean serializable = false;
082: Object object = theObject;
083:
084: // if the specific Shape is Serializable, then write itself;
085: // if the specific Shape has a proxy itself, use that proxy;
086: // for the regular Shapes, such as Arc, Ellipse and etc, write
087: // the parameters;
088: // for an Area, write the path and recover the Area;
089: // for the instance of GeneralPath or unknown Shape, write the path;
090: //
091: if (object instanceof Serializable)
092: serializable = true;
093:
094: // deal with Serializable Shape such as Polygon and Rectangle or
095: // the Shape has its own proxy.
096: //
097: out.writeBoolean(serializable);
098: if (serializable) {
099: out.writeObject(object);
100: return;
101: }
102:
103: Object dataArray = null;
104: Object otherData = null;
105: int type = SHAPE_UNKNOWN;
106:
107: // deal with the regular Shapes
108: if (theObject instanceof Area)
109: type = SHAPE_AREA;
110: else if (theObject instanceof Arc2D.Double) {
111: Arc2D.Double ad = (Arc2D.Double) theObject;
112: dataArray = new double[] { ad.x, ad.y, ad.width, ad.height,
113: ad.start, ad.extent };
114: type = SHAPE_ARC_DOUBLE;
115: otherData = new Integer(ad.getArcType());
116: } else if (theObject instanceof Arc2D.Float) {
117: Arc2D.Float af = (Arc2D.Float) theObject;
118: dataArray = new float[] { af.x, af.y, af.width, af.height,
119: af.start, af.extent };
120: type = SHAPE_ARC_FLOAT;
121: otherData = new Integer(af.getArcType());
122: } else if (theObject instanceof CubicCurve2D.Double) {
123: CubicCurve2D.Double cd = (CubicCurve2D.Double) theObject;
124: dataArray = new double[] { cd.x1, cd.y1, cd.ctrlx1,
125: cd.ctrly1, cd.ctrlx2, cd.ctrly2, cd.x2, cd.y2 };
126: type = SHAPE_CUBICCURVE_DOUBLE;
127: } else if (theObject instanceof CubicCurve2D.Float) {
128: CubicCurve2D.Float cf = (CubicCurve2D.Float) theObject;
129: dataArray = new float[] { cf.x1, cf.y1, cf.ctrlx1,
130: cf.ctrly1, cf.ctrlx2, cf.ctrly2, cf.x2, cf.y2 };
131: type = SHAPE_CUBICCURVE_FLOAT;
132: } else if (theObject instanceof Ellipse2D.Double) {
133: Ellipse2D.Double ed = (Ellipse2D.Double) theObject;
134: dataArray = new double[] { ed.x, ed.y, ed.width, ed.height };
135: type = SHAPE_ELLIPSE_DOUBLE;
136: } else if (theObject instanceof Ellipse2D.Float) {
137: Ellipse2D.Float ef = (Ellipse2D.Float) theObject;
138: dataArray = new float[] { ef.x, ef.y, ef.width, ef.height };
139: type = SHAPE_ELLIPSE_FLOAT;
140: } else if (theObject instanceof GeneralPath)
141: type = SHAPE_GENERALPATH;
142: else if (theObject instanceof Line2D.Double) {
143: Line2D.Double ld = (Line2D.Double) theObject;
144: dataArray = new double[] { ld.x1, ld.y1, ld.x2, ld.y2 };
145: type = SHAPE_LINE_DOUBLE;
146: } else if (theObject instanceof Line2D.Float) {
147: Line2D.Float lf = (Line2D.Float) theObject;
148: dataArray = new float[] { lf.x1, lf.y1, lf.x2, lf.y2 };
149: type = SHAPE_LINE_FLOAT;
150: } else if (theObject instanceof QuadCurve2D.Double) {
151: QuadCurve2D.Double qd = (QuadCurve2D.Double) theObject;
152: dataArray = new double[] { qd.x1, qd.y1, qd.ctrlx,
153: qd.ctrly, qd.x2, qd.y2 };
154: type = SHAPE_QUADCURVE_DOUBLE;
155: } else if (theObject instanceof QuadCurve2D.Float) {
156: QuadCurve2D.Float qf = (QuadCurve2D.Float) theObject;
157: dataArray = new float[] { qf.x1, qf.y1, qf.ctrlx, qf.ctrly,
158: qf.x2, qf.y2 };
159: type = SHAPE_QUADCURVE_FLOAT;
160: } else if (theObject instanceof RoundRectangle2D.Double) {
161: RoundRectangle2D.Double rrd = (RoundRectangle2D.Double) theObject;
162: dataArray = new double[] { rrd.x, rrd.y, rrd.width,
163: rrd.height, rrd.arcwidth, rrd.archeight };
164: type = SHAPE_ROUNDRECTANGLE_DOUBLE;
165: } else if (theObject instanceof RoundRectangle2D.Float) {
166: RoundRectangle2D.Float rrf = (RoundRectangle2D.Float) theObject;
167: dataArray = new float[] { rrf.x, rrf.y, rrf.width,
168: rrf.height, rrf.arcwidth, rrf.archeight };
169: type = SHAPE_ROUNDRECTANGLE_FLOAT;
170: } else if (theObject instanceof Rectangle2D.Double) {
171: Rectangle2D.Double rd = (Rectangle2D.Double) theObject;
172: dataArray = new double[] { rd.x, rd.y, rd.width, rd.height };
173: type = SHAPE_RECTANGLE_DOUBLE;
174: } else if (theObject instanceof Rectangle2D.Float) {
175: Rectangle2D.Float rf = (Rectangle2D.Float) theObject;
176: dataArray = new float[] { rf.x, rf.y, rf.width, rf.height };
177: type = SHAPE_RECTANGLE_FLOAT;
178: }
179: // write Shape belonging to : GenrealPath, Area and unknown classes
180: out.writeInt(type);
181: if (dataArray != null) {
182: out.writeObject(dataArray);
183: if (otherData != null)
184: out.writeObject(otherData);
185: return;
186: }
187:
188: PathIterator pathIterator = ((Shape) theObject)
189: .getPathIterator(null);
190:
191: // obtain and write the winding rule
192: int rule = pathIterator.getWindingRule();
193: out.writeInt(rule);
194:
195: float[] coordinates = new float[6];
196:
197: // iteratively write isDone, segment type and segment coordinates
198: boolean isDone = pathIterator.isDone();
199: while (!isDone) {
200: int segmentType = pathIterator.currentSegment(coordinates);
201: out.writeBoolean(isDone);
202: out.writeInt(segmentType);
203: for (int i = 0; i < 6; i++)
204: out.writeFloat(coordinates[i]);
205: pathIterator.next();
206: isDone = pathIterator.isDone();
207: }
208: out.writeBoolean(isDone);
209: }
210:
211: /**
212: * Deserialize the <code>ShapeState</code>.
213: *
214: * @param out The <code>ObjectInputStream</code>.
215: */
216: private void readObject(ObjectInputStream in) throws IOException,
217: ClassNotFoundException {
218:
219: boolean serializable = in.readBoolean();
220:
221: // if Serializable or has a specific proxy
222: if (serializable) {
223: theObject = in.readObject();
224: return;
225: }
226:
227: // read the type of the wrapped Shape
228: int type = in.readInt();
229:
230: //for regular shapes, read the parameters and recover it
231: switch (type) {
232: case SHAPE_ARC_DOUBLE: {
233: double[] data = (double[]) in.readObject();
234: int arcType = ((Integer) in.readObject()).intValue();
235: theObject = new Arc2D.Double(data[0], data[1], data[2],
236: data[3], data[4], data[5], arcType);
237: return;
238: }
239: case SHAPE_ARC_FLOAT: {
240: float[] data = (float[]) in.readObject();
241: int arcType = ((Integer) in.readObject()).intValue();
242: theObject = new Arc2D.Float(data[0], data[1], data[2],
243: data[3], data[4], data[5], arcType);
244: return;
245: }
246: case SHAPE_CUBICCURVE_DOUBLE: {
247: double[] data = (double[]) in.readObject();
248: theObject = new CubicCurve2D.Double(data[0], data[1],
249: data[2], data[3], data[4], data[5], data[6],
250: data[7]);
251: return;
252: }
253: case SHAPE_CUBICCURVE_FLOAT: {
254: float[] data = (float[]) in.readObject();
255: theObject = new CubicCurve2D.Float(data[0], data[1],
256: data[2], data[3], data[4], data[5], data[6],
257: data[7]);
258: return;
259: }
260: case SHAPE_ELLIPSE_DOUBLE: {
261: double[] data = (double[]) in.readObject();
262: theObject = new Ellipse2D.Double(data[0], data[1], data[2],
263: data[3]);
264: return;
265: }
266: case SHAPE_ELLIPSE_FLOAT: {
267: float[] data = (float[]) in.readObject();
268: theObject = new Ellipse2D.Float(data[0], data[1], data[2],
269: data[3]);
270: return;
271: }
272:
273: case SHAPE_LINE_DOUBLE: {
274: double[] data = (double[]) in.readObject();
275: theObject = new Line2D.Double(data[0], data[1], data[2],
276: data[3]);
277: return;
278: }
279: case SHAPE_LINE_FLOAT: {
280: float[] data = (float[]) in.readObject();
281: theObject = new Line2D.Float(data[0], data[1], data[2],
282: data[3]);
283: return;
284: }
285: case SHAPE_QUADCURVE_DOUBLE: {
286: double[] data = (double[]) in.readObject();
287: theObject = new QuadCurve2D.Double(data[0], data[1],
288: data[2], data[3], data[4], data[5]);
289: return;
290: }
291: case SHAPE_QUADCURVE_FLOAT: {
292: float[] data = (float[]) in.readObject();
293: theObject = new QuadCurve2D.Float(data[0], data[1],
294: data[2], data[3], data[4], data[5]);
295:
296: return;
297: }
298: case SHAPE_ROUNDRECTANGLE_DOUBLE: {
299: double[] data = (double[]) in.readObject();
300: theObject = new RoundRectangle2D.Double(data[0], data[1],
301: data[2], data[3], data[4], data[5]);
302: return;
303: }
304: case SHAPE_ROUNDRECTANGLE_FLOAT: {
305: float[] data = (float[]) in.readObject();
306: theObject = new RoundRectangle2D.Float(data[0], data[1],
307: data[2], data[3], data[4], data[5]);
308: return;
309: }
310: case SHAPE_RECTANGLE_DOUBLE: {
311: double[] data = (double[]) in.readObject();
312: theObject = new Rectangle2D.Double(data[0], data[1],
313: data[2], data[3]);
314: return;
315: }
316: case SHAPE_RECTANGLE_FLOAT: {
317: float[] data = (float[]) in.readObject();
318: theObject = new Rectangle2D.Float(data[0], data[1],
319: data[2], data[3]);
320: return;
321: }
322: }
323:
324: //read the winding rule
325: int rule = in.readInt();
326:
327: GeneralPath path = new GeneralPath(rule);
328: float[] coordinates = new float[6];
329:
330: //read the path
331: while (!in.readBoolean()) {
332: int segmentType = in.readInt();
333: for (int i = 0; i < 6; i++)
334: coordinates[i] = in.readFloat();
335:
336: switch (segmentType) {
337: case PathIterator.SEG_MOVETO:
338: path.moveTo(coordinates[0], coordinates[1]);
339: break;
340:
341: case PathIterator.SEG_LINETO:
342: path.lineTo(coordinates[0], coordinates[1]);
343: break;
344:
345: case PathIterator.SEG_QUADTO:
346: path.quadTo(coordinates[0], coordinates[1],
347: coordinates[2], coordinates[3]);
348: break;
349:
350: case PathIterator.SEG_CUBICTO:
351: path.curveTo(coordinates[0], coordinates[1],
352: coordinates[2], coordinates[3], coordinates[4],
353: coordinates[5]);
354: break;
355:
356: case PathIterator.SEG_CLOSE:
357: path.closePath();
358: break;
359: default:
360: break;
361: }
362: }
363:
364: //recover Area instance
365: switch (type) {
366: case SHAPE_AREA:
367: theObject = new Area(path);
368: break;
369: default:
370: theObject = path;
371: break;
372: }
373: }
374: }
|