JDR Binary Format
Jpgfdraw's native JDR file format is a binary format written in the big-endian fashion. Since all Java 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
JDR file using the JDR.load()
and JDR.save() methods, otherwise the JDR file
format is as follows:
- To read a data stream in Java (where
filename is a string containing the file name):
DataInputStream din = new DataInputStream(new FileInputStream(filename));
or to write a data stream:DataOutputStream dout = new DataOutputStream(new FileOutputStream(filename));
- At the start of the file, there must be the three
characters JDR stored as 16-bit Unicode characters.
To write:
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 } - The JDR file format version comes next.
This may be 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 or 1.6. The file version number is
stored as a string not a number. First the length of the string
(fileVersion) is stored, then follows the string itself.
To write:
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();
- Next is a value indicating whether or not the
Jpgfdraw settings are
stored.
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 - The settings information is stored as follows:
- a
- A boolean variable (grid) indicating whether or
not to display the grid. To write:
dout.writeBoolean(grid);
To read:boolean grid = din.readBoolean();
- b
- A boolean variable (gridLock) indicating whether or
not to lock the grid. To write:
dout.writeBoolean(gridLock);
To read:boolean gridLock = din.readBoolean();
- c
- A boolean variable (showRulers) indicating whether
or not to show the rulers. To write:
dout.writeBoolean(showRulers);
To read:boolean showRulers = din.readBoolean();
- d
- A 32-bit integer indicating which tool to select. This must be
an integer between 0 and 7 (inclusive). Table A.1
indicates the integer ID for each tool. To write (where tool
is an integer):
dout.writeInt(tool);
To read:int tool = din.readInt(); if (tool < 0 || tool > 7) { // insert invalid tool id error }
- e
- A 32-bit integer indicating the normal font size.
(This is used
as the default in the font settings dialog box, and as the
normal size font for the LaTeX font size conversions.)
To write:
dout.writeInt(normalSize);
To read:int normalSize = din.readInt();
- f
- The paper size (see below).
- g
- The grid style:
JDR1.0-1.5 - An 8-bit byte representing the unit used for the rulers
and grid. This should be one of: 0 (TeX pt), 1 (inches),
2 (centimetres) or 3 (PostScript points).
To write:
dout.writeByte(unitType);
To read:byte unitType = din.readByte();
- Two 32-bit integers representing the major grid divisions
and the subdivisions, respectively.
To write:
dout.writeInt(majorDivisions); dout.writeInt(subdivisions);
To read:int majorDivisions = din.readInt(); int subdivisions = din.readInt();
JDR1.0-1.5 JDR1.6 onwards An 8-bit byte representing the grid style ID. This may be: - 0
- A rectangular grid. This is then followed by:
- An 8-bit byte representing the unit ID (as
above).
- A 64-bit double representing the major grid division.
- A 32-bit integer representing the grid subdivision.
- An 8-bit byte representing the unit ID (as
above).
- 1
- A radial grid. This is then followed by:
- An 8-bit byte representing the unit ID (as
above).
- A 64-bit double representing the major grid division.
- A 32-bit integer representing the grid subdivision.
- A 32-bit integer representing the number of spokes.
- An 8-bit byte representing the unit ID (as
above).
JDR1.6 onwards - An 8-bit byte representing the unit used for the rulers
and grid. This should be one of: 0 (TeX pt), 1 (inches),
2 (centimetres) or 3 (PostScript points).
To write:
- The paper size is specified as an 8-bit byte.
For versions before 1.3, this must be an integer in the range 0 to 18
(inclusive), otherwise it must be in the range 0 to 72 (inclusive).
Table A.2 indicates the integer ID for each paper size,
and Table A.3 shows additional values for version
1.3. If the paper size has an ID of 18 (user defined), then there
must follow the paper width (64-bit double in points), height (64-bit
double in points). For versions prior to 1.3, the user defined
setting must also be followed by a boolean variable to indicate
whether or not the orientation is portrait (true) or
landscape (false).
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 Table A.2: Paper Size Identifiers 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
Table A.3: Additional Paper Size Identifiers (JDR v1.3 onwards) 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)
- The objects that constitute the
picture are now stored. When saving to a file, an outer grouping is
implied that is not evident whilst using Jpgfdraw. This means that
there should always be a single group structure saved to file which
contains all the objects that
constitute the picture. Each object is then recursively
stored. For example, if a picture contains a path, a
group and a text area, in the
JDR file these three objects will be stored as a single
group structure containing the three objects. If in Jpgfdraw you
explicitly group all the objects, then in the
JDR file, the outermost implicit group will contain
only one object which will be this group.
Each object has the following format:
JDR1.0 & 1.1 <id-char><object-specs><fflag>[<flowframe-specs>] JDR1.0 & 1.1
where <id-char> is a character determining the object type: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: - X--text-path
JDR1.5 JDR1.5 As versions 1.5. Additionally: - R--rotational pattern;
- C--scaled pattern;
- L--spiral pattern.
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:
if (/* test to see if object is a group */)
{
dout.writeChar('G');
// save group specification (see below)
}
else if (/* test to see if object is a path */)
{
dout.writeChar('P');
// save path specification (see below)
}
else if (/* test to see if object is a text area */)
{
dout.writeChar('T');
// save text area specification (see below)
}
else if (/* test to see if object is a bitmap */)
{
dout.writeChar('I');
// save bitmap specification (see below)
}
else if (/* test if object is text-path and version > 1.4 */)
{
dout.writeChar('X');
// save text-path specification (see below)
}
else if (/* test if object is rotational-pattern and version > 1.5 */)
{
dout.writeChar('R');
// save rotational-pattern specification (see below)
}
else if (/* test if object is scaled-pattern and version > 1.5 */)
{
dout.writeChar('C');
// save scaled-pattern specification (see below)
}
else if (/* test if object is spiral-pattern and version > 1.5 */)
{
dout.writeChar('L');
// save spiral-pattern specification (see below)
}
// boolean fflag indicates object has flow frame data
dout.writeBoolean(fflag);
if (fflag)
{
// save flow frame data (see below)
}
// if version 1.2 or above save description (see below)
To read:
char c = din.readChar();
if (c == 'G')
{
// read group data (see below)
}
else if (c == 'P')
{
// read path data (see below)
}
else if (c == 'T')
{
// read text area data (see below)
}
else if (c == 'I')
{
// read bitmap data (see below)
}
else if (c == 'X')
{
// read text-path data (see below)
}
else if (c == 'R')
{
// read rotational-pattern data (see below)
}
else if (c == 'C')
{
// read scaled-pattern data (see below)
}
else if (c == 'L')
{
// read spiral-pattern data (see below)
}
else
{
// insert invalid object id code
}
if (din.readBoolean())
{
// read flow frame data (see below)
}
// if version 1.2 or above read description (see below)
- Group data, G, is stored as follows:
<n><object data>+
where <n> is an integer indicating the number of objects within the group, there should then follow <n> lots of <object data>, where <object data> is the data for each object within the group, where the object data is as described above. To write:// int n is the number of objects in the group
dout.writeInt(n);
for (int i = 0; i < n; i++)
{
// save the ith object in the group (see above)
}
To read:
int n = din.readInt();
for (int i = 0; i < n; i++)
{
// read in the ith object in the group (see above)
}
- Path data, P, is stored as
follows:
JDR1.0-1.2 <line colour><fill colour><line style>O|C<n><segment data>+ JDR1.0-1.2
where <line colour> and <fill colour> contain the line and fill colour data (see below), <line style> is the line style data (see below). The character O or C indicates whether the path is open or closed, <n> is an integer indicating the number of segments that constitute the path. This should be followed by <n> lots of <segment data> (described below). Version 1.3 has removed the redundancy present in earlier versions.JDR1.3 onwards <line colour><fill colour><line style>O|C<n><start point><segment data>+ JDR1.3 onwards JDR1.0-1.2 To write: // save line colour data (see below)To read:
// save fill colour 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 colour data (see below)
// read fill colour 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 colour data (see below)To read:
// save fill colour 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 colour data (see below)
// read fill colour 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 - Colour data is stored as
follows: <col-id>[<colour-specs>], where <col-id>
is a character representing the colour type. Available types are
listed in Table A.4. Note that if
<col-id> is T (transparent) <colour-specs> is
omitted.
To write
if (/* test if transparent */)
{
dout.writeChar('T');
}
else if (/* test if single RGB colour */)
{
dout.writeChar('R');
// save single RGB colour data (see below)
}
else if (/* test if single CMYK colour */)
{
dout.writeChar('C');
// save single CMYK colour data (see below)
}
else if (/* test if linear gradient colour */)
{
dout.writeChar('G');
// save linear gradient colour data (see below)
}
else if (/* test if radial and JDR version >= 1.3 */)
{
dout.writeChar('D');
// save radial gradient colour data (see below)
}
else if (/* test if HSB colour and JDR version >= 1.4 */)
{
dout.writeChar('S');
// save HSB colour data (see below)
}
else if (/* test if grey and JDR version >= 1.4 */)
{
dout.writeChar('Y');
// save grey data (see below)
}
To read:
char c = din.readChar();
if (c == 'T')
{
// set to transparent
}
else if (c == 'R')
{
// read single RGB colour data (see below)
}
else if (c == 'C')
{
// read single CMKY colour data (see below)
}
else if (c == 'G')
{
// read linear gradient colour data (see below)
}
else if (c == 'D' /* and JDR version >= 1.3 */)
{
// read radial gradient colour data (see below)
}
else if (c == 'S' /* and JDR version >= 1.4 */)
{
// read HSB colour data (see below)
}
else if (c == 'Y' /* and JDR version >= 1.4 */)
{
// read grey data (see below)
}
else
{
// insert invalid colour identifier code
}
- Single RGB colour data is specified as:
<R><G><B><A>
where each element is a 32-bit single precision floating point number between 0 and 1 (inclusive), and <R> represents the red value, <G> represents the green value, <B> represents the blue value, and <A> represents the alpha (transparency) value. To write: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]
- Single CMYK colour data is specified as:
<C><M><Y><K><A>
where each element is a 32-bit floating point value between 0 and 1 (inclusive), and <C> represents the cyan value, <M> represents the magenta value, <Y> represents the yellow value, <K> represents the black value, and <A> represents the alpha (transparency) value. To write: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]
- As from version 1.4, HSB colour data is
specified as:
<H><S><B><A>
where each element is a 32-bit single precision floating point number and all except <H> lie in the range 0-1 (inclusive). <H> represents the hue value in the range [0,360), <S> represents the saturation value, <B> represents the brightness value, and <A> represents the alpha (transparency) value. To write: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]
- As from version 1.4, grey data is specified
as:
<G><A>
where each element is a 32-bit single precision floating point number between 0 and 1 (inclusive), and <G> represents the grey value, and <A> represents the alpha (transparency) value. To write: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]
- Linear gradient colour data is specified as:
<start-col-id><start-col-specs><end-col-id><end-col-specs><direction>
where <start-col-id> is the colour identifier for the starting colour and <start-col-specs> is the colour specification, and <end-col-id> is the colour identifier for the end colour and <end-col-specs> is the colour specification. The colour identifiers may be any of those listed in Table A.4 except the linear or radial gradient types. The colour specifications are as described above. The gradient direction, <direction>, is a 32-bit integer and may only take one of the following values: 0 (North), 1 (North East), 2 (East), 3 (South East), 4 (South), 5 (South West), 6 (West) and 7 (North West). To write:if (/* start colour RGB */)
{
dout.writeChar('R');
// save RGB single colour data (see above)
}
else if (/* start colour CMYK */)
{
dout.writeChar('C');
// save CMYK single colour data (see above)
}
else if (/* start colour HSB and version >= 1.4 */)
{
dout.writeChar('S');
// save HSB single colour data (see above)
}
else if (/* start colour grey and version >= 1.4 */)
{
dout.writeChar('Y');
// save HSB single grey data (see above)
}
else
{
// insert invalid colour type code
}
if (/* end colour RGB */)
{
dout.writeChar('R');
// save RGB single colour data (see above)
}
else if (/* end colour CMYK */)
{
dout.writeChar('C');
// save CMYK single colour data (see above)
}
else if (/* end colour HSB and version >= 1.4 */)
{
dout.writeChar('S');
// save HSB single colour data (see above)
}
else if (/* end colour grey and version >= 1.4 */)
{
dout.writeChar('Y');
// save HSB single grey data (see above)
}
else
{
// insert invalid colour type code
}
dout.writeInt(direction);
To read:
char c = din.readChar();
if (c == 'R')
{
// read RGB single colour data (see above)
}
else if (c == 'C')
{
// read CMYK single colour data (see above)
}
else if (c == 'S')
{
// read HSB single colour data (see above)
}
else if (c == 'Y')
{
// read grey data (see above)
}
else
{
// insert invalid start colour identifier code
}
c = din.readChar();
if (c == 'R')
{
// read RGB single colour data (see above)
}
else if (c == 'C')
{
// read CMYK single colour data (see above)
}
else if (c == 'S')
{
// read HSB single colour data (see above)
}
else if (c == 'Y')
{
// read grey data (see above)
}
else
{
// insert invalid end colour identifier code
}
int direction = din.readInt();
// check direction is in range [0,7]
- Radial gradient colour data is not available for versions prior to
JDR v1.3. The radial colour data is specified as:
<start-col-id><start-col-specs><end-col-id><end-col-specs><start location>
where <start-col-id> is the colour identifier for the starting colour and <start-col-specs> is the colour specification, and <end-col-id> is the colour identifier for the end colour and <end-col-specs> is the colour specification. The colour identifiers may be any of those listed in Table A.4 except the linear or radial gradient types. The colour specifications are as described above. The starting location, <start location>, is a 32-bit integer and may only take one of the following values: 0 (North), 1 (North East), 2 (East), 3 (South East), 4 (South), 5 (South West), 6 (West), 7 (North West) and 8 (Centre). To write:if (/* start colour RGB */)
{
dout.writeChar('R');
// save RGB single colour data (see above)
}
else if (/* start colour CMYK */)
{
dout.writeChar('C');
// save CMYK single colour data (see above)
}
else if (/* start colour HSB and version >= 1.4 */)
{
dout.writeChar('S');
// save HSB single colour data (see above)
}
else if (/* start colour grey and version >= 1.4 */)
{
dout.writeChar('Y');
// save HSB single grey data (see above)
}
else
{
// insert invalid colour type code
}
if (/* end colour RGB */)
{
dout.writeChar('R');
// save RGB single colour data (see above)
}
else if (/* end colour CMYK */)
{
dout.writeChar('C');
// save CMYK single colour data (see above)
}
else if (/* end colour HSB and version >= 1.4 */)
{
dout.writeChar('S');
// save HSB single colour data (see above)
}
else if (/* end colour grey and version >= 1.4 */)
{
dout.writeChar('Y');
// save HSB single grey data (see above)
}
else
{
// insert invalid colour type code
}
dout.writeInt(startLocation);
To read:
char c = din.readChar();
if (c == 'R')
{
// read RGB single colour data (see above)
}
else if (c == 'C')
{
// read CMYK single colour data (see above)
}
else if (c == 'S')
{
// read HSB single colour data (see above)
}
else if (c == 'Y')
{
// read grey data (see above)
}
else
{
// insert invalid start colour identifier code
}
c = din.readChar();
if (c == 'R')
{
// read RGB single colour data (see above)
}
else if (c == 'C')
{
// read CMYK single colour data (see above)
}
else if (c == 'S')
{
// read HSB single colour data (see above)
}
else if (c == 'Y')
{
// read grey data (see above)
}
else
{
// insert invalid end colour identifier code
}
int startLocation = din.readInt();
// check startLocation is in range [0,8]
- Single RGB colour data is specified as:
- The line style data has changed from file version 1.0 to 1.1 to
take into account the inclusion of mid point markers,
and is stored as follows:
JDR1.0 <linewidth><dash><cap><join>[<mitre-limit>]<winding><start arrow><end arrow> JDR1.0
where:JDR1.1 and above <linewidth><dash><cap><join>[<mitre-limit>]<winding><start arrow><mid marker><end arrow> JDR1.1 and above - <linewidth> the line width (in points) stored as a 32-bit
floating point number. To write:
dout.writeFloat(linewidth);
To read:float linewidth = din.readFloat(); // check linewidth isn't negative
- <dash> is the dash pattern. This is stored as:
<n>[<pattern>+<offset>]
where <n> is 0 if there is no dash pattern (i.e. a solid line) or the number of patterns. There should be an even number of patterns, the odd numbered patterns represent the dash length, the even number of patterns represent the dash gap. The patterns should be stored as a 32-bit floating point number (in points). Lastly, the offset should be a 32-bit float (in points). Note that if <n> is 0, there should be no <pattern> or <offset>. To write: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 } - <cap> is the cap style, this is an 8-bit byte. It may
only have one of the following values: 0 (butt), 1 (round) or 2
(square). To write:
dout.writeByte(cap);
To read:byte cap = din.readByte(); // check cap is in the range [0,2]
- <join> is the join style, this is an 8-bit byte.
It may only have one of the following values: 0 (mitre), 1 (round)
or 2 (bevel). To write:
dout.writeByte(join);
To read:byte join = din.readByte(); // check join is in the range [0,2]
- <mitre-limit> is the mitre-limit, this is a 32-bit float,
and should only be stored if the join style is a mitre. To write:
if (join == 0) { dout.writeFloat(mitreLimit); }To read:if (join == 0) { float mitreLimit = din.readFloat(); } - <winding> is the winding rule, this is an 8-bit byte.
It may only have one of the following values: 0 (Even-Odd) or
1 (Non Zero).
To write:
dout.writeByte(windingRule);
To read:byte windingRule = din.readByte(); // check it's either 0 or 1
- <start arrow> and <end arrow> are the starting and
ending arrow styles. The <mid marker> is the style for the
mid-point markers. Each marker type (start/mid/end) has the same
format, but the file format varies as follows:
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:
<size><repeat><is reversed><orient data><colour data><overlay><composite data>
where:- <size> is a 32-bit float representing the marker size
(some markers will ignore this attribute, but it must still be
present in the file.)
To write:
dout.writeFloat(markerSize);
To read:float markerSize = din.readFloat();
- <repeat> is an 8-bit byte identifying the repeat factor
(a value of 1 indicates a single marker, a value of 2 indicates
a double marker, a value of 3 indicates a triple marker.)
To write:
dout.writeByte(markerRepeat);
To read:byte markerRepeat = din.readByte(); // check lies in range [1-3]
- <is reversed> is a boolean value indicating whether
or not the marker has been reversed. To write:
dout.writeBoolean(markerReversed);
To read:boolean markerReversed = din.readBoolean();
- <orient data> is the marker orientation data. This has
the form <auto-orient>[<angle>] where <auto-orient>
is a boolean value indicating whether the marker should be
oriented along the path. If <auto-orient> is true, <angle>
should be omitted, otherwise <angle> should be a float
representing the orientation angle (in Radians).
To write:
dout.writeBoolean(autoOrient); if (!autoOrient) dout.writeFloat(angle);
To read:boolean autoOrient = din.readBoolean(); float angle = 0.0f; if (!autoOrient) angle = din.readFloat();
- <colour data> is the marker colour. This has the
same form as the line/fill/text colour data
defined earlier, except a transparent
value indicates the colour should be derived from the path
to which the marker is attached, and there is no provision for
gradient paint markers.
- <overlay> is a boolean value indicating whether
to overlay composite markers.
To write:
dout.writeBoolean(overlay);
To read:boolean overlay = din.readBoolean();
- <composite data> is the data for composite markers. This has the same format as the <marker data>. If the <composite data> has a marker id of 0, then the marker is not a composite marker. Although the format allows for nested composite markers, Jpgfdraw's marker settings dialog boxes do not allow for it.
Table A.5: Marker IDs 0 No marker 11 Box Filled 1 Pointed 12 Box Open 2 Triangle 13 Cross 3 Circle 14 Plus 4 Diamond 15 Star 5 Square bracket 16 Triangle Up Filled 6 Bar 17 Triangle Up Open 7 Single 18 Triangle Down Filled 8 Round bracket 19 Triangle Down Open 9 Dot Filled 20 Rhombus Filled 10 Dot Open 21 Rhombus Open
JDR1.1-1.3 JDR1.4 onwards
Table A.6: Additional Marker IDs (JDR 1.4) 22 Pentagon Filled 41 Half Cusp Down 60 Open Semicircle 23 Pentagon Open 42 Alt Single 61 Filled Semicircle 24 Hexagon Filled 43 Alt Single Open 62 Open 5 Pointed star 25 Hexagon Open 44 Triangle Open 63 Filled 5 Pointed star 26 Octagon Filled 45 Circle Open 64 Asterisk 27 Octagon Open 46 Diamond Open 65 Scissors Down Filled 28 Pointed 60 47 Brace 66 Scissors Up Filled 29 Pointed 45 48 Rectangle Cap 67 Scissors Down Open 30 Hooks 49 Chevron Cap 68 Scissors Up Open 31 Hook up 50 Fast Cap 69 Heart Right Filled 32 Hook Down 51 Round Cap 70 Heart Right Open 33 Half Pointed Up 52 Triangle Cap 71 Heart Filled 34 Half Pointed Down 53 Inverted Triangle Cap 72 Heart Open 35 Half Pointed 60 Up 54 Inverted Chevron Cap 73 Snowflake 36 Half Pointed 60 Down 55 Inverted Fast Cap 74 Star Chevron Open 37 Half Pointed 45 Up 56 Alt Bar 75 Star Chevron Filled 38 Half Pointed 45 Down 57 Alt Round 76 Star 6 Filled 39 Cusp 58 Alt Square 77 Star 6 Open 40 Half Cusp Up 59 Alt Brace 78 Equilateral Filled 79 Equilateral Open
<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:
<size> <repeat> <is reversed> <orient data> <colour data> <overlay> [<user offset flag> [<user offset>] <repeat offset flag> [<repeat offset>]] <composite data>
where: <user offset flag> [<user offset>] <repeat offset flag> [<repeat offset>] are only specified if <overlay> is false. <user offset> and <repeat offset> are only specified if <user offset flag> or <repeat offset flag> are true, respectively. The remaining values are as for JDR versions 1.1-1.3 described above.- <user offset flag> is a boolean value indicating
whether the marker offset is specified by the user (true) or
determined automatically (false).
- <user offset> is a 32-bit float indicating the marker
offset from the vertex.
- <repeat offset flag> is a number indicating whether the
repeat offset (i.e. gap between repeat markers) is specified by
the user (true) or determined automatically (false).
- <repeat offset> is a 32-bit float indicating the gap between repeat markers.
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 - <size> is a 32-bit float representing the marker size
(some markers will ignore this attribute, but it must still be
present in the file.)
To write:
- <linewidth> the line width (in points) stored as a 32-bit
floating point number. To write:
- Segments are stored as follows:
<id><specs>
where <id> is a character representing the segment type. This can be one of: B (cubic Bézier), L (line) or M (move). To write:if (/* test if Bézier */)
{
dout.writeChar('B');
// save Bézier data (see below)
}
else if (/* test if line */)
{
dout.writeChar('L');
//save line data (see below)
}
else
{
dout.writeChar('M');
// save move to data (see below)
}
To read:
char c = din.readChar();
if (c == 'B')
{
// read Bézier data (see below)
}
else if (c == 'L')
{
// read line data (see below)
}
else if (c == 'M')
{
// read move to data (see below)
}
else
{
// insert invalid segment identifier code
}
- Bézier segments are stored as follows:
JDR1.0-1.2 <c0x><c0y><c1x><c1y><c2x><c2y><c3x><c3y> JDR1.0-1.2
where <c0x> and <c0y> are the x and y co-ordinates of the starting point, <c1x> and <c1y> are the x and y co-ordinates of the first curvature control point, <c2x> and <c2y> are the x and y co-ordinates of the second curvature control point, and <c3x> and <c3y> are the x and y co-ordinates of the end point. All values are stored as 64-bit doubles. To write: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 - Line and move to (gap) segments are stored as follows:
JDR1.0-1.2 <x0><y0><x1><y1> JDR1.0-1.2
where <x0> and <y0> are the x and y co-ordinates of the starting point and <x1> and <y1> are the x and y co-ordinates of the end point.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
- Bézier segments are stored as follows:
- Colour data is stored as
follows: <col-id>[<colour-specs>], where <col-id>
is a character representing the colour type. Available types are
listed in Table A.4. Note that if
<col-id> is T (transparent) <colour-specs> is
omitted.
- Text area data is stored as
follows:
<fam-length><family><shape><series><size><transformation><latex-flag>[<latex-specs>]<text colour><text-length><text>
where:- <fam-length> is a 32-bit integer that is the length of
the font family name, and <family> is the font family name.
To write:
// 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); - <shape> is an 8-bit byte representing the font shape.
This can have one of two values: 0 (upright) or 1 (italic). To
write:
dout.writeByte(shape);
to read:byte shape = din.readByte(); // check shape is either 0 or 1
- <series> is an 8-bit byte representing the font series.
This can have one of two values: 0 (medium) or 1 (bold). To write:
dout.writeByte(series);
To read:byte series = din.readByte(); // check series is either 0 or 1
- <size> is the font size stored as a 32-bit integer.
To write:
dout.writeInt(size);
To read:int size = din.readInt(); // check size is not negative
- <transformation> is the transformation. The origin is
taken to be the leftmost point along the baseline of the text.
The transformation is stored as:
<m0><m1><m2><m3><m4><m5>
where each element is stored as a 64-bit double precision number. The transformation matrix used is given by:
To write: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(); } - <latex-flag> is a boolean variable indicating whether
or not the <latex-specs> are present. To write:
To read:
- <latex-specs> contains the LaTeX information, and has
the format:
<lfam-length>[<lfamily>]<lseries-length>[<lseries>]<lshape-length>[<lshape>]<lsize-length>[<lsize>]<halign><valign><ltext-length>[<ltext>]
where:- <lfam-length> is an integer indicating the number of
characters in <lfamily> where <lfamily> is a string
containing the LaTeX family declaration (e.g. \rmfamily).
If <lfam-length> is zero, <lfamily> is omitted.
(<lfam-length> must not be negative.) To write:
// 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); } - <lseries-length> is an integer indicating the number of
characters in <lseries> where <lseries> is a string
containing the LaTeX series declaration (e.g. \bfseries).
If <lseries-length> is zero, <lseries> is omitted.
(<lseries-length> must not be negative.) To write:
// 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); } - <lshape-length> is an integer indicating the number of
characters in <lshape> where <lshape> is a string
containing the LaTeX shape declaration (e.g. \itshape).
If <lshape-length> is zero, <lshape> is omitted.
(<lshape-length> must not be negative.) To write:
// 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); } - <lsize-length> is an integer indicating the number of
characters in <lsize> where <lsize> is a string
containing the LaTeX size declaration (e.g. \large).
If <lsize-length> is zero, <lsize> is omitted.
(<lsize-length> must not be negative.) To write:
// 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); } - <halign> is an 8-bit byte indicating the horizontal
alignment of the \pgfbox command. It may only take one of the
following values: 0 (left), 1 (centre) or 2 (right). To write:
dout.writeByte(halign);
To read:byte halign = din.readByte(); if (halign < 0 || halign > 2) { // insert code to throw invalid halign exception } - <valign> is an 8-bit byte indicating the vertical alignment
of the \pgfbox command. It may only take one of the following
values: 0 (top), 1 (centre), 2 (base) or 3 (bottom). To write:
dout.writeByte(valign);
To read:byte valign = din.readByte(); if (valign < 0 || valign > 3) { // insert code to throw invalid valign exception } - <ltext-length> is an integer indicating the number of
characters in <ltext> where <ltext> is a string
containing the LaTeX alternative to <text>.
If <ltext-length> is zero, <ltext> is omitted.
(<ltext-length> must not be negative.) To write:
// 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); }
- <lfam-length> is an integer indicating the number of
characters in <lfamily> where <lfamily> is a string
containing the LaTeX family declaration (e.g. \rmfamily).
If <lfam-length> is zero, <lfamily> is omitted.
(<lfam-length> must not be negative.) To write:
- <text colour> is the text colour. This has the same format
as the path line and fill colours
described above.
- <text length> is the number of characters contained in
the text area (stored as a 32-bit integer) and
<text> are the characters contained in the text area.
<text length> must be strictly positive. To write:
// 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);
- <fam-length> is a 32-bit integer that is the length of
the font family name, and <family> is the font family name.
To write:
- Text-paths are not available for versions below 1.5. For newer
versions, the specifications are stored as follows:
<text colour><fam-length><family><shape><series><size><transformation><latex-flag>[<latex-specs>]<text-length><text>O|C<n><start point><segment data>+
where the text information (<text colour> to <text>) is as described above for text areas. The remaining information is as described above for paths. - Rotational
patterns are not available for versions below 1.6.
For newer versions, the specifications are stored as
follows:
<shape-specs><anchor-x><anchor-y><angle><replicas><mode><show>
where:- <shape-specs> are the underlying object's
specifications as described above. (Bitmap
and text specifications not permitted.)
- <anchor-x> is a 64-bit double representing the
x-coordinate of the anchor point.
- <anchor-y> is a 64-bit double representing the
y-coordinate of the anchor point.
- <angle> is a 64-bit double representing the angle of
rotation.
- <replicas> is a 32-bit integer representing the number
of replicas.
- <mode> is a boolean variable, true if single-path mode.
- <show> is a boolean variable, true if the underlying path is visible.
- <shape-specs> are the underlying object's
specifications as described above. (Bitmap
and text specifications not permitted.)
- Scaled
patterns are not available for versions below 1.6. For
newer versions, the specifications are stored as follows:
<shape-specs><anchor-x><anchor-y><adjust-x><adjust-y><scale-x><scale-y><replicas><mode><show>
where <shape-specs>, <anchor-x>, <anchor-y>, <replicas>, <mode> and <show> are as above. Additionally:- <adjust-x> is a 64-bit double representing the
x-coordinate of the adjust control point.
- <adjust-y> is a 64-bit double representing the
y-coordinate of the adjust control point.
- <scale-x> is a 64-bit double representing the
x-scale factor.
- <scale-y> is a 64-bit double representing the y-scale factor.
- <adjust-x> is a 64-bit double representing the
x-coordinate of the adjust control point.
- Spiral
patterns are not available for versions below 1.6. For
newer versions, the specifications are stored as follows:
<shape-specs><anchor-x><anchor-y><adjust-x><adjust-y><angle><distance><replicas><mode><show>
where <shape-specs>, <anchor-x>, <anchor-y>, <adjust-x>, <adjust-y>, <replicas>, <mode> and <show> are as above. Additionally:- <angle> is a 64-bit double representing the spiral angle
parameter.
- <distance> is a 64-bit double representing the spiral distance parameter.
- <angle> is a 64-bit double representing the spiral angle
parameter.
- Bitmap data are stored as follows:
<filename-length><filename><latex-flag>[<latex-bitmap-specs>]<transformation>
where:- <filename-length> is an integer indicating the number
of characters in the file name, and <filename> is the file name.
Note that <filename-length> must be strictly positive.
To write:
// 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(); } - <latex-flag> is a boolean variable indicating whether or
not the <latex-bitmap-specs> is present. To write:
To read:
boolean latexFlag = din.readBoolean();
if (latexFlag)
{
// read LaTeX bitmap information (see below)
}
- <latex-bitmaps-specs> has the following format:
<lfilename-length>[<lfilename>]<imgcmd-length>[<imgcmd>]
where <lfilename-length> is an integer indicating the number of characters in <lfilename>, and <lfilename> is the LaTeX link to the bitmap file. If <lfilename-length> is zero, <lfilename> is omitted. <imgcmd-length> is an integer indicating the number of characters in <imgcmd>, where <imgcmd> is a string containing the LaTeX command name to include the bitmap (e.g. \pgfimage.) If <imgcmd-length> is zero, <imgcmd> is omitted. To write// 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); } - <transformation> is the transformation matrix, and has the same format as the text area transformation matrix (see above.) The origin is the bottom left corner of the bitmap.
- <filename-length> is an integer indicating the number
of characters in the file name, and <filename> is the file name.
Note that <filename-length> must be strictly positive.
To write:
- Flow frame data is stored as
follows:
- The frame type is stored as an 8-bit byte. This may only
take one of the following values: 0 (static), 1 (flow), 2 (dynamic)
and 3 (typeblock). There should only be one typeblock and this
should belong to the outermost implicit group.
To write:
dout.writeByte(type)
To read:byte type = din.readByte(); // check valid value
- If <type> is not equal to 3 (i.e. is not the typeblock), the following
information should also be saved: a boolean value (border)
indicating whether or not the frame should have a border,
the identification label (label) stored as an integer
(the number of characters in label) followed by that many
characters, and the page list (pages) should likewise be
stored as an integer (the number of characters in pages)
followed by that many characters.
To write:
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); } } - Store margin information as a 32-bit single precision floating
point number, in the following order: top, bottom, left, right.
To write:
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();
- JDR v1.2 and above contains extra information if the frame type
is either 0 (static frame) or 2 (dynamic frame) which relates to the
paragraph shape. This is a byte that can be 0 (standard shape),
1 (use \parshape) or 2 (use \shapepar).
To write:
if (type == 0 || type == 2) { dout.writeByte(shape); }To readif (type == 0 || type == 2) { byte shape = din.readByte(); } - JDR v1.3 onwards contains additional information if the frame type is
either 0 (static frame) or 2 (dynamic frame) which relates to the
vertical alignment of material in the frame. This is a byte that
can be 0 (top), 1 (centre) or 2 (bottom).
To write:
if (type == 0 || type == 2) { dout.writeByte(valign); }To readif (type == 0 || type == 2) { byte valign = din.readByte(); }
- The frame type is stored as an 8-bit byte. This may only
take one of the following values: 0 (static), 1 (flow), 2 (dynamic)
and 3 (typeblock). There should only be one typeblock and this
should belong to the outermost implicit group.
To write:
- JDR v1.2 and above also optionally
contains the object's description. This is saved in the form:
<desc-length>[<description>]
where <desc-length> is an integer indicating the length of the description string. This may be zero, in which case <description> is omitted, otherwise <description> is a sequence of <desc-length> characters that make up the description. To write:// 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); }
Footnotes
- ... processorsA.1
- although some fonts may not be available, and links to bitmaps may be unresolved