Rev 3408 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2006 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* Author: Steve Ratcliffe
* Create date: 03-Dec-2006
*/
package uk.me.parabola.imgfmt.app.trergn;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import uk.me.parabola.imgfmt.app.BufferedImgFileWriter;
import uk.me.parabola.imgfmt.app.ImgFile;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
import uk.me.parabola.imgfmt.fs.ImgChannel;
import uk.me.parabola.log.Logger;
/**
* The region file. Holds actual details of points and lines etc.
*
*
*
* The data is rather complicated and is packed to save space. This class does
* not really handle that format however as it is written by the
* {@link MapObject}s themselves.
*
* Each subdivision takes space in this file. The I am expecting this to be the
* biggest file, although it seems that TRE may be in some circumstances.
*
* @author Steve Ratcliffe
*/
public class RGNFile
extends ImgFile
{
private static final Logger log =
Logger.
getLogger(RGNFile.
class);
private static final int HEADER_LEN = RGNHeader.
HEADER_LEN;
private final RGNHeader header =
new RGNHeader
();
private Subdivision currentDivision
;
private int indPointPtrOff
;
private int polylinePtrOff
;
private int polygonPtrOff
;
private ByteArrayOutputStream extTypePointsData
;
private ByteArrayOutputStream extTypeLinesData
;
private ByteArrayOutputStream extTypeAreasData
;
public RGNFile
(ImgChannel chan
) {
setHeader
(header
);
setWriter
(new BufferedImgFileWriter
(chan
));
// Position at the start of the writable area.
position
(HEADER_LEN
);
}
public void write
() {
if (!isWritable
())
throw new IllegalStateException("File not writable");
header.
setDataSize(position
() - HEADER_LEN
);
if(extTypeAreasData
!=
null) {
header.
setExtTypeAreasInfo(position
(), extTypeAreasData.
size());
getWriter
().
put(extTypeAreasData.
toByteArray());
}
if(extTypeLinesData
!=
null) {
header.
setExtTypeLinesInfo(position
(), extTypeLinesData.
size());
getWriter
().
put(extTypeLinesData.
toByteArray());
}
if(extTypePointsData
!=
null) {
header.
setExtTypePointsInfo(position
(), extTypePointsData.
size());
getWriter
().
put(extTypePointsData.
toByteArray());
}
getHeader
().
writeHeader(getWriter
());
}
public void startDivision
(Subdivision sd
) {
sd.
setStartRgnPointer(position
() - HEADER_LEN
);
// We need to reserve space for a pointer for each type of map
// element that is supported by this division. Note that these
// pointers are only 2bytes long. A pointer to the points is never
// needed as it will always be first if present.
if (sd.
needsIndPointPtr()) {
indPointPtrOff = position
();
position
(position
() +
2);
}
if (sd.
needsPolylinePtr()) {
polylinePtrOff = position
();
position
(position
() +
2);
}
if (sd.
needsPolygonPtr()) {
polygonPtrOff = position
();
position
(position
() +
2);
}
currentDivision = sd
;
}
public void addMapObject
(MapObject item
) {
if(item.
hasExtendedType()) {
try {
if(item
instanceof Point) {
if(extTypePointsData ==
null)
extTypePointsData =
new ByteArrayOutputStream();
item.
write(extTypePointsData
);
}
else if(item
instanceof Polygon) {
if(extTypeAreasData ==
null)
extTypeAreasData =
new ByteArrayOutputStream();
item.
write(extTypeAreasData
);
}
else if(item
instanceof Polyline
) {
if(extTypeLinesData ==
null)
extTypeLinesData =
new ByteArrayOutputStream();
item.
write(extTypeLinesData
);
}
else
log.
error("Can't add object of type " + item.
getClass());
}
catch (IOException ioe
) {
log.
error("Error writing extended type object: " + ioe.
getMessage());
}
}
else {
item.
write(getWriter
());
}
}
public void setIndPointPtr
() {
if (currentDivision.
needsIndPointPtr()) {
long currPos = position
();
position
(indPointPtrOff
);
long off = currPos - currentDivision.
getStartRgnPointer() - HEADER_LEN
;
if (off
> 0xffff
)
throw new IllegalStateException("IndPoint offset too large: " + off
);
getWriter
().
putChar((char) off
);
position
(currPos
);
}
}
public void setPolylinePtr
() {
if (currentDivision.
needsPolylinePtr()) {
long currPos = position
();
position
(polylinePtrOff
);
long off = currPos - currentDivision.
getStartRgnPointer() - HEADER_LEN
;
if (off
> 0xffff
)
throw new IllegalStateException("Polyline offset too large: " + off
);
if (log.
isDebugEnabled())
log.
debug("setting polyline offset to", off
);
getWriter
().
putChar((char) off
);
position
(currPos
);
}
}
public void setPolygonPtr
() {
if (currentDivision.
needsPolygonPtr()) {
long currPos = position
();
long off = currPos - currentDivision.
getStartRgnPointer() - HEADER_LEN
;
log.
debug("currpos=", currPos,
", off=", off
);
if (off
> 0xffff
)
throw new IllegalStateException("Polygon offset too large: " + off
);
if (log.
isDebugEnabled())
log.
debug("setting polygon offset to ", off,
" @", polygonPtrOff
);
position
(polygonPtrOff
);
getWriter
().
putChar((char) off
);
position
(currPos
);
}
}
public ImgFileWriter getWriter
() {
return super.
getWriter();
}
public int getExtTypePointsSize
() {
return (extTypePointsData ==
null)? 0 : extTypePointsData.
size();
}
public int getExtTypeLinesSize
() {
return (extTypeLinesData ==
null)? 0 : extTypeLinesData.
size();
}
public int getExtTypeAreasSize
() {
return (extTypeAreasData ==
null)? 0 : extTypeAreasData.
size();
}
public boolean haveExtendedTypes
() {
return (extTypePointsData
!=
null ||
extTypeLinesData
!=
null ||
extTypeAreasData
!=
null);
}
}