Rev 2438 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2011.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* 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.
*/
package uk.me.parabola.imgfmt.app.typ;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import java.util.List;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
/**
* Base routines and data used by points, lines and polygons.
*
* If fact they are all very similar, so there is very little extra in the
* subclasses apart from the write routine.
*
* @author Steve Ratcliffe
*/
public abstract class TypElement
implements Comparable<TypElement
> {
private int type
;
private int subType
;
protected final List<TypLabel
> labels =
new ArrayList<TypLabel
>();
protected Xpm xpm
;
protected int fontStyle
;
protected Rgb dayFontColour
;
protected Rgb nightFontColour
;
protected int offset
;
public void setType
(int type
) {
this.
type = type
;
}
public void setSubType
(int subType
) {
this.
subType = subType
;
}
public int getType
() {
return type
;
}
/**
* We sort these by type.
* Only the index needs to be sorted (probably) but we don't create the index separately.
*
* @param o The other object to compare against.
* @return The usual -1, 0, 1 for the other object being less than, equal, greater than than this.
*/
public int compareTo
(TypElement o
) {
int t1 = getTypeForFile
();
int t2 = o.
getTypeForFile();
if (t1 == t2
)
return 0;
else if (t1
< t2
)
return -
1;
else
return 1;
}
/**
* Get the type in the format required for writing in the typ file sections.
*/
public int getTypeForFile
() {
return (type
<< 5) |
(subType
& 0x1f
);
}
public void addLabel
(String text
) {
labels.
add(new TypLabel
(text
));
}
public void setXpm
(Xpm xpm
) {
this.
xpm = xpm
;
}
public void setFontStyle
(int font
) {
this.
fontStyle = font
;
}
public void setDayFontColor
(String value
) {
dayFontColour =
new Rgb
(value
);
}
public void setNightCustomColor
(String value
) {
nightFontColour =
new Rgb
(value
);
}
public abstract void write
(ImgFileWriter writer,
CharsetEncoder encoder
);
public int getOffset
() {
return offset
;
}
/**
* Does this element have two colour bitmaps, with possible automatic night colours. For lines and polygons.
*
* Overridden for points and icons.
*/
public boolean simpleBitmap
() {
return true;
}
/**
* Make the label block separately as we need its length before we write it out properly.
*
* @param encoder For encoding the strings as bytes.
* @return A byte buffer with position set to the length of the block.
*/
protected ByteBuffer makeLabelBlock
(CharsetEncoder encoder
) {
ByteBuffer out =
ByteBuffer.
allocate(256 * labels.
size());
for (TypLabel tl : labels
) {
out.
put((byte) tl.
getLang());
CharBuffer cb =
CharBuffer.
wrap(tl.
getText());
try {
ByteBuffer buffer = encoder.
encode(cb
);
out.
put(buffer
);
} catch (CharacterCodingException ignore
) {
String name = encoder.
charset().
name();
//System.out.println("cs " + name);
throw new TypLabelException
(name
);
}
out.
put((byte) 0);
}
return out
;
}
/**
* Write the label block, this is the same for all element types.
* @param encoder To properly encode the labels.
*/
protected void writeLabelBlock
(ImgFileWriter writer,
CharsetEncoder encoder
) {
ByteBuffer out = makeLabelBlock
(encoder
);
int len = out.
position();
// The length is encoded as a variable length integer with the length indicated by a suffix.
len =
(len
<< 1) +
1;
int mask = ~0xff
;
while ((len
& mask
) !=
0) {
mask
<<=
8;
len
<<=
1;
}
// write out the length, I'm assuming that it will be 1 or 2 bytes
if (len
> 0xff
)
writer.
putChar((char) len
);
else
writer.
put((byte) len
);
// Prepare and write buffer
out.
flip();
writer.
put(out
);
}
/**
* Write out extended font information, colour and size.
*
* This is the same for each element type.
*/
protected void writeExtendedFontInfo
(ImgFileWriter writer
) {
byte fontExt =
(byte) fontStyle
;
if (dayFontColour
!=
null)
fontExt |= 0x8
;
if (nightFontColour
!=
null)
fontExt |= 0x10
;
writer.
put(fontExt
);
if (dayFontColour
!=
null)
dayFontColour.
write(writer,
(byte) 0x10
);
if (nightFontColour
!=
null)
nightFontColour.
write(writer,
(byte) 0x10
);
}
/**
* Write out an image. The width and height are written separately, because they are not
* repeated for the night image.
*
* @param xpm Either the day or night XPM.
*/
protected void writeImage
(ImgFileWriter writer, Xpm xpm
) {
ColourInfo colourInfo = xpm.
getColourInfo();
writer.
put((byte) colourInfo.
getNumberOfSColoursForCM());
writer.
put((byte) colourInfo.
getColourMode());
colourInfo.
write(writer
);
xpm.
writeImage(writer
);
}
}