2009-01-17 Felix Zielcke <fzielcke@z-51.de>
* Makefile.in: Change font compilation to use new grub-mkfont instead of java version. * util/fonttool/src/org/gnu/grub/fonttool/BDFLoader.java: Remove. * util/fonttool/src/org/gnu/grub/fonttool/CharDefs.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/Converter.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/Font.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/Glyph.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/PFF2Sections.java: Likewise. * util/fonttool/src/org/gnu/grub/fonttool/PFF2Writer.java: Likewise.
This commit is contained in:
parent
7086085ba3
commit
4fa809981f
11 changed files with 23 additions and 1155 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2009-01-17 Felix Zielcke <fzielcke@z-51.de>
|
||||
|
||||
* Makefile.in: Change font compilation to use new grub-mkfont instead
|
||||
of java version.
|
||||
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/BDFLoader.java: Remove.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/CharDefs.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/Converter.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/Font.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/Glyph.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/PFF2Sections.java: Likewise.
|
||||
* util/fonttool/src/org/gnu/grub/fonttool/PFF2Writer.java: Likewise.
|
||||
|
||||
2009-01-16 Christian Franke <franke@computer.org>
|
||||
|
||||
* disk/ata.c (enum grub_ata_commands): Remove EXEC_DEV_DIAGNOSTICS.
|
||||
|
|
19
Makefile.in
19
Makefile.in
|
@ -153,24 +153,21 @@ partmap.lst: $(PARTMAPFILES)
|
|||
|
||||
ifeq (, $(UNIFONT_BDF))
|
||||
else
|
||||
|
||||
ifeq ($(enable_grub_mkfont),yes)
|
||||
|
||||
pkgdata_DATA += unicode.pf2 ascii.pf2
|
||||
|
||||
# Arrows and lines are needed to draw the menu, so we always include them
|
||||
UNICODE_ARROWS=0x2190-0x2193
|
||||
UNICODE_LINES=0x2501-0x251B
|
||||
|
||||
# Note: fonttool should be replaced with C only implementation
|
||||
unicode.pf2: $(UNIFONT_BDF) grub-mkfont
|
||||
$(builddir)/grub-mkfont -o $@ $(UNIFONT_BDF)
|
||||
|
||||
$(builddir)/fonttool/fonttool.jar:
|
||||
mkdir -p "$(builddir)/fonttool/src"
|
||||
javac -source 1.5 -target 1.5 -g -deprecation -encoding UTF-8 -d "$(builddir)/fonttool/src" `find "$(srcdir)/util/fonttool/src/" -name '*.java'`
|
||||
jar cf $(builddir)/fonttool/fonttool.jar -C $(builddir)/fonttool/src .
|
||||
|
||||
unicode.pf2: $(UNIFONT_BDF) $(builddir)/fonttool/fonttool.jar
|
||||
java -cp $(builddir)/fonttool/fonttool.jar org.gnu.grub.fonttool.Converter --in=$(UNIFONT_BDF) --out=$@
|
||||
|
||||
ascii.pf2: $(UNIFONT_BDF) $(builddir)/fonttool/fonttool.jar
|
||||
java -cp $(builddir)/fonttool/fonttool.jar org.gnu.grub.fonttool.Converter --in=$(UNIFONT_BDF) --out=$@ 0x0-0x7f $(UNICODE_ARROWS) $(UNICODE_LINES)
|
||||
ascii.pf2: $(UNIFONT_BDF) grub-mkfont
|
||||
$(builddir)/grub-mkfont -o $@ $(UNIFONT_BDF) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Used for building modules externally
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class BDFLoader {
|
||||
private final BufferedReader in;
|
||||
private final Font font;
|
||||
private int maxCharWidth;
|
||||
private int maxCharHeight;
|
||||
|
||||
BDFLoader(BufferedReader in) {
|
||||
this.in = in;
|
||||
this.font = new Font();
|
||||
this.maxCharWidth = 0;
|
||||
this.maxCharHeight = 0;
|
||||
}
|
||||
|
||||
public static boolean isBDFFile(String filename) {
|
||||
DataInputStream in = null;
|
||||
try {
|
||||
in = new DataInputStream(new FileInputStream(filename));
|
||||
final String signature = "STARTFONT ";
|
||||
byte[] b = new byte[signature.length()];
|
||||
in.readFully(b);
|
||||
in.close();
|
||||
|
||||
String s = new String(b, "US-ASCII");
|
||||
return signature.equals(s);
|
||||
} catch (IOException e) {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e1) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Font loadFontResource(String resourceName) throws IOException {
|
||||
InputStream in = BDFLoader.class.getClassLoader().getResourceAsStream(resourceName);
|
||||
if (in == null)
|
||||
throw new FileNotFoundException("Font resource " + resourceName + " not found");
|
||||
return loadFontFromStream(in);
|
||||
}
|
||||
|
||||
public static Font loadFontFile(String filename) throws IOException {
|
||||
InputStream in = new FileInputStream(filename);
|
||||
return loadFontFromStream(in);
|
||||
}
|
||||
|
||||
private static Font loadFontFromStream(InputStream inStream) throws IOException {
|
||||
BufferedReader in;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Encoding not supported: " + e.getMessage(), e);
|
||||
}
|
||||
return new BDFLoader(in).loadFont();
|
||||
}
|
||||
|
||||
private Font loadFont() throws IOException {
|
||||
loadFontInfo();
|
||||
while (loadChar()) {
|
||||
/* Loop. */
|
||||
}
|
||||
|
||||
font.setMaxCharWidth(maxCharWidth);
|
||||
font.setMaxCharHeight(maxCharHeight);
|
||||
return font;
|
||||
}
|
||||
|
||||
private void loadFontInfo() throws IOException {
|
||||
final Pattern stringSettingPattern = Pattern.compile("^(\\w+)\\s+\"([^\"]+)\"$");
|
||||
String line;
|
||||
// Load the global font information that appears before CHARS.
|
||||
final int UNSET = Integer.MIN_VALUE;
|
||||
font.setAscent(UNSET);
|
||||
font.setDescent(UNSET);
|
||||
font.setFamily("Unknown");
|
||||
font.setBold(false);
|
||||
font.setItalic(false);
|
||||
font.setPointSize(Font.UNKNOWN_POINT_SIZE);
|
||||
do {
|
||||
line = in.readLine();
|
||||
if (line == null)
|
||||
throw new IOException("BDF format error: end of file while " +
|
||||
"reading global font information");
|
||||
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
if (st.hasMoreTokens()) {
|
||||
String name = st.nextToken();
|
||||
if (name.equals("FONT_ASCENT")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: " +
|
||||
"no tokens after " + name);
|
||||
font.setAscent(Integer.parseInt(st.nextToken()));
|
||||
} else if (name.equals("FONT_DESCENT")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: " +
|
||||
"no tokens after " + name);
|
||||
font.setDescent(Integer.parseInt(st.nextToken()));
|
||||
} else if (name.equals("POINT_SIZE")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: " +
|
||||
"no tokens after " + name);
|
||||
// Divide by 10, since it is stored X10.
|
||||
font.setPointSize(Integer.parseInt(st.nextToken()) / 10);
|
||||
} else if (name.equals("FAMILY_NAME")) {
|
||||
Matcher matcher = stringSettingPattern.matcher(line);
|
||||
if (!matcher.matches())
|
||||
throw new IOException("BDF format error: " +
|
||||
"line doesn't match string " +
|
||||
"setting pattern: " + line);
|
||||
font.setFamily(matcher.group(2));
|
||||
} else if (name.equals("WEIGHT_NAME")) {
|
||||
Matcher matcher = stringSettingPattern.matcher(line);
|
||||
if (!matcher.matches())
|
||||
throw new IOException("BDF format error: " +
|
||||
"line doesn't match string " +
|
||||
"setting pattern: " + line);
|
||||
String weightName = matcher.group(2);
|
||||
font.setBold("bold".equalsIgnoreCase(weightName));
|
||||
} else if (name.equals("SLANT")) {
|
||||
Matcher matcher = stringSettingPattern.matcher(line);
|
||||
if (!matcher.matches())
|
||||
throw new IOException("BDF format error: " +
|
||||
"line doesn't match string " +
|
||||
"setting pattern: " + line);
|
||||
String slantType = matcher.group(2);
|
||||
font.setItalic(!"R".equalsIgnoreCase(slantType));
|
||||
} else if (name.equals("CHARS")) {
|
||||
// This is the end of the global font information and
|
||||
// the beginning of the character definitions.
|
||||
break;
|
||||
} else {
|
||||
// Skip other fields.
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
if (font.getAscent() == UNSET)
|
||||
throw new IOException("BDF format error: no FONT_ASCENT property");
|
||||
if (font.getDescent() == UNSET)
|
||||
throw new IOException("BDF format error: no FONT_DESCENT property");
|
||||
}
|
||||
|
||||
private boolean loadChar() throws IOException {
|
||||
String line;
|
||||
// Find start of character
|
||||
do {
|
||||
line = in.readLine();
|
||||
if (line == null)
|
||||
return false;
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
if (st.hasMoreTokens() && st.nextToken().equals("STARTCHAR")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: no character name after STARTCHAR");
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
// Find properties
|
||||
final int UNSET = Integer.MIN_VALUE;
|
||||
int codePoint = UNSET;
|
||||
int bbx = UNSET;
|
||||
int bby = UNSET;
|
||||
int bbox = UNSET;
|
||||
int bboy = UNSET;
|
||||
int dwidth = UNSET;
|
||||
do {
|
||||
line = in.readLine();
|
||||
if (line == null)
|
||||
return false;
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
if (st.hasMoreTokens()) {
|
||||
String field = st.nextToken();
|
||||
if (field.equals("ENCODING")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: no encoding # after ENCODING");
|
||||
String codePointStr = st.nextToken();
|
||||
codePoint = Integer.parseInt(codePointStr);
|
||||
} else if (field.equals("BBX")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: no tokens after BBX");
|
||||
bbx = Integer.parseInt(st.nextToken());
|
||||
bby = Integer.parseInt(st.nextToken());
|
||||
bbox = Integer.parseInt(st.nextToken());
|
||||
bboy = Integer.parseInt(st.nextToken());
|
||||
} else if (field.equals("DWIDTH")) {
|
||||
if (!st.hasMoreTokens())
|
||||
throw new IOException("BDF format error: no tokens after DWIDTH");
|
||||
dwidth = Integer.parseInt(st.nextToken());
|
||||
int dwidthY = Integer.parseInt(st.nextToken());
|
||||
// The DWIDTH Y value should be zero for any normal font.
|
||||
if (dwidthY != 0) {
|
||||
throw new IOException("BDF format error: dwidth Y value" +
|
||||
"is nonzero (" + dwidthY + ") " +
|
||||
"for char " + codePoint + ".");
|
||||
}
|
||||
} else if (field.equals("BITMAP")) {
|
||||
break; // now read the bitmap
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
if (codePoint == UNSET)
|
||||
throw new IOException("BDF format error: " +
|
||||
"no code point set");
|
||||
if (bbx == UNSET || bby == UNSET)
|
||||
throw new IOException("BDF format error: " +
|
||||
"bbx/bby missing: " + bbx + ", " + bby +
|
||||
" for char " + codePoint);
|
||||
|
||||
if (bbox == UNSET || bboy == UNSET)
|
||||
throw new IOException("BDF format error: " +
|
||||
"bbox/bboy missing: " + bbox + ", " + bboy +
|
||||
" for char " + codePoint);
|
||||
|
||||
if (dwidth == UNSET)
|
||||
throw new IOException("BDF format error: " +
|
||||
"dwidth missing for char " + codePoint);
|
||||
|
||||
final int glyphWidth = bbx;
|
||||
final int glyphHeight = bby;
|
||||
if (glyphWidth > maxCharWidth)
|
||||
maxCharWidth = glyphWidth;
|
||||
if (glyphHeight > maxCharHeight)
|
||||
maxCharHeight = glyphHeight;
|
||||
|
||||
// Read the bitmap
|
||||
Glyph glyph = new Glyph(codePoint, glyphWidth, glyphHeight, bbox, bboy, dwidth);
|
||||
for (int y = 0; y < glyphHeight; y++) {
|
||||
line = in.readLine();
|
||||
if (line == null)
|
||||
return false;
|
||||
for (int b = 0; b < line.length(); b++) {
|
||||
int v = Integer.parseInt(Character.toString(line.charAt(b)), 16);
|
||||
for (int x = b * 4, i = 0; i < 4 && x < glyphWidth; x++, i++) {
|
||||
boolean set = (v & 0x8) != 0;
|
||||
v <<= 1;
|
||||
glyph.setPixel(x, y, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
font.putGlyph(codePoint, glyph);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
class CharDefs {
|
||||
private boolean debug = "1".equals(System.getProperty("fonttool.debug"));
|
||||
private TreeMap<Integer, Glyph> glyphs;
|
||||
private ByteArrayOutputStream charDefsData;
|
||||
private int maxCharWidth;
|
||||
private int maxCharHeight;
|
||||
private HashMap<Integer, CharStorageInfo> charIndex;
|
||||
|
||||
public CharDefs(Font font) {
|
||||
this.glyphs = font.getGlyphs();
|
||||
this.charIndex = null;
|
||||
this.charDefsData = null;
|
||||
|
||||
calculateMaxSizes();
|
||||
}
|
||||
|
||||
private void calculateMaxSizes() {
|
||||
maxCharWidth = 0;
|
||||
maxCharHeight = 0;
|
||||
for (Glyph glyph : glyphs.values()) {
|
||||
final int w = glyph.getWidth();
|
||||
final int h = glyph.getHeight();
|
||||
if (w > maxCharWidth)
|
||||
maxCharWidth = w;
|
||||
if (h > maxCharHeight)
|
||||
maxCharHeight = h;
|
||||
}
|
||||
}
|
||||
|
||||
void buildDefinitions(List<CharacterRange> rangeList) {
|
||||
charIndex = new HashMap<Integer, CharStorageInfo>();
|
||||
HashMap<CharDef, Long> charDefIndex = new HashMap<CharDef, Long>();
|
||||
charDefsData = new ByteArrayOutputStream();
|
||||
DataOutputStream charDefs = new DataOutputStream(charDefsData);
|
||||
try {
|
||||
// Loop through all the glyphs, writing the glyph data to the
|
||||
// in-memory byte stream, collapsing duplicate glyphs, and
|
||||
// constructing index information.
|
||||
for (Glyph glyph : glyphs.values()) {
|
||||
// Determine if glyph should be included in written file
|
||||
if (rangeList.size() > 0) {
|
||||
boolean skip = true;
|
||||
|
||||
for (Iterator<CharacterRange> iter = rangeList.iterator(); iter
|
||||
.hasNext();) {
|
||||
CharacterRange item = iter.next();
|
||||
|
||||
if (item.isWithinRange(glyph.getCodePoint())) {
|
||||
skip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CharDef charDef = new CharDef(glyph.getWidth(),
|
||||
glyph.getHeight(),
|
||||
glyph.getBitmap());
|
||||
|
||||
if (charDefIndex.containsKey(charDef)) {
|
||||
// Use already-written glyph.
|
||||
if (debug)
|
||||
System.out.printf("Duplicate glyph for character U+%04X%n",
|
||||
glyph.getCodePoint());
|
||||
final int charOffset = charDefIndex.get(charDef).intValue();
|
||||
final CharStorageInfo info =
|
||||
new CharStorageInfo(glyph.getCodePoint(), charOffset);
|
||||
charIndex.put(glyph.getCodePoint(), info);
|
||||
} else {
|
||||
// Write glyph data.
|
||||
final int charOffset = charDefs.size();
|
||||
final CharStorageInfo info =
|
||||
new CharStorageInfo(glyph.getCodePoint(), charOffset);
|
||||
charIndex.put(glyph.getCodePoint(), info);
|
||||
|
||||
charDefIndex.put(charDef, (long) charOffset);
|
||||
|
||||
charDefs.writeShort(glyph.getWidth());
|
||||
charDefs.writeShort(glyph.getHeight());
|
||||
charDefs.writeShort(glyph.getBbox());
|
||||
charDefs.writeShort(glyph.getBboy());
|
||||
charDefs.writeShort(glyph.getDeviceWidth());
|
||||
charDefs.write(glyph.getBitmap());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error writing to in-memory byte stream", e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxCharWidth() {
|
||||
return maxCharWidth;
|
||||
}
|
||||
|
||||
public int getMaxCharHeight() {
|
||||
return maxCharHeight;
|
||||
}
|
||||
|
||||
public HashMap<Integer, CharStorageInfo> getCharIndex() {
|
||||
if (charIndex == null) throw new IllegalStateException();
|
||||
return charIndex;
|
||||
}
|
||||
|
||||
public byte[] getDefinitionData() {
|
||||
if (charDefsData == null) throw new IllegalStateException();
|
||||
return charDefsData.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
private static class CharDef {
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final byte[] data;
|
||||
|
||||
public CharDef(int width, int height, byte[] data) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
CharDef charDef = (CharDef) o;
|
||||
|
||||
if (height != charDef.height) return false;
|
||||
if (width != charDef.width) return false;
|
||||
if (!Arrays.equals(data, charDef.data)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = width;
|
||||
result = 31 * result + height;
|
||||
result = 31 * result + Arrays.hashCode(data);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getIndexSize() {
|
||||
if (charIndex == null)
|
||||
return 0;
|
||||
|
||||
return charIndex.size();
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
class CharStorageInfo {
|
||||
private final int codePoint;
|
||||
private final int fileOffset;
|
||||
|
||||
public CharStorageInfo(int codePoint, int fileOffset) {
|
||||
this.codePoint = codePoint;
|
||||
this.fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
public int getCodePoint() {
|
||||
return codePoint;
|
||||
}
|
||||
|
||||
public int getFileOffset() {
|
||||
return fileOffset;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
/**
|
||||
* @author chaac
|
||||
*
|
||||
*/
|
||||
public class CharacterRange {
|
||||
private int start;
|
||||
private int end;
|
||||
|
||||
public CharacterRange(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
protected boolean isCombinable(CharacterRange range) {
|
||||
if (getStart() <= range.getStart() && range.getStart() <= getEnd())
|
||||
return true;
|
||||
|
||||
if (range.getStart() <= getStart() && getStart() <= range.getEnd())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isWithinRange(int value) {
|
||||
if (value >= start && value <= end)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean combine(CharacterRange range) {
|
||||
int start;
|
||||
int end;
|
||||
|
||||
if (! isCombinable(range))
|
||||
return false;
|
||||
|
||||
start = getStart();
|
||||
if (range.getStart() < start)
|
||||
start = range.getStart();
|
||||
|
||||
end = getEnd();
|
||||
if (range.getEnd() > end)
|
||||
end = range.getEnd();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Program to convert BDF fonts into PFF2 fonts for use with GRUB.
|
||||
*/
|
||||
public class Converter {
|
||||
public static void main(String[] args) {
|
||||
if (args.length < 1) {
|
||||
printUsageAndExit();
|
||||
}
|
||||
|
||||
String in = null;
|
||||
String out = null;
|
||||
List <CharacterRange> rangeList = new ArrayList<CharacterRange>();
|
||||
|
||||
try {
|
||||
for (String arg : args) {
|
||||
if (arg.startsWith("--")) {
|
||||
String option;
|
||||
String value;
|
||||
int equalsPos = arg.indexOf('=');
|
||||
if (equalsPos < 0) {
|
||||
option = arg.substring(2);
|
||||
value = null;
|
||||
} else {
|
||||
option = arg.substring(2, equalsPos);
|
||||
value = arg.substring(equalsPos + 1);
|
||||
}
|
||||
|
||||
if ("in".equals(option)) {
|
||||
if (value == null)
|
||||
throw new CommandLineException(option
|
||||
+ " option requires a value.");
|
||||
in = value;
|
||||
} else if ("out".equals(option)) {
|
||||
if (value == null)
|
||||
throw new CommandLineException(option
|
||||
+ " option requires a value.");
|
||||
out = value;
|
||||
}
|
||||
} else if (arg.startsWith("0x")) {
|
||||
// Range specifier
|
||||
String strRange[] = arg.split("-");
|
||||
|
||||
if (strRange.length > 0) {
|
||||
boolean validRange = true;
|
||||
int start;
|
||||
int end;
|
||||
|
||||
if (strRange.length > 2) {
|
||||
validRange = false;
|
||||
} else if (strRange.length == 2
|
||||
&& !strRange[1].startsWith("0x")) {
|
||||
validRange = false;
|
||||
} else
|
||||
{
|
||||
try {
|
||||
start = Integer.parseInt(strRange[0]
|
||||
.substring(2), 16);
|
||||
end = start;
|
||||
|
||||
if (strRange.length == 2) {
|
||||
end = Integer.parseInt(strRange[1]
|
||||
.substring(2), 16);
|
||||
}
|
||||
|
||||
CharacterRange range = new CharacterRange(
|
||||
start, end);
|
||||
boolean add = true;
|
||||
|
||||
// First, try to combine range to existing ranges
|
||||
for (Iterator<CharacterRange> iter = rangeList.iterator(); iter.hasNext(); )
|
||||
{
|
||||
CharacterRange item = iter.next();
|
||||
|
||||
if (range.equals(item))
|
||||
{
|
||||
add = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.combine(range))
|
||||
{
|
||||
// Start from beginning of list using combined range
|
||||
range = item;
|
||||
iter = rangeList.iterator();
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If range could not be combined or no matching range, add it to the list
|
||||
if (add)
|
||||
{
|
||||
rangeList.add(range);
|
||||
}
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
validRange = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!validRange) {
|
||||
throw new CommandLineException("Invalid range `"
|
||||
+ arg + "'.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new CommandLineException("Non-option argument `" + arg + "'.");
|
||||
}
|
||||
}
|
||||
if (in == null || out == null) {
|
||||
throw new CommandLineException("Both --in=X and --out=Y must be specified.");
|
||||
}
|
||||
} catch (CommandLineException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
// Read BDF.
|
||||
Font font = BDFLoader.loadFontFile(in);
|
||||
|
||||
// Write PFF2.
|
||||
new PFF2Writer(out).writeFont(font, rangeList);
|
||||
} catch (IOException e) {
|
||||
System.err.println("I/O error converting font: " + e);
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CommandLineException extends Exception {
|
||||
public CommandLineException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printUsageAndExit() {
|
||||
System.err.println("GNU GRUB Font Conversion Tool");
|
||||
System.err.println();
|
||||
System.err.println("Usage: Converter --in=IN.bdf --out=OUT.pf2");
|
||||
System.err.println();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class Font {
|
||||
public static final int UNKNOWN_POINT_SIZE = -1;
|
||||
|
||||
private TreeMap<Integer, Glyph> glyphs;
|
||||
private String family;
|
||||
private boolean bold;
|
||||
private boolean italic;
|
||||
private int pointSize;
|
||||
private int maxCharWidth;
|
||||
private int maxCharHeight;
|
||||
private int ascent;
|
||||
private int descent;
|
||||
|
||||
public Font() {
|
||||
glyphs = new TreeMap<Integer, Glyph>();
|
||||
}
|
||||
|
||||
public String getFamily() {
|
||||
return family;
|
||||
}
|
||||
|
||||
public void setFamily(String family) {
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
public boolean isBold() {
|
||||
return bold;
|
||||
}
|
||||
|
||||
public void setBold(boolean bold) {
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
public boolean isItalic() {
|
||||
return italic;
|
||||
}
|
||||
|
||||
public void setItalic(boolean italic) {
|
||||
this.italic = italic;
|
||||
}
|
||||
|
||||
public int getPointSize() {
|
||||
return pointSize;
|
||||
}
|
||||
|
||||
public void setPointSize(int pointSize) {
|
||||
this.pointSize = pointSize;
|
||||
}
|
||||
|
||||
public int getMaxCharWidth() {
|
||||
return maxCharWidth;
|
||||
}
|
||||
|
||||
public void setMaxCharWidth(int maxCharWidth) {
|
||||
this.maxCharWidth = maxCharWidth;
|
||||
}
|
||||
|
||||
public int getMaxCharHeight() {
|
||||
return maxCharHeight;
|
||||
}
|
||||
|
||||
public void setMaxCharHeight(int maxCharHeight) {
|
||||
this.maxCharHeight = maxCharHeight;
|
||||
}
|
||||
|
||||
public int getAscent() {
|
||||
return ascent;
|
||||
}
|
||||
|
||||
public void setAscent(int ascent) {
|
||||
this.ascent = ascent;
|
||||
}
|
||||
|
||||
public int getDescent() {
|
||||
return descent;
|
||||
}
|
||||
|
||||
public void setDescent(int descent) {
|
||||
this.descent = descent;
|
||||
}
|
||||
|
||||
public void putGlyph(int codePoint, Glyph glyph) {
|
||||
glyphs.put(codePoint, glyph);
|
||||
}
|
||||
|
||||
public TreeMap<Integer, Glyph> getGlyphs() {
|
||||
return glyphs;
|
||||
}
|
||||
|
||||
public Glyph getGlyph(int codePoint) {
|
||||
return glyphs.get(codePoint);
|
||||
}
|
||||
|
||||
public String getStandardName() {
|
||||
StringBuilder name = new StringBuilder(getFamily());
|
||||
if (isBold()) name.append(" Bold");
|
||||
if (isItalic()) name.append(" Italic");
|
||||
name.append(' ');
|
||||
name.append(getPointSize());
|
||||
return name.toString();
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
public class Glyph {
|
||||
private final int codePoint;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
// These define the amounts to shift the character bitmap by
|
||||
// before drawing it. See
|
||||
// http://www.adobe.com/devnet/font/pdfs/5005.BDF_Spec.pdf
|
||||
// and
|
||||
// http://www.linuxbabble.com/documentation/x/bdf/
|
||||
// for explanatory figures.
|
||||
private final int bbox;
|
||||
private final int bboy;
|
||||
|
||||
// Number of pixels to advance horizontally from this character's origin
|
||||
// to the origin of the next character.
|
||||
private final int deviceWidth;
|
||||
|
||||
// Row-major order, no padding. Rows can break within a byte.
|
||||
// MSb is first (leftmost/uppermost) pixel.
|
||||
private final byte[] bitmap;
|
||||
|
||||
public Glyph(int codePoint, int width, int height, int bbox, int bboy, int deviceWidth) {
|
||||
this(codePoint, width, height, bbox, bboy, deviceWidth,
|
||||
new byte[(width * height + 7) / 8]);
|
||||
}
|
||||
|
||||
public Glyph(int codePoint, int width, int height,
|
||||
int bbox, int bboy, int deviceWidth,
|
||||
byte[] bitmap) {
|
||||
this.codePoint = codePoint;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.bboy = bboy;
|
||||
this.bbox = bbox;
|
||||
this.deviceWidth = deviceWidth;
|
||||
this.bitmap = bitmap;
|
||||
}
|
||||
|
||||
public void setPixel(int x, int y, boolean value) {
|
||||
if (x < 0 || y < 0 || x >= width || y >= height)
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid pixel location (" + x + ", " + y + ") for "
|
||||
+ width + "x" + height + " glyph");
|
||||
|
||||
int bitIndex = y * width + x;
|
||||
int byteIndex = bitIndex / 8;
|
||||
int bitPos = bitIndex % 8;
|
||||
int v = value ? 0x80 >>> bitPos : 0;
|
||||
int mask = ~(0x80 >>> bitPos);
|
||||
bitmap[byteIndex] = (byte) ((bitmap[byteIndex] & mask) | v);
|
||||
}
|
||||
|
||||
public int getCodePoint() {
|
||||
return codePoint;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getBbox() {
|
||||
return bbox;
|
||||
}
|
||||
|
||||
public int getBboy() {
|
||||
return bboy;
|
||||
}
|
||||
|
||||
public int getDeviceWidth() {
|
||||
return deviceWidth;
|
||||
}
|
||||
|
||||
public byte[] getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
/**
|
||||
* Section name constants for the PFF2 file format.
|
||||
*/
|
||||
public class PFF2Sections {
|
||||
static final String FILE = "FILE";
|
||||
static final String FONT_NAME = "NAME";
|
||||
static final String FONT_FAMILY = "FAMI";
|
||||
static final String FONT_WEIGHT = "WEIG";
|
||||
static final String FONT_SLANT = "SLAN";
|
||||
static final String FONT_POINT_SIZE = "PTSZ";
|
||||
static final String MAX_CHAR_WIDTH = "MAXW";
|
||||
static final String MAX_CHAR_HEIGHT = "MAXH";
|
||||
static final String FONT_ASCENT = "ASCE";
|
||||
static final String FONT_DESCENT = "DESC";
|
||||
static final String CHAR_INDEX = "CHIX";
|
||||
static final String REMAINDER_IS_DATA = "DATA";
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
/**
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.gnu.grub.fonttool;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.List;
|
||||
|
||||
// TODO Add DEFLATE compressed blocks of characters.
|
||||
public class PFF2Writer {
|
||||
private RandomAccessFile f;
|
||||
private String currentSection;
|
||||
private long currentSectionStart;
|
||||
|
||||
public PFF2Writer(String filename) throws FileNotFoundException {
|
||||
this.f = new RandomAccessFile(filename, "rw");
|
||||
this.currentSection = null;
|
||||
this.currentSectionStart = -1;
|
||||
}
|
||||
|
||||
public void writeFont(Font font, List<CharacterRange> rangeList) throws IOException {
|
||||
// Clear existing file.
|
||||
f.setLength(0);
|
||||
|
||||
// Write file type ID header.
|
||||
writeSection(PFF2Sections.FILE, "PFF2");
|
||||
|
||||
writeSection(PFF2Sections.FONT_NAME, font.getStandardName());
|
||||
writeSection(PFF2Sections.FONT_FAMILY, font.getFamily());
|
||||
writeSection(PFF2Sections.FONT_WEIGHT, font.isBold() ? "bold" : "normal");
|
||||
writeSection(PFF2Sections.FONT_SLANT, font.isItalic() ? "italic" : "normal");
|
||||
if (font.getPointSize() != Font.UNKNOWN_POINT_SIZE)
|
||||
writeShortSection(PFF2Sections.FONT_POINT_SIZE, font.getPointSize());
|
||||
|
||||
// Construct character definitions.
|
||||
CharDefs charDefs = new CharDefs(font);
|
||||
charDefs.buildDefinitions(rangeList);
|
||||
|
||||
// Write max character width and height metrics.
|
||||
writeShortSection(PFF2Sections.MAX_CHAR_WIDTH, charDefs.getMaxCharWidth());
|
||||
writeShortSection(PFF2Sections.MAX_CHAR_HEIGHT, charDefs.getMaxCharHeight());
|
||||
writeShortSection(PFF2Sections.FONT_ASCENT, font.getAscent());
|
||||
writeShortSection(PFF2Sections.FONT_DESCENT, font.getDescent());
|
||||
|
||||
// Write character index with pointers to the character definitions.
|
||||
beginSection(PFF2Sections.CHAR_INDEX);
|
||||
|
||||
// Determine the size of the index, so we can properly refer to the
|
||||
// character definition offset in the index. The actual number of
|
||||
// bytes written is compared to the calculated value to ensure we
|
||||
// are correct.
|
||||
final int indexStart = (int) f.getFilePointer();
|
||||
final int calculatedIndexLength =
|
||||
charDefs.getIndexSize() * (4 + 1 + 4);
|
||||
final int charDefStart = indexStart + calculatedIndexLength + 8;
|
||||
|
||||
for (CharStorageInfo storageInfo : charDefs.getCharIndex().values()) {
|
||||
f.writeInt(storageInfo.getCodePoint());
|
||||
f.writeByte(0); // Storage flags: bits 1..0 = 00b : uncompressed.
|
||||
f.writeInt(charDefStart + storageInfo.getFileOffset());
|
||||
}
|
||||
|
||||
final int indexEnd = (int) f.getFilePointer();
|
||||
if (indexEnd - indexStart != calculatedIndexLength) {
|
||||
throw new RuntimeException("Incorrect index length calculated, calc="
|
||||
+ calculatedIndexLength
|
||||
+ " actual=" + (indexEnd - indexStart));
|
||||
}
|
||||
endSection(PFF2Sections.CHAR_INDEX);
|
||||
|
||||
f.writeBytes(PFF2Sections.REMAINDER_IS_DATA);
|
||||
f.writeInt(-1); // Data takes up the rest of the file.
|
||||
f.write(charDefs.getDefinitionData());
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
private void beginSection(String sectionName) throws IOException {
|
||||
verifyOkToBeginSection(sectionName);
|
||||
|
||||
f.writeBytes(sectionName);
|
||||
f.writeInt(-1); // Placeholder for the section length.
|
||||
currentSection = sectionName;
|
||||
currentSectionStart = f.getFilePointer();
|
||||
}
|
||||
|
||||
private void endSection(String sectionName) throws IOException {
|
||||
verifyOkToEndSection(sectionName);
|
||||
|
||||
long sectionEnd = f.getFilePointer();
|
||||
long sectionLength = sectionEnd - currentSectionStart;
|
||||
f.seek(currentSectionStart - 4);
|
||||
f.writeInt((int) sectionLength);
|
||||
f.seek(sectionEnd);
|
||||
currentSection = null;
|
||||
currentSectionStart = -1;
|
||||
}
|
||||
|
||||
private void verifyOkToBeginSection(String sectionName) {
|
||||
if (sectionName.length() != 4)
|
||||
throw new IllegalArgumentException(
|
||||
"Section names must be 4 characters: `" + sectionName + "'.");
|
||||
if (currentSection != null)
|
||||
throw new IllegalStateException(
|
||||
"Attempt to start `" + sectionName
|
||||
+ "' section before ending the previous section `"
|
||||
+ currentSection + "'.");
|
||||
}
|
||||
|
||||
private void verifyOkToEndSection(String sectionName) {
|
||||
if (sectionName.length() != 4)
|
||||
throw new IllegalStateException("Invalid section name '" + sectionName
|
||||
+ "'; must be 4 characters.");
|
||||
if (currentSection == null)
|
||||
throw new IllegalStateException(
|
||||
"Attempt to end section `" + sectionName
|
||||
+ "' when no section active.");
|
||||
if (!sectionName.equals(currentSection))
|
||||
throw new IllegalStateException(
|
||||
"Attempt to end `" + sectionName
|
||||
+ "' section during active section `"
|
||||
+ currentSection + "'.");
|
||||
}
|
||||
|
||||
private void writeSection(String sectionName, String contents) throws IOException {
|
||||
verifyOkToBeginSection(sectionName);
|
||||
f.writeBytes(sectionName);
|
||||
f.writeInt(contents.length());
|
||||
f.writeBytes(contents);
|
||||
}
|
||||
|
||||
private void writeShortSection(String sectionName, int value) throws IOException {
|
||||
verifyOkToBeginSection(sectionName);
|
||||
f.writeBytes(sectionName);
|
||||
f.writeInt(2);
|
||||
f.writeShort(value);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue