|
| AJR Format
|
Jpgfdraw's native file format is a binary format written in the big-endian fashion. Since all binary data files are platform independent, there should be no problems transferring the files between processorsA.1. Integers are stored as 32-bit integers, single precision numbers are stored as 32-bit floats, double precision numbers are stored as 64-bit doubles and characters are stored as 16-bit Unicode characters. (For more details see [2, Chapter 12] or http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataInput.html)
The current JDR file format version is 1.6.
If you use the uk.ac.uea.cmp.nlct.jdr package, you can load and save a
file using the JDR.load()
and JDR.save() methods, otherwise the file
format is as follows:
DataInputStream din = new DataInputStream(new FileInputStream(filename));or to write a data stream:
DataOutputStream dout = new DataOutputStream(new FileOutputStream(filename));
dout.writeChars("JDR");
To read:
char[] str = new char[3];
for (int i = 0; i < 3; i++) str[i] = din.readChar();
if (!(new String(str)).equals("JDR"))
{
// not a JDR file error code
}
dout.writeInt(fileVersion.length()) dout.writeChars(fileVersion)To read:
int n = din.readInt(); char[] version = new char[n]; for (int i = 0; i < n; i++) version[i] = din.readChar();
| JDR1.3 onwards |
|---|
In version 1.3 onwards, this value is a byte, and may take one of three
values: 0 (no settings), 1 (all settings) or 2 (paper size only).
To omit the settings information:
dout.writeByte((byte)0);To save all the settings: To save only the paper size: To read: |
| JDR1.3 onwards |
| JDR1.0-1.2 |
|---|
In versions prior to 1.3, this value is a boolean value.
To save the settings:
To omit the settings information:
dout.writeBoolean(false);To read: |
| JDR1.0-1.2 |
dout.writeBoolean(grid);To read:
boolean grid = din.readBoolean();
dout.writeBoolean(gridLock);To read:
boolean gridLock = din.readBoolean();
dout.writeBoolean(showRulers);To read:
boolean showRulers = din.readBoolean();
dout.writeInt(tool);To read:
int tool = din.readInt();
if (tool < 0 || tool > 7)
{
// insert invalid tool id error
}
dout.writeInt(normalSize);To read:
int normalSize = din.readInt();
| JDR1.6 onwards |
|---|
An 8-bit byte representing the grid style ID. This may be:
|
| JDR1.6 onwards |
| JDR1.0-1.2 |
|---|
To write:
dout.writeByte(paperSize);
if (paperSize == 18) // user defined paper size
{
dout.writeDouble(paperWidth);
dout.writeDouble(paperHeight);
dout.writeBoolean(isPortrait);
}
To read:
byte paperSize = din.readByte();
if (paperSize < 0 || paperSize > 18)
{
// insert invalid paper size id code
}
else if (paperSize == 18) // user defined paper size
{
double paperWidth = din.readDouble();
double paperHeight = din.readDouble();
boolean isPortrait = din.readBoolean();
}
|
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
To write:
dout.writeByte(paperSize);
if (paperSize == 18) // user defined paper size
{
dout.writeDouble(paperWidth);
dout.writeDouble(paperHeight);
}
To read:
byte paperSize = din.readByte();
if (paperSize < 0 || paperSize > 72)
{
// insert invalid paper size id code
}
else if (paperSize == 18) // user defined paper size
{
double paperWidth = din.readDouble();
double paperHeight = din.readDouble();
}
|
| JDR1.3 onwards |
| ID | Paper Size | ID | Paper Size |
|---|---|---|---|
| 0 | A0 (portrait) | 9 | A0 (landscape) |
| 1 | A1 (portrait) | 10 | A1 (landscape) |
| 2 | A2 (portrait) | 11 | A2 (landscape) |
| 3 | A3 (portrait) | 12 | A3 (landscape) |
| 4 | A4 (portrait) | 13 | A4 (landscape) |
| 5 | A5 (portrait) | 14 | A5 (landscape) |
| 6 | letter (portrait) | 15 | letter (landscape) |
| 7 | legal (portrait) | 16 | legal (landscape) |
| 8 | executive (portrait) | 17 | executive (landscape) |
| 18 | user defined |
| ID | Paper Size | ID | Paper Size |
|---|---|---|---|
| 19 | A6 (portrait) | 46 | A6 (landscape) |
| 20 | A7 (portrait) | 47 | A7 (landscape) |
| 21 | A8 (portrait) | 48 | A8 (landscape) |
| 22 | A9 (portrait) | 49 | A9 (landscape) |
| 23 | A10 (portrait) | 50 | A10 (landscape) |
| 24 | B0 (portrait) | 51 | B0 (landscape) |
| 25 | B1 (portrait) | 52 | B1 (landscape) |
| 26 | B2 (portrait) | 53 | B2 (landscape) |
| 27 | B3 (portrait) | 54 | B3 (landscape) |
| 28 | B4 (portrait) | 55 | B4 (landscape) |
| 29 | B5 (portrait) | 56 | B5 (landscape) |
| 30 | B6 (portrait) | 57 | B6 (landscape) |
| 31 | B7 (portrait) | 58 | B7 (landscape) |
| 32 | B8 (portrait) | 59 | B8 (landscape) |
| 33 | B9 (portrait) | 60 | B9 (landscape) |
| 34 | B10 (portrait) | 61 | B10 (landscape) |
| 35 | C0 (portrait) | 62 | C0 (landscape) |
| 36 | C1 (portrait) | 63 | C1 (landscape) |
| 37 | C2 (portrait) | 64 | C2 (landscape) |
| 38 | C3 (portrait) | 65 | C3 (landscape) |
| 39 | C4 (portrait) | 66 | C4 (landscape) |
| 40 | C5 (portrait) | 67 | C5 (landscape) |
| 41 | C6 (portrait) | 68 | C6 (landscape) |
| 42 | C7 (portrait) | 69 | C7 (landscape) |
| 43 | C8 (portrait) | 70 | C8 (landscape) |
| 44 | C9 (portrait) | 71 | C9 (landscape) |
| 45 | C10 (portrait) | 72 | C10 (landscape) |
Each has the following format:
| JDR1.0 & 1.1 |
|---|
| <id-char><object-specs><fflag>[<flowframe-specs>] |
| JDR1.0 & 1.1 |
| JDR1.2 onwards |
|---|
| <id-char><object-specs><fflag>[<flowframe-specs>]<description-specs> |
| JDR1.2 onwards |
| JDR1.0-1.4 |
|---|
|
| JDR1.0-1.4 |
| JDR1.5 |
|---|
As versions 1.0-1.4. Additionally:
|
| JDR1.5 |
| JDR1.5 |
|---|
As versions 1.5. Additionally:
|
| JDR1.5 |
The object specifications <object-specs> vary according to the object type and are described below. <fflag> is a boolean variable indicating whether or not this object has flowframe data associated with it. If true, then the flowframe specifications <flowframe-specs> should follow (see below), otherwise <flowframe-specs> should be omitted. Note that JDR version 1.2 and above contains <description-specs>, which was omitted in earlier versions. To write:
To read:
To read:
| JDR1.0-1.2 |
|---|
| <line color><fill color><line style>O|C<n><segment data>+ |
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
| <line color><fill color><line style>O|C<n><start point><segment data>+ |
| JDR1.3 onwards |
| JDR1.0-1.2 |
|---|
|
To write:
// save line color data (see below)
To read:
// save fill color data (see below) // save line style data (see below) // boolean closed indicates whether or not the path // is closed dout.writeChar(closed ? 'C' : 'O'); // int n is the number of segments in the path dout.writeInt(n); for (int i = 0; i < n; i++) { // save data for segment i (see below) }
// read line color data (see below)
// read fill color data (see below) // read line style data (see below) char c = din.readChar(); if (c == 'O') { // make it an open path } else if (c == 'C') { // make it a closed path } else { // insert invalid identifier code } int n = din.readInt(); for (int i = 0; i < n; i++) { // read data for segment i (see below) } |
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
|
JDR v1.3 onwards requires that the starting point <start point>
follows the number of segments (<n>). The starting point
is stored as two double precision numbers.
To write:
// save line color data (see below)
To read:
// save fill color data (see below) // save line style data (see below) // boolean closed indicates whether or not the path // is closed dout.writeChar(closed ? 'C' : 'O'); // int n is the number of segments in the path dout.writeInt(n); // double x, y is the starting position of the path dout.writeDouble(x); dout.writeDouble(y); for (int i = 0; i < n; i++) { // save data for segment i (see below) }
// read line color data (see below)
// read fill color data (see below) // read line style data (see below) char c = din.readChar(); if (c == 'O') { // make it an open path } else if (c == 'C') { // make it a closed path } else { // insert invalid identifier code } int n = din.readInt(); double x = din.readDouble(); double y = din.readDouble(); for (int i = 0; i < n; i++) { // read data for segment i (see below) } |
| JDR1.3 onwards |
To write
To read:
dout.writeFloat(red); dout.writeFloat(green); dout.writeFloat(blue); dout.writeFloat(alpha);To read:
float red = din.readFloat(); // check lies in range [0,1] float green = din.readFloat(); // check lies in range [0,1] float blue = din.readFloat(); // check lies in range [0,1] float alpha = din.readFloat(); // check lies in range [0,1]
dout.writeFloat(cyan); dout.writeFloat(magenta); dout.writeFloat(yellow); dout.writeFloat(black); dout.writeFloat(alpha);To read:
float cyan = din.readFloat(); // check lies in range [0,1] float magenta = din.readFloat(); // check lies in range [0,1] float yellow = din.readFloat(); // check lies in range [0,1] float black = din.readFloat(); // check lies in range [0,1] float alpha = din.readFloat(); // check lies in range [0,1]
dout.writeFloat(hue); dout.writeFloat(saturation); dout.writeFloat(brightness); dout.writeFloat(alpha);To read:
float hue = din.readFloat(); // check lies in range [0,360) float saturation = din.readFloat(); // check lies in range [0,1] float brightness = din.readFloat(); // check lies in range [0,1] float alpha = din.readFloat(); // check lies in range [0,1]
dout.writeFloat(grey); dout.writeFloat(alpha);To read:
float grey = din.readFloat(); // check lies in range [0,1] float alpha = din.readFloat(); // check lies in range [0,1]
To read:
To read:
| JDR1.0 |
|---|
| <linewidth><dash><cap><join>[<mitre-limit>]<winding><start arrow><end arrow> |
| JDR1.0 |
| JDR1.1 and above |
|---|
| <linewidth><dash><cap><join>[<mitre-limit>]<winding><start arrow><mid marker><end arrow> |
| JDR1.1 and above |
dout.writeFloat(linewidth);To read:
float linewidth = din.readFloat(); // check linewidth isn't negative
dout.writeInt(n);
for (int i = 0; i < n; i++)
{
dout.writeFloat(pattern[i]);
}
if (n > 0) dout.writeFloat(offset);
To read:
int n = din.readInt();
if (n < 0)
{
// insert invalid pattern length code
}
else if (n > 0)
{
float[] pattern = new float[n];
for (int i = 0; i < n; i++)
{
pattern[i] = din.readFloat();
}
float offset = din.readFloat();
}
else
{
// solid line
}
dout.writeByte(cap);To read:
byte cap = din.readByte(); // check cap is in the range [0,2]
dout.writeByte(join);To read:
byte join = din.readByte(); // check join is in the range [0,2]
if (join == 0)
{
dout.writeFloat(mitreLimit);
}
To read:
if (join == 0)
{
float mitreLimit = din.readFloat();
}
dout.writeByte(windingRule);To read:
byte windingRule = din.readByte(); // check it's either 0 or 1
| JDR1.0 |
|---|
|
<id>[<size><is double><is reversed>]
where <id> is an 8-bit byte identifying the arrow type. This may be one of: 0 (none), 1 (pointed), 2 (triangle), 3 (circle), 4 (diamond), 5 (square), 6 (bar) or 7 (single). <size> is 32-bit float representing the arrow size. (Some arrows only have a fixed size, but a size must still be present.) <is double> is a boolean value indicating whether the arrow head is a double arrow (<true>) or a single arrow (<false>). <is reversed> is a boolean value indicating whether the arrow head has been reversed. The values <size><is double><is reversed> are omitted if <id> equals 0 (no arrow head). To write:
dout.writeByte(arrowType);
if (arrowType != 0)
{
dout.writeFloat(arrowSize);
dout.writeBoolean(arrowDouble);
dout.writeBoolean(arrowReversed);
}
To read:
byte arrowType = din.readByte();
// omitted code to check arrowType is in range [0,7]
if (arrowType != 0)
{
float arrowSize = din.readFloat();
boolean arrowDouble = din.readBoolean();
boolean arrowReversed = din.readBoolean();
}
|
| JDR1.0 |
| JDR1.1-1.3 | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
<id>[<marker data>]
where <id> is an 8-bit byte identifying the marker type. If <id> is 0, then <marker data> should be omitted, otherwise it should be present. Valid <id> values are listed in Table A.5. To write: dout.writeByte(markerType);To read:
byte markerType = din.readByte();
// omitted code to check markerType has valid value
if (markerType != 0)
{
// read in marker data
}
The <marker data> is stored as follows:
| ||||||||||||||||||||||||||||||||||||||||||||
| JDR1.1-1.3 |
| JDR1.4 onwards | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
<id> [<marker data> ] where <id> is an 8-bit byte identifying the marker type. If <id> is 0, then <marker data> should be omitted, otherwise it should be present. Valid <id> values are listed in Table A.5 and Table A.6. Additional markers listed in Table A.7 are also available for version 1.6 onwards. To write: dout.writeByte(markerType);To read:
byte markerType = din.readByte();
// omitted code to check markerType has valid value
if (markerType != 0)
{
// read in marker data
}
The <marker data> is stored as follows:
if (overlay)
{
dout.writeBoolean(userOffsetFlag);
if (userOffsetFlag)
{
dout.writeFloat(userOffset);
}
dout.writeBoolean(repeatOffsetFlag);
if (repeatOffsetFlag)
{
dout.writeFloat(repeatOffset);
}
}
To read:
if (overlay)
{
boolean userOffsetFlag = din.readBoolean();
if (userOffsetFlag)
{
float userOffset = din.readFloat();
}
boolean repeatOffsetFlag = din.readBoolean();
if (repeatOffsetFlag)
{
float repeatOffset = din.readFloat();
}
}
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| JDR1.4 onwards |
To read:
| JDR1.0-1.2 |
|---|
| <c0x><c0y><c1x><c1y><c2x><c2y><c3x><c3y> |
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
| <c1x><c1y><c2x><c2y><c3x><c3y> |
| JDR1.3 onwards |
| JDR1.0-1.2 |
|---|
for (int i = 0; i < 4; i++)
{
dout.writeDouble(x[i]);
dout.writeDouble(y[i]);
}
To read:
double[] x = new double[4];
double[] y = new double[4];
for (int i = 0; i < 4; i++)
{
x[i] = din.readDouble();
y[i] = din.readDouble();
}
|
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
for (int i = 0; i < 3; i++)
{
dout.writeDouble(x[i]);
dout.writeDouble(y[i]);
}
To read:
double[] x = new double[3];
double[] y = new double[3];
for (int i = 0; i < 3; i++)
{
x[i] = din.readDouble();
y[i] = din.readDouble();
}
|
| JDR1.3 onwards |
| JDR1.0-1.2 |
|---|
| <x0><y0><x1><y1> |
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
| <x1><y1> |
| JDR1.3 onwards |
| JDR1.0-1.2 |
|---|
To write:
for (int i = 0; i < 2; i++)
{
dout.writeDouble(x[i]);
dout.writeDouble(y[i]);
}
To read:
double[] x = new double[2];
double[] y = new double[2];
for (int i = 0; i < 2; i++)
{
x[i] = din.readDouble();
y[i] = din.readDouble();
}
|
| JDR1.0-1.2 |
| JDR1.3 onwards |
|---|
To write:
dout.writeDouble(x1); dout.writeDouble(y1);To read: x1 = din.readDouble(); y1 = din.readDouble(); |
| JDR1.3 onwards |
// String family contains the name of the font family dout.writeInt(family.length()); dout.writeChars(family);To read:
int n = din.readInt();
char[] fam = new char[n];
for (int i = 0; i < n; i++)
{
fam[i] = din.readChar();
}
String family = new String(fam);
dout.writeByte(shape);to read:
byte shape = din.readByte(); // check shape is either 0 or 1
dout.writeByte(series);To read:
byte series = din.readByte(); // check series is either 0 or 1
dout.writeInt(size);To read:
int size = din.readInt(); // check size is not negative
for (int i = 0; i < 6; i++)
{
dout.writeDouble(matrix[i]);
}
To read:
double[] matrix = new double[6];
for (int i = 0; i < 6; i++)
{
matrix[i] = din.readDouble();
}
To read:
// String lfamily contains the LaTeX family declaration dout.writeInt(lfamily.length()); dout.writeChars(lfamily);To read:
int n = din.readInt();
if (n < 0)
{
// insert code to throw error if n is negative
}
else if (n > 0)
{
char[] fam = new char[n];
for (int i = 0; i < n; i++)
{
fam[i] = din.readChar();
}
String lfamily = new String(fam);
}
// String lseries contains the LaTeX series declaration dout.writeInt(lseries.length()); dout.writeChars(lseries);To read:
int n = din.readInt();
if (n < 0)
{
// insert code to throw error if n is negative
}
else if (n > 0)
{
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
String lseries = new String(str);
}
// String lshape contains the LaTeX shape declaration dout.writeInt(lshape.length()); dout.writeChars(lshape);To read:
int n = din.readInt();
if (n < 0)
{
// insert code to throw error if n is negative
}
else if (n > 0)
{
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
String lshape = new String(str);
}
// String lsize contains the LaTeX size declaration dout.writeInt(lsize.length()); dout.writeChars(lsize);To read:
int n = din.readInt();
if (n < 0)
{
// insert code to throw error if n is negative
}
else if (n > 0)
{
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
String lsize = new String(str);
}
dout.writeByte(halign);To read:
byte halign = din.readByte();
if (halign < 0 || halign > 2)
{
// insert code to throw invalid halign exception
}
dout.writeByte(valign);To read:
byte valign = din.readByte();
if (valign < 0 || valign > 3)
{
// insert code to throw invalid valign exception
}
// String ltext contains the alternative LaTeX text dout.writeInt(ltext.length()); dout.writeChars(ltext);To read:
int n = din.readInt();
if (n < 0)
{
// insert code to throw error if n is negative
}
else if (n > 0)
{
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
String ltext = new String(str);
}
// String text contains the text dout.writeInt(text.length()); dout.writeChars(text);To read:
int n = din.readInt();
if (n <= 0)
{
// insert code to throw invalid length exception
}
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
String text = new String(str);
// String filename contains the file name dout.writeInt(filename.length()); dout.writeChars(filename);To read:
int n = din.readInt();
if (n <= 0)
{
// insert code to throw exception
}
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
To read:
// String lfilename contains the LaTeX link to the bitmap dout.writeInt(lfilename.length()); dout.writeChars(lfilename); // String imgcmd contains the LaTeX image command dout.writeInt(imgcmd.length()); dout.writeChars(imgcmd);To read:
int n = din.readInt();
if (n < 0)
{
// insert code to throw invalid length exception
}
else if (n > 0)
{
char[] str = new char[n];
for (int i = 0; i < n; i++)
{
str[i] = din.readChar();
}
String lfilename = new String(str);
}
n = din.readInt();
if (n < 0)
{
// insert code to throw invalid length exception
}
else if (n > 0)
{
char[] cmd = new char[n];
for (int i = 0; i < n; i++)
{
cmd[i] = din.readChar();
}
String imgcmd = new String(cmd);
}
dout.writeByte(type)To read:
byte type = din.readByte(); // check valid value
if (type != 3)
{
dout.writeBoolean(border);
dout.writeInt(label.length());
dout.writeChars(label);
dout.writeInt(pages.length());
dout.writeChars(pages);
}
To read:
if (type != 3)
{
boolean border = din.readBoolean();
int n = din.readInt();
// throw exception if n < 0
String label = "";
char[] c;
if (n > 0)
{
c = new char[n];
for (int i = 0; i < n; i++)
{
c[i] = din.readChar();
}
label = new String(c);
}
n = din.readInt();
// throw exception if n < 0
String pages = "";
if (n > 0)
{
c = new char[n];
for (int i = 0; i < n; i++)
{
c[i] = din.readChar();
}
pages = new String(c);
}
}
dout.writeFloat(top); dout.writeFloat(bottom); dout.writeFloat(left); dout.writeFloat(right);To read:
float top = din.readFloat(); float bottom = din.readFloat(); float left = din.readFloat(); float right = din.readFloat();
if (type == 0 || type == 2)
{
dout.writeByte(shape);
}
To read
if (type == 0 || type == 2)
{
byte shape = din.readByte();
}
if (type == 0 || type == 2)
{
dout.writeByte(valign);
}
To read
if (type == 0 || type == 2)
{
byte valign = din.readByte();
}
// description is a String
int n = description.length();
dout.writeInt(n);
if (n > 0)
{
dout.writeChars(description);
}
To read:
int n = din.readInt();
String description = "";
if (n > 0)
{
char[] desc = new char[n];
for (int i = 0; i < n; i++)
{
desc[i] = din.readChar();
}
description = new String(desc);
}
|
| AJR Format
|