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>
|
2009-01-16 Christian Franke <franke@computer.org>
|
||||||
|
|
||||||
* disk/ata.c (enum grub_ata_commands): Remove EXEC_DEV_DIAGNOSTICS.
|
* 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))
|
ifeq (, $(UNIFONT_BDF))
|
||||||
else
|
else
|
||||||
|
|
||||||
|
ifeq ($(enable_grub_mkfont),yes)
|
||||||
|
|
||||||
pkgdata_DATA += unicode.pf2 ascii.pf2
|
pkgdata_DATA += unicode.pf2 ascii.pf2
|
||||||
|
|
||||||
# Arrows and lines are needed to draw the menu, so we always include them
|
# Arrows and lines are needed to draw the menu, so we always include them
|
||||||
UNICODE_ARROWS=0x2190-0x2193
|
UNICODE_ARROWS=0x2190-0x2193
|
||||||
UNICODE_LINES=0x2501-0x251B
|
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:
|
ascii.pf2: $(UNIFONT_BDF) grub-mkfont
|
||||||
mkdir -p "$(builddir)/fonttool/src"
|
$(builddir)/grub-mkfont -o $@ $(UNIFONT_BDF) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES)
|
||||||
javac -source 1.5 -target 1.5 -g -deprecation -encoding UTF-8 -d "$(builddir)/fonttool/src" `find "$(srcdir)/util/fonttool/src/" -name '*.java'`
|
endif
|
||||||
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)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Used for building modules externally
|
# 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…
Add table
Reference in a new issue