// Copyright 2001, FreeHEP.
package org.freehep.graphicsio.cgm;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
import org.freehep.util.io.IndentPrintWriter;
import org.freehep.util.io.Tag;
import org.freehep.util.io.TaggedOutput;
/**
* CGM Clear Text Writer. Tags written with this Writer will produce a clear
* text CGM file. The class also holds the state for the various precisions,
* defaults, etc...
*
* @author Mark Donszelmann
* @author Charles Loomis
* @version $Id: freehep-graphicsio-cgm/src/main/java/org/freehep/graphicsio/cgm/CGMWriter.java 83dd558e0284 2005/12/11 22:59:37 duns $
*/
public class CGMWriter extends FilterWriter implements TaggedOutput {
private int version;
private boolean direct = true;
private int colorIndexPrecision = 8;
private int directColorPrecision = 8;
private int integerPrecision = 16;
private boolean fixedPrecision = true;
private boolean doublePrecision = false;
private boolean vdcReal = false;
private boolean vdcFixedPrecision = true;
private boolean vdcDoublePrecision = false;
private int vdcIntegerPrecision = 16;
private int namePrecision = 16;
private int lineWidthSpecificationMode = LineWidthSpecificationMode.ABSOLUTE;
private int markerSizeSpecificationMode = MarkerSizeSpecificationMode.ABSOLUTE;
private int edgeWidthSpecificationMode = EdgeWidthSpecificationMode.ABSOLUTE;
private int interiorStyleSpecificationMode = InteriorStyleSpecificationMode.ABSOLUTE;
/**
* Constructs a Clear Text CGM writer of a specified version.
*
* @param writer the underlying writer
* @param version the requested cgm version
*/
public CGMWriter(Writer writer, int version) throws IOException {
super(new IndentPrintWriter(writer));
this.version = version;
}
/**
* Constructs a Clear Text CGM Writer of version 1.
*
* @param writer the underlying writer.
*/
public CGMWriter(Writer writer) throws IOException {
this(writer, 1);
}
void setColorMode(boolean direct) {
this.direct = direct;
}
void setColorIndexPrecision(int precision) {
colorIndexPrecision = precision;
}
void setDirectColorPrecision(int precision) {
directColorPrecision = precision;
}
void setIntegerPrecision(int precision) {
integerPrecision = precision;
}
void setRealPrecision(boolean fixedPrecision, boolean doublePrecision) {
this.fixedPrecision = fixedPrecision;
this.doublePrecision = doublePrecision;
}
void setVDCReal(boolean real) {
vdcReal = real;
}
void setVDCIntegerPrecision(int precision) {
vdcIntegerPrecision = precision;
}
void setVDCRealPrecision(boolean fixedPrecision, boolean doublePrecision) {
this.vdcFixedPrecision = fixedPrecision;
this.vdcDoublePrecision = doublePrecision;
}
void setNamePrecision(int precision) {
namePrecision = precision;
}
void setLineWidthSpecificationMode(int mode) {
lineWidthSpecificationMode = mode;
}
int getLineWidthSpecificationMode() {
return lineWidthSpecificationMode;
}
void setMarkerSizeSpecificationMode(int mode) {
markerSizeSpecificationMode = mode;
}
int getMarkerSizeSpecificationMode() {
return markerSizeSpecificationMode;
}
void setEdgeWidthSpecificationMode(int mode) {
edgeWidthSpecificationMode = mode;
}
int getEdgeWidthSpecificationMode() {
return edgeWidthSpecificationMode;
}
void setInteriorStyleSpecificationMode(int mode) {
interiorStyleSpecificationMode = mode;
}
int getInteriorStyleSpecificationMode() {
return interiorStyleSpecificationMode;
}
/**
* Write a Fixed Point value (FX)
*
* @param d value to the written
*/
public void writeFixedPoint(double d) throws IOException {
boolean negative = d < 0;
d = Math.abs(d);
int whole = (int) Math.floor(d);
int frac = (int) Math.floor((d - whole) * 10000);
if (negative)
print("-");
print(whole);
print(".");
print(frac);
}
/**
* Writes a Floating Point value (FP)
*
* @param d value to be written
*/
public void writeFloatingPoint(double d) throws IOException {
if (doublePrecision) {
// FIXME: ignored number of digits
print(d);
} else {
// FIXME: ignored number of digits
print((float) d);
}
}
/**
* Writes a Color Index (CI)
*
* @param i index to be written
*/
public void writeColorIndex(int i) throws IOException {
switch (colorIndexPrecision) {
case 8:
print(Math.max(0, Math.min(255, i)));
break;
case 16:
print(Math.max(0, Math.min(65535, i)));
break;
default:
case 24: // FIXME
case 32:
print(i);
break;
}
}
/**
* Writes a Color Component (CCO)
*
* @param c color component to be written
*/
public void writeColorComponent(int c) throws IOException {
switch (directColorPrecision) {
default:
case 8:
print(Math.max(0, Math.min(255, c)));
break;
case 16:
print(Math.max(0, Math.min(65535, c)));
break;
case 24: // FIXME
case 32:
print(c);
break;
}
}
/**
* Writes a Color Direct (CD)
*
* @param c color to be written
*/
public void writeColorDirect(Color c) throws IOException {
writeColorComponent(c.getRed());
print(", ");
writeColorComponent(c.getGreen());
print(", ");
writeColorComponent(c.getBlue());
}
/**
* Writes an Integer (I)
*
* @param i integer to be written
*/
public void writeInteger(int i) throws IOException {
switch (integerPrecision) {
case 8:
print((byte) i);
break;
default:
case 16:
print((short) i);
break;
case 24: // FIXME
case 32:
print(i);
break;
}
}
/**
* Writes a Real (R)
*
* @param r value to be written
*/
public void writeReal(double r) throws IOException {
if (fixedPrecision) {
writeFixedPoint(r);
} else {
writeFloatingPoint(r);
}
}
/**
* Writes a String or String Fixed (S, SF)
*
* @param s string to be written
*/
public void writeString(String s) throws IOException {
StringBuffer b = new StringBuffer();
b.append('"');
for (int i = 0; i < s.length(); i++) {
b.append(s.charAt(i));
if (s.charAt(i) == '"') {
b.append('"');
}
}
b.append('"');
print(b.toString());
}
/**
* Writes a chunk of Data (D)
*
* @param data data to be written
*/
public void writeData(byte[] data) throws IOException {
// FIXME: good unless strings will do encoding
writeString(new String(data));
}
/**
* Writes a Virtual Display Coordinate (VDC)
*
* @param d VDC to be written
*/
public void writeVDC(double d) throws IOException {
if (vdcReal) {
if (vdcFixedPrecision) {
writeFixedPoint(d);
} else {
if (vdcDoublePrecision) {
print(d);
} else {
print((float) d);
}
}
} else {
switch (vdcIntegerPrecision) {
default:
case 16:
print((short) d);
break;
case 24: // FIXME
case 32:
print(d);
break;
}
}
}
/**
* Writes a Point (P)
*
* @param p value to be written
*/
public void writePoint(Point2D p) throws IOException {
print("(");
writeVDC(p.getX());
print(", ");
writeVDC(p.getY());
print(")");
}
/**
* Writes a Color (CO)
*
* @param c color to be written
*/
public void writeColor(Color c) throws IOException {
if (direct) {
writeColorDirect(c);
} else {
// FIXME: we should look up the color
writeColorIndex((c.getRed() << 16) + (c.getGreen() << 8)
+ c.getBlue());
}
}
/**
* Writes a Name (N)
*
* @param name name to be written
*/
public void writeName(int name) throws IOException {
switch (namePrecision) {
case 8:
print(Math.max(0, Math.min(255, name)));
break;
default:
case 16:
print(Math.max(0, Math.min(65535, name)));
break;
case 24: // FIXME
case 32:
print(name);
break;
}
}
/**
* Writes a Tag and a Terminator (;)
*
* @param tag tag to be written
*/
public void writeTag(Tag tag) throws IOException {
CGMTag cgm = (CGMTag) tag;
cgm.write(cgm.getTag(), this);
println(";");
}
/**
* @return the version of this CGM Writer
*/
public int getVersion() {
return version;
}
// Delegations to IndentPrintWriter to avoid "strange" compilation error in jdk 1.5
public void indent() {
((IndentPrintWriter)out).indent();
}
public void outdent() {
((IndentPrintWriter)out).outdent();
}
public void print(byte b) {
((IndentPrintWriter)out).print(b);
}
public void print(double d) {
((IndentPrintWriter)out).print(d);
}
public void print(String s) {
((IndentPrintWriter)out).print(s);
}
public void println(String s) {
((IndentPrintWriter)out).println(s);
}
public void println() {
((IndentPrintWriter)out).println();
}
}