![]() | 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.5.
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();
dout.writeByte(unitType);To read:
byte unitType = din.readByte();
dout.writeInt(majorDivisions); dout.writeInt(subdivisions);To read:
int majorDivisions = din.readInt(); int subdivisions = din.readInt();
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 |
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 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(gray); dout.writeFloat(alpha);To read:
float gray = 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>[<miter-limit>]<winding><start arrow><end arrow> |
JDR1.0 |
JDR1.1 and above |
---|
<linewidth><dash><cap><join>[<miter-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(miterLimit); }To read:
if (join == 0) { float miterLimit = 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 |
---|
<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. 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 |
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
![]() |