QuickDraw fonts

This commit is contained in:
Denis Molony 2017-01-17 11:00:51 +11:00
parent 30c5b7467f
commit c8397009fa
5 changed files with 343 additions and 72 deletions

View File

@ -0,0 +1,253 @@
package com.bytezone.diskbrowser.applefile;
import com.bytezone.diskbrowser.prodos.ProdosConstants;
import com.bytezone.diskbrowser.utilities.HexFormatter;
public class QuickDrawFont extends AbstractFile
{
private boolean corrupt;
private final int fileType;
private final int auxType;
private final String fontName;
private final int headerSize;
private final int fontSize;
private final int fontFamily;
private final int fontStyle;
private final int versionMajor;
private final int versionMinor;
private final int extent;
private final int fontType;
private final int firstChar;
private final int lastChar;
private final int maxWidth;
private final int maxKern;
private final int negativeDescent;
private final int rectangleWidth;
private final int rectangleHeight;
private final int offsetToOffsetWidthTable;
private final int ascent;
private final int descent;
private final int leading;
private final int rowWords;
private final int totalCharacters;
private final String[] imageLines;
private final byte[] bitImage;
private final byte[] locationTable;
private final byte[] offsetWidthTable;
private final int fontDefinitionOffset;
private final int bitImageOffset;
private final int locationTableOffset;
private final int offsetWidthTableOffset;
public QuickDrawFont (String name, byte[] buffer, int fileType, int auxType)
{
super (name, buffer);
assert fileType == ProdosConstants.FILE_TYPE_FONT;
this.fileType = fileType;
this.auxType = auxType;
fontName = HexFormatter.getPascalString (buffer, 0);
int nameLength = (buffer[0] & 0xFF);
int ptr = nameLength + 1;
headerSize = HexFormatter.getShort (buffer, ptr);
fontDefinitionOffset = nameLength + 1 + headerSize * 2;
fontFamily = HexFormatter.getShort (buffer, ptr + 2);
fontStyle = HexFormatter.getShort (buffer, ptr + 4);
fontSize = HexFormatter.getShort (buffer, ptr + 6);
versionMajor = buffer[ptr + 8] & 0xFF;
versionMinor = buffer[ptr + 9] & 0xFF;
extent = HexFormatter.getShort (buffer, ptr + 10);
ptr = fontDefinitionOffset;
fontType = HexFormatter.getShort (buffer, ptr);
firstChar = HexFormatter.getShort (buffer, ptr + 2);
lastChar = HexFormatter.getShort (buffer, ptr + 4);
maxWidth = HexFormatter.getShort (buffer, ptr + 6);
maxKern = HexFormatter.getShort (buffer, ptr + 8);
negativeDescent = HexFormatter.getShort (buffer, ptr + 10);
rectangleWidth = HexFormatter.getShort (buffer, ptr + 12);
rectangleHeight = HexFormatter.getShort (buffer, ptr + 14);
imageLines = new String[rectangleHeight];
offsetToOffsetWidthTable = HexFormatter.getShort (buffer, ptr + 16);
offsetWidthTableOffset = (ptr + 16) + offsetToOffsetWidthTable * 2;
locationTableOffset = offsetWidthTableOffset - (lastChar - firstChar + 3) * 2;
bitImageOffset = ptr + 26;
ascent = HexFormatter.getShort (buffer, ptr + 18);
descent = HexFormatter.getShort (buffer, ptr + 20);
leading = HexFormatter.getShort (buffer, ptr + 22);
rowWords = HexFormatter.getShort (buffer, ptr + 24);
totalCharacters = lastChar - firstChar + 2; // includes missing character
bitImage = new byte[rowWords * 2 * rectangleHeight]; // should use java bits
locationTable = new byte[(totalCharacters + 1) * 2];
offsetWidthTable = new byte[(totalCharacters + 1) * 2];
if (false)
{
System.out.printf ("Buffer length : %d%n", buffer.length);
System.out.printf ("Total chars : %d%n", totalCharacters);
System.out.printf ("owtable offset : %d%n", offsetWidthTableOffset);
System.out.printf ("owtable size : %d%n", offsetWidthTable.length);
}
if (offsetWidthTableOffset + offsetWidthTable.length > buffer.length)
{
System.out.println ("*********** Bad ow length");
corrupt = true;
return;
}
System.arraycopy (buffer, bitImageOffset, bitImage, 0, bitImage.length);
System.arraycopy (buffer, locationTableOffset, locationTable, 0,
locationTable.length);
System.arraycopy (buffer, offsetWidthTableOffset, offsetWidthTable, 0,
offsetWidthTable.length);
for (int i = 0; i < rectangleHeight; i++)
{
int rowOffset = i * rowWords * 2;
StringBuilder bits = new StringBuilder ();
for (int j = rowOffset; j < rowOffset + rowWords * 2; j++)
bits.append (HexFormatter.getBitString (bitImage[j]));
imageLines[i] = bits.toString ().replaceAll ("1", "#");
}
// System.out.println ("\n Location table o/w table\n");
for (int i = 0, max = totalCharacters + 1; i < max; i++)
{
int location = HexFormatter.getShort (locationTable, i * 2);
int offset = offsetWidthTable[i * 2] & 0xFF;
int width = offsetWidthTable[i * 2 + 1] & 0xFF;
int j = i + 1;
if (j < max)
{
int nextLocation = HexFormatter.getShort (locationTable, j * 2);
int pixelWidth = nextLocation - location;
// System.out.printf ("%3d %04X %04X %2d %02X %02X%n", i, location,
// nextLocation, pixelWidth, offset, width);
if (pixelWidth < 0)
{
System.out.println ("*********** Bad pixelWidth");
corrupt = true;
return;
}
}
// else
// System.out.printf ("%3d %04X %n", i, location);
}
}
@Override
public String getText ()
{
StringBuilder text = new StringBuilder ("Name : " + name + "\n\n");
text.append ("File type : Font\n");
String auxTypeText =
auxType == 0 ? "QuickDraw Font File" : auxType == 1 ? "XX" : "??";
text.append (String.format ("Aux type : %04X (%s)%n%n", auxType, auxTypeText));
text.append (String.format ("Font name : %s%n", fontName));
text.append (String.format ("Font family : %d%n", fontFamily));
text.append (String.format ("Font style : %d%n", fontStyle));
text.append (String.format ("Font size : %d%n", fontSize));
text.append (String.format ("Font version : %d.%d%n", versionMajor, versionMinor));
text.append (String.format ("Font extent : %d%n%n", extent));
text.append (String.format ("Font type : %d%n", fontType));
text.append (String.format ("First char : %d%n", firstChar));
text.append (String.format ("Last char : %d%n", lastChar));
text.append (String.format ("Max width : %d%n", maxWidth));
text.append (String.format ("Max kern : %d%n", maxKern));
text.append (String.format ("Neg descent : %d%n", negativeDescent));
text.append (String.format ("Width : %d%n", rectangleWidth));
text.append (String.format ("Height : %d%n", rectangleHeight));
text.append (String.format ("O/W Offset : %d%n", offsetToOffsetWidthTable));
text.append (String.format ("Ascent : %d%n", ascent));
text.append (String.format ("Descent : %d%n", descent));
text.append (String.format ("Leading : %d%n", leading));
text.append (String.format ("Row words : %d%n%n", rowWords));
if (corrupt)
{
text.append ("\nCannot interpret Font file");
return text.toString ();
}
for (int i = 0; i < totalCharacters; i++)
{
int offset = offsetWidthTable[i * 2] & 0xFF;
int width = offsetWidthTable[i * 2 + 1] & 0xFF;
if (offset == 255 && width == 255)
continue;
int location = HexFormatter.getShort (locationTable, i * 2);
int nextLocation = HexFormatter.getShort (locationTable, (i + 1) * 2);
int pixelWidth = nextLocation - location;
text.append (String.format ("Char %3d %,5d %2d %,5d %,5d%n", i, location,
pixelWidth, offset, width));
if (pixelWidth > 0 && location + pixelWidth < imageLines[0].length ())
for (int j = 0; j < rectangleHeight; j++)
{
for (int w = 0; w < width; w++)
text.append (' ');
text.append (imageLines[j].substring (location, location + pixelWidth));
text.append ("\n");
}
}
if (false)
{
text.append ("\n\n");
for (int i = 0; i < rectangleHeight; i++)
{
text.append (String.format ("Row: %d%n", i));
int rowOffset = i * rowWords * 2;
String line = HexFormatter.format (bitImage, rowOffset, rowWords * 2,
bitImageOffset + rowOffset);
text.append (line);
text.append ("\n\n");
}
text.append ("\n\n");
text.append (HexFormatter.format (locationTable, 0, locationTable.length,
locationTableOffset));
text.append ("\n\n");
text.append (HexFormatter.format (offsetWidthTable, 0, offsetWidthTable.length,
offsetWidthTableOffset));
text.append ("\n\n");
for (int i = 0; i < totalCharacters; i++)
{
int location = HexFormatter.getShort (locationTable, i * 2);
text.append (String.format ("%3d %04X %,7d%n", i, location, location));
}
text.append ("\n\n");
for (int i = 0; i < totalCharacters; i++)
{
int offset = offsetWidthTable[i * 2] & 0xFF;
int width = offsetWidthTable[i * 2 + 1] & 0xFF;
text.append (String.format ("%3d %02X %02X%n", i, offset, width));
}
}
return text.toString ();
}
}

View File

@ -3,44 +3,47 @@ package com.bytezone.diskbrowser.applefile;
public class SimpleText extends AbstractFile
{
public SimpleText (String name, byte[] buffer)
{
super (name, buffer);
}
public SimpleText (String name, byte[] buffer)
{
super (name, buffer);
}
@Override
public String getText ()
{
StringBuilder text = new StringBuilder ();
@Override
public String getText ()
{
StringBuilder text = new StringBuilder ();
text.append ("Name : " + name + "\n");
text.append (String.format ("End of file : %,8d%n%n", buffer.length));
text.append ("Name : " + name + "\n");
text.append (String.format ("End of file : %,8d%n%n", buffer.length));
int ptr = 0;
while (ptr < buffer.length)
{
String line = getLine (ptr);
text.append (line + "\n");
ptr += line.length () + 1;
if (ptr < buffer.length && buffer[ptr] == 0x0A)
ptr++;
}
return text.toString ();
}
int ptr = 0;
while (ptr < buffer.length)
{
String line = getLine (ptr);
text.append (line + "\n");
ptr += line.length () + 1;
if (ptr < buffer.length && buffer[ptr] == 0x0A)
ptr++;
}
return text.toString ();
}
private String getLine (int ptr)
{
StringBuilder line = new StringBuilder ();
while (ptr < buffer.length && buffer[ptr] != 0x0D)
line.append ((char) buffer[ptr++]);
return line.toString ();
}
private String getLine (int ptr)
{
StringBuilder line = new StringBuilder ();
public static boolean isHTML (byte[] buffer)
{
String text = new String (buffer, 0, buffer.length);
if (text.indexOf ("HTML") > 0 || text.indexOf ("html") > 0)
return true;
return false;
}
// added check for 0x00 eol 17/01/17
while (ptr < buffer.length && buffer[ptr] != 0x0D && buffer[ptr] != 0x00)
line.append ((char) buffer[ptr++]);
return line.toString ();
}
public static boolean isHTML (byte[] buffer)
{
String text = new String (buffer, 0, buffer.length);
if (text.indexOf ("HTML") > 0 || text.indexOf ("html") > 0)
return true;
return false;
}
}

View File

@ -321,6 +321,11 @@ class FileEntry extends CatalogEntry implements ProdosConstants
case FILE_TYPE_APPLETALK:
file = new DefaultAppleFile (name + " (Appletalk file)", buffer);
break;
case FILE_TYPE_GWP:
// using full buffer because the ENDFILE can be 512 for multi-block files
// SimpleText will now terminate at 0x00 (see Fonts.po)
file = new SimpleText (name, buffer);
break;
case FILE_TYPE_AWP:
file = new AppleworksWPFile (name + " (Appleworks Word Processor)", buffer);
break;
@ -342,6 +347,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
case FILE_TYPE_PIC:
file = new OriginalHiResImage (name, exactBuffer, fileType, auxType);
break;
case FILE_TYPE_FONT:
file = new QuickDrawFont (name, exactBuffer, fileType, auxType);
break;
default:
System.out.format ("Unknown file type : %02X%n", fileType);
if (fileType == 0xB3)

View File

@ -9,19 +9,21 @@ public interface ProdosConstants
int FILE_TYPE_ADB = 0x19;
int FILE_TYPE_AWP = 0x1A;
int FILE_TYPE_ASP = 0x1B;
int FILE_TYPE_GWP = 0x50;
int FILE_TYPE_ASM_SOURCE = 0xB0;
int FILE_TYPE_ASM_OBJECT = 0xB1;
int FILE_TYPE_FORKED_FILE = 0xB3; // S16
int FILE_TYPE_PNT = 0xC0;
int FILE_TYPE_PIC = 0xC1;
int FILE_TYPE_FONT = 0xC8;
int FILE_TYPE_ICN = 0xCA;
int FILE_TYPE_APPLETALK = 0xE2;
int FILE_TYPE_INTEGER_BASIC = 0xFA;
int FILE_TYPE_INTEGER_BASIC_VARS = 0xFB;
int FILE_TYPE_APPLESOFT_BASIC = 0xFC;
int FILE_TYPE_APPLESOFT_BASIC_VARS = 0xFD;
int FILE_TYPE_RELOCATABLE = 0xFE;
int FILE_TYPE_SYS = 0xFF;
int FILE_TYPE_APPLETALK = 0xE2;
int TYPE_DIRECTORY_HEADER = 15;
int TYPE_SUBDIRECTORY_HEADER = 14;
@ -33,31 +35,39 @@ public interface ProdosConstants
int TYPE_SEEDLING = 1;
int TYPE_FREE = 0;
String[] fileTypes =
{ "NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", "FOT", "BA3", "DA3",
"WPF", "SOS", "$0D", "$0E", "DIR", "RPD", "RPI", "AFD", "AFM", "AFR", "SCL",
"PFS", "$17", "$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", "TDM",
"$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "8SC", "8OB",
"8IC", "8LD", "P8C", "$2F", "$30", "$31", "$32", "$33", "$34", "$35", "$36",
"$37", "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", "DIC", "OCR",
"FTD", "$43", "$44", "$45", "$46", "$47", "$48", "$49", "$4A", "$4B", "$4C",
"$4D", "$4E", "$4F", "GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN",
"HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", "$60", "$61", "$62",
"$63", "$64", "$65", "$66", "$67", "$68", "$69", "$6A", "BIO", "$6C", "TDR",
"PRE", "HDV", "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", "$78",
"$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", "GES", "GEA", "GEO", "GED",
"GEF", "GEP", "GEI", "GEX", "$88", "GEV", "$8A", "GEC", "GEK", "GEW", "$8E",
"$8F", "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", "$98", "$99",
"$9A", "$9B", "$9C", "$9D", "$9E", "$9F", "WP ", "$A1", "$A2", "$A3", "$A4",
"$A5", "$A6", "$A7", "$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF",
"SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", "NDA", "CDA", "TOL",
"DVR", "LDF", "FST", "$BE", "DOC", "PNT", "PIC", "ANI", "PAL", "$C4", "OOG",
"SCR", "CDV", "FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", "$D0",
"$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", "SND", "$D9", "$DA", "DBM",
"$DC", "DDD", "$DE", "$DF", "LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6",
"$E7", "$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAS", "CMD", "$F1",
"$F2", "$F3", "$F4", "$F5", "$F6", "$F7", "$F8", "OS ", "INT", "IVR", "BAS",
"VAR", "REL", "SYS" };
String[] fileTypes = { //
"NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", //
"FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", //
"RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", //
"$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", //
"TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", //
"$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", //
"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", //
"$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", //
"DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", //
"$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", //
"GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", //
"HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", //
"$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", //
"$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", //
"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", //
"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", //
"GES", "GEA", "GEO", "GED", "GEF", "GEP", "GEI", "GEX", //
"$88", "GEV", "$8A", "GEC", "GEK", "GEW", "$8E", "$8F", //
"$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", //
"$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", //
"WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", //
"$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", //
"SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", //
"NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", //
"PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", //
"FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", //
"$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", //
"SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", //
"LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", //
"$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAS", //
"CMD", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7", //
"$F8", "OS ", "INT", "IVR", "BAS", "VAR", "REL", "SYS" };
int ENTRY_SIZE = 39;
int ENTRIES_PER_BLOCK = 13;

View File

@ -60,19 +60,9 @@ public class HexFormatter
line.append ("\n");
// print offset
for (int temp = i + startingAddress, max = 65536; max > 0; max /= 16)
{
if (temp >= max)
{
line.append (hex[temp / max]);
temp %= max;
}
else
line.append ("0");
}
line.append (String.format ("%05X : ", (startingAddress + i - offset)));
// print hex values
line.append (" : ");
StringBuffer trans = new StringBuffer ();
StringBuffer hexLine = new StringBuffer ();
@ -236,6 +226,13 @@ public class HexFormatter
return hex.toString ();
}
public static String getBitString (byte b)
{
String s = "0000000" + Integer.toBinaryString (b & 0xFF);
s = s.replaceAll ("0", ".");
return s.substring (s.length () - 8);
}
public static char byteValue (byte b)
{
int c = b & 0xFF;