Browse Source

Updated: tdfont is in the door package.

Steve Thielemann 3 năm trước cách đây
mục cha
commit
ae6e2dd118
9 tập tin đã thay đổi với 608 bổ sung142 xóa
  1. 8 4
      Makefile
  2. 1 1
      door/input.go
  3. 9 9
      door/tdfont.go
  4. 21 115
      font-out.go
  5. 553 0
      font-show/font-show.go
  6. 7 0
      font-show/go.mod
  7. 0 2
      testdoor/go.mod
  8. 0 2
      testdoor/go.sum
  9. 9 9
      testdoor/testdoor.go

+ 8 - 4
Makefile

@@ -4,16 +4,15 @@ all: door32 testdoor/testdoor testdoor/art.go space-ace/space-ace
 
 font-out: font-out.go
 	go build font-out.go
+	go build font-show.go door/tdfont.go
 
 
 door32: door32.c
 	gcc -o door32 door32.c
 
 testdoor/fonts.go: font-out
-	echo "package main" > testdoor/fonts.go
-	./font-out -f "Amazon Cyan,Medieval,Anarchy Blue" -tdf TDFONTS.TDF 
-	./font-out -f Unchained,Asylum,ArmageonRed,BrainDmgBlu -tdf TDFONTS2.TDF
-	./font-out -f Boner,Descent,Remorse,Dungeon -tdf TDFONTS9.TDF
+	echo "package main\n\nimport \"red-green/door\"\n\n" > testdoor/fonts.go
+	./font-out -f "Amazon Cyan,Medieval,Anarchy Blue,Unchained,Asylum,ArmageonRed,BrainDmgBlu,Boner,Descent,Remorse,Dungeon" TDFONTS.TDF TDFONTS2.TDF TDFONTS9.TDF
 	cat *_font.go >> testdoor/fonts.go    
 	rm *_font.go
 
@@ -29,3 +28,8 @@ testdoor/testdoor: testdoor/art.go testdoor/fonts.go testdoor/*.go door/*.go
 space-ace/space-ace: space-ace/*.go door/*.go space-ace/space.go
 	cd space-ace; go build
 
+
+#	./font-out -f "Amazon Cyan,Medieval,Anarchy Blue" TDFONTS.TDF 
+#	./font-out -f Unchained,Asylum,ArmageonRed,BrainDmgBlu TDFONTS2.TDF
+#	./font-out -f Boner,Descent,Remorse,Dungeon TDFONTS9.TDF
+

+ 1 - 1
door/input.go

@@ -48,7 +48,7 @@ func isSet(fdSetPtr *syscall.FdSet, fd int) bool {
 */
 
 func clearAll(fdSetPtr *syscall.FdSet) {
-	for index, _ := range (*fdSetPtr).Bits {
+	for index := range (*fdSetPtr).Bits {
 		(*fdSetPtr).Bits[index] = 0
 	}
 }

+ 9 - 9
testdoor/tdfont.go → door/tdfont.go

@@ -1,4 +1,4 @@
-package main
+package door
 
 import (
 	"bytes"
@@ -8,8 +8,8 @@ import (
 )
 
 type BlockFont struct {
-	characters []int
-	data       [][][]byte
+	Characters []int
+	Data       [][][]byte
 }
 
 /*
@@ -63,12 +63,12 @@ func (bf *BlockFont) GetCharacter(c int) [][]byte {
 	// 33-126 are the possible characters.
 	if c >= 33 && c <= 126 {
 		c -= 33
-		idx := bf.characters[c]
+		idx := bf.Characters[c]
 		if idx == -1 {
 			// This character is not supported by this font.
 			return result
 		}
-		result = bf.data[bf.characters[c]]
+		result = bf.Data[bf.Characters[c]]
 		// fmt.Println("normalizeCharBlock")
 		normalizeBlock(&result)
 		// fmt.Println("normalizeChar done")
@@ -148,8 +148,8 @@ func (bf *BlockFont) Output(input string) ([][]byte, int) {
 }
 
 type ColorFont struct {
-	characters []int
-	data       [][][]byte
+	Characters []int
+	Data       [][][]byte
 }
 
 /*
@@ -208,11 +208,11 @@ func (cf *ColorFont) GetCharacter(c int) ([][]byte, int) {
 
 	if c >= 33 && c <= 126 {
 		c -= 33
-		idx := cf.characters[c]
+		idx := cf.Characters[c]
 		if idx == -1 {
 			return result, 0
 		}
-		result = cf.data[cf.characters[c]]
+		result = cf.Data[cf.Characters[c]]
 		// fmt.Println("Character:")
 		// BytesArrayHexed(&result)
 		// fmt.Println("normalizing...")

+ 21 - 115
font-out.go

@@ -10,9 +10,6 @@ import (
 	"strings"
 )
 
-// TODO:
-// Add ability to load font into struct and render
-
 func ListFonts(filename string) {
 
 	f, err := os.Open(filename)
@@ -101,10 +98,6 @@ func ExtractColor(name string, offsets []uint16, data []byte) {
 	var indexes []int
 	var blocks [][][]byte
 	var current [][]byte
-	// w := -1
-	// h := -1
-	// ch := -1
-	// color := -1
 	var line []byte
 
 	pos := 0
@@ -116,7 +109,6 @@ func ExtractColor(name string, offsets []uint16, data []byte) {
 		// We don't use these.
 		// w = data[pos]
 		// h = data[pos+1]
-
 		pos += 2
 
 		// process this character
@@ -148,52 +140,6 @@ func ExtractColor(name string, offsets []uint16, data []byte) {
 		}
 	}
 
-	// the old, sloppy way
-	/*
-		for idx, b := range data {
-			if w == -1 {
-				indexes = append(indexes, idx)
-				current = make([][]byte, 0)
-				line = make([]byte, 0)
-				w = int(b)
-				continue
-			}
-			if h == -1 {
-				h = int(b)
-				continue
-			}
-			if ch == -1 {
-				ch = int(b)
-				if ch == 0x0d {
-					ch = -1
-					current = append(current, line)
-					line = make([]byte, 0)
-					continue
-				}
-				if ch == 0 {
-					current = append(current, line)
-					blocks = append(blocks, current)
-					current = make([][]byte, 0)
-					line = make([]byte, 0)
-					w = -1
-					h = -1
-					ch = -1
-					continue
-				}
-				if ch == 0x26 {
-					// & descender mark
-					ch = -1
-					continue
-				}
-			} else {
-				color = int(b)
-				line = append(line, byte(ch))
-				line = append(line, byte(color))
-				ch = -1
-			}
-		}
-	*/
-
 	// offset optimization:
 	var single []int
 	for _, o := range offsets {
@@ -227,9 +173,9 @@ func ExtractColor(name string, offsets []uint16, data []byte) {
 	// Name := strings.ToUpper(name)
 	Name := strings.Replace(name, " ", "", -1)
 
-	writer.WriteString("func Font" + Name + "() ColorFont {\n")
+	writer.WriteString("func Font" + Name + "() door.ColorFont {\n")
 	var output string
-	output = "  return ColorFont{characters: []int{"
+	output = "  return door.ColorFont{Characters: []int{"
 	for _, s := range single {
 		output += strconv.Itoa(s) + ", "
 	}
@@ -237,7 +183,7 @@ func ExtractColor(name string, offsets []uint16, data []byte) {
 	writer.WriteString(output)
 	writer.Flush()
 
-	output = "    data: [][][]byte{"
+	output = "    Data: [][][]byte{"
 	for _, blk := range blocks {
 		output += "{"
 		if len(blk) == 0 {
@@ -264,9 +210,6 @@ func ExtractBlock(name string, offsets []uint16, data []byte) {
 	var indexes []int
 	var blocks [][][]byte
 	var current [][]byte
-	// w := -1
-	// h := -1
-	// ch := -1
 	var line []byte
 
 	pos := 0
@@ -306,48 +249,6 @@ func ExtractBlock(name string, offsets []uint16, data []byte) {
 		}
 	}
 
-	/*
-		for idx, b := range data {
-			if w == -1 {
-				indexes = append(indexes, idx)
-				current = make([][]byte, 0)
-				line = make([]byte, 0)
-				w = int(b)
-				continue
-			}
-			if h == -1 {
-				h = int(b)
-				continue
-			}
-			if ch == -1 {
-				ch = int(b)
-				if ch == 0x0d {
-					ch = -1
-					current = append(current, line)
-					line = make([]byte, 0)
-					continue
-				}
-				if ch == 0 {
-					current = append(current, line)
-					blocks = append(blocks, current)
-					current = make([][]byte, 0)
-					line = make([]byte, 0)
-					w = -1
-					h = -1
-					ch = -1
-					continue
-				}
-				if ch == 0x26 {
-					// & descender mark
-					ch = -1
-					continue
-				}
-				line = append(line, byte(ch))
-				ch = -1
-			}
-		}
-	*/
-
 	// offset optimization:
 	var single []int
 	for _, o := range offsets {
@@ -384,9 +285,9 @@ func ExtractBlock(name string, offsets []uint16, data []byte) {
 	// Name := strings.ToUpper(name)
 	Name := strings.Replace(name, " ", "", -1)
 
-	writer.WriteString("func Font" + Name + "() BlockFont {\n")
+	writer.WriteString("func Font" + Name + "() door.BlockFont {\n")
 	var output string
-	output = "  return BlockFont{characters: []int{"
+	output = "  return door.BlockFont{Characters: []int{"
 	for _, s := range single {
 		output += strconv.Itoa(s) + ", "
 	}
@@ -394,7 +295,7 @@ func ExtractBlock(name string, offsets []uint16, data []byte) {
 	writer.WriteString(output)
 	writer.Flush()
 
-	output = "    data: [][][]byte{"
+	output = "    Data: [][][]byte{"
 	for _, blk := range blocks {
 		output += "{"
 		if len(blk) == 0 {
@@ -495,29 +396,23 @@ func ExtractFonts(filename string, fonts []string) {
 
 func main() {
 	fmt.Println("Font-Out - A TDF (TheDraw Font) file processor.")
-	var fontfile string
 	var fonts string
 	var defaultPackage string = "main"
 	var listFonts bool
 	var allFonts bool
 
-	flag.StringVar(&fontfile, "tdf", "", "TheDraw Font File")
 	flag.StringVar(&fonts, "f", "", "Font(s) to extract")
 	flag.BoolVar(&allFonts, "a", false, "Extract All Fonts")
 	flag.StringVar(&defaultPackage, "p", "main", "Package name to use")
 	flag.BoolVar(&listFonts, "l", false, "List Fonts")
 	flag.Parse()
 
-	if len(fontfile) == 0 {
-		fmt.Println("I need a TDF filename.")
+	if flag.NArg() == 0 {
+		fmt.Println("No TDF filenames given.")
 		flag.PrintDefaults()
 		os.Exit(2)
 	}
 
-	if listFonts {
-		ListFonts(fontfile)
-	}
-
 	var fontList []string
 	if len(fonts) > 0 {
 		fontList = strings.Split(fonts, ",")
@@ -528,7 +423,18 @@ func main() {
 		fontList = append(fontList, "*")
 	}
 
-	if len(fontList) > 0 {
-		ExtractFonts(fontfile, fontList)
+	if !listFonts && len(fontList) == 0 {
+		fmt.Println("Default to -l (List Fonts)")
+		listFonts = true
+	}
+
+	for _, fontfile := range flag.Args() {
+		if listFonts {
+			ListFonts(fontfile)
+		}
+
+		if len(fontList) > 0 {
+			ExtractFonts(fontfile, fontList)
+		}
 	}
 }

+ 553 - 0
font-show/font-show.go

@@ -0,0 +1,553 @@
+package main
+
+import (
+	"encoding/binary"
+	"flag"
+	"fmt"
+	"os"
+	"red-green/door"
+	"regexp"
+	"strings"
+)
+
+// Given a TheDrawFont file, display the fonts contained within.
+func ListFonts(filename string) {
+	f, err := os.Open(filename)
+	if err != nil {
+		fmt.Printf("Open(%s): %s\n", filename, err)
+		panic(err)
+	}
+	defer f.Close()
+	tdfonts := make([]byte, 20)
+	f.Read(tdfonts)
+	for true {
+		fontdef := make([]byte, 4)
+		read, _ := f.Read(fontdef)
+		if read != 4 {
+			fmt.Println("*END*")
+			break
+		}
+		fontname := make([]byte, 13)
+		f.Read(fontname)
+		Name := strings.Trim(string(fontname[1:]), "\x00")
+		// fmt.Printf("Font: %s\n", Name)
+		f.Read(fontdef)
+		single := make([]byte, 1)
+
+		var FontType int8
+		binary.Read(f, binary.LittleEndian, &FontType)
+
+		fmt.Printf("Font: %s (type %d)\n", Name, FontType)
+		f.Read(single) // Spacing
+
+		var BlockSize int16
+		binary.Read(f, binary.LittleEndian, &BlockSize)
+		// fmt.Printf("Size: %d / %x\n", BlockSize, BlockSize)
+
+		letterOffsets := make([]int16, 94)
+		binary.Read(f, binary.LittleEndian, &letterOffsets)
+
+		if false {
+			for idx, i := range letterOffsets {
+				fmt.Printf(" %04X", i)
+				if (idx+1)%10 == 0 {
+					fmt.Println("")
+				}
+			}
+			fmt.Println("")
+		}
+
+		// Or possibly, seek past the character data
+		data := make([]byte, BlockSize)
+		binary.Read(f, binary.LittleEndian, &data)
+	}
+}
+
+// Properly convert bytes to string
+// This is easy to get wrong, and string([]byte) might not work.
+// (Work right, that is.)
+func byte_to_text(line []byte) string {
+	var output string
+
+	for _, ch := range line {
+		output += fmt.Sprintf("0x%02x,", ch)
+	}
+	if len(output) > 0 {
+		output = output[:len(output)-1]
+	}
+	return output
+}
+
+// Convert string to hex values for initializing []byte{}
+func text_to_hextext(line string) string {
+	var output string
+	// output = "\""
+	for _, ch := range []byte(line) {
+		output += fmt.Sprintf("0x%02x,", ch)
+	}
+	if len(output) > 1 {
+		output = output[:len(output)-1]
+	}
+	// output += "\""
+	return output
+}
+
+// Attempt to fix broken fonts.
+// This verifies that the character offsets are proceeded
+// by a null character.
+func FontFixup(offsets []uint16, data *[]byte) bool {
+	fixed := false
+	for _, offset := range offsets {
+		if offset == 65535 {
+			continue
+		}
+		if offset == 0 {
+			continue
+		}
+		if (*data)[offset-1] != 0 {
+			(*data)[offset-1] = 0
+			fixed = true
+		}
+	}
+	return fixed
+}
+
+func ExtractColor(name string, offsets []uint16, data []byte) (Font door.ColorFont) {
+
+	defer func() {
+		if r := recover(); r != nil {
+			// Ok, this failed
+			Font = door.ColorFont{}
+		}
+	}()
+
+	var indexes []int
+	var blocks [][][]byte
+	var current [][]byte
+	var line []byte
+
+	pos := 0
+	for pos < len(data) {
+		indexes = append(indexes, pos)
+		current = make([][]byte, 0)
+		line = make([]byte, 0)
+
+		// We don't use these.
+		// w = data[pos]
+		// h = data[pos+1]
+
+		pos += 2
+
+		// process this character
+		for pos < len(data) {
+			ch := data[pos]
+			pos++
+			if ch == 0x00 {
+				// end of character
+				current = append(current, line)
+				blocks = append(blocks, current)
+				current = make([][]byte, 0)
+				line = make([]byte, 0)
+				break
+			}
+			if ch == 0x0d {
+				// end of this character line
+				current = append(current, line)
+				line = make([]byte, 0)
+				continue
+			}
+			if ch == 0x26 {
+				// & descender mark
+				continue
+			}
+			line = append(line, ch)
+			color := data[pos]
+			pos++
+			line = append(line, color)
+		}
+
+	}
+
+	// offset optimization:
+	var single []int
+	for _, o := range offsets {
+		if o == 65535 {
+			single = append(single, -1)
+			continue
+		}
+		found := false
+		for idx, i := range indexes {
+			if o == uint16(i) {
+				single = append(single, idx)
+				found = true
+				break
+			}
+		}
+		if !found {
+			panic(fmt.Sprintf("Unable to locate index %d / %x (font appears corrupted)", o, o))
+		}
+	}
+
+	font := door.ColorFont{}
+	font.Characters = single
+	font.Data = blocks
+	return font
+}
+
+func ExtractBlock(name string, offsets []uint16, data []byte) (Font door.BlockFont) {
+
+	defer func() {
+		if r := recover(); r != nil {
+			// Ok, this failed
+			Font = door.BlockFont{}
+		}
+	}()
+
+	// fmt.Printf("Extract Block Font: %s\n", name)
+	var indexes []int
+	var blocks [][][]byte
+	var current [][]byte
+	var line []byte
+
+	pos := 0
+	for pos < len(data) {
+		indexes = append(indexes, pos)
+		current = make([][]byte, 0)
+		line = make([]byte, 0)
+
+		// We don't use these
+		// w = data[pos]
+		// h = data[pos+1]
+		pos += 2
+
+		// process this character
+		for pos < len(data) {
+			ch := data[pos]
+			pos++
+
+			if ch == 0x00 {
+				// end of character
+				current = append(current, line)
+				blocks = append(blocks, current)
+				current = make([][]byte, 0)
+				line = make([]byte, 0)
+				break
+			}
+			if ch == 0x0d {
+				// end of this character line
+				current = append(current, line)
+				line = make([]byte, 0)
+				continue
+			}
+			if ch == 0x26 {
+				// & descender mark
+				continue
+			}
+			line = append(line, ch)
+		}
+	}
+
+	// offset optimization:
+	var single []int
+	for _, o := range offsets {
+		if o == 65535 {
+			single = append(single, -1)
+			continue
+		}
+		found := false
+		for idx, i := range indexes {
+			if o == uint16(i) {
+				single = append(single, idx)
+				found = true
+				break
+			}
+		}
+		if !found {
+			panic(fmt.Sprintf("Unable to locate index %d / %x (font appears corrupted)", o, o))
+		}
+	}
+
+	font := door.BlockFont{}
+	font.Characters = single
+	font.Data = blocks
+	return font
+}
+
+func Show(parts [][]byte) {
+	reset := "\x1b[0m"
+
+	if len(parts) > 0 {
+		for _, line := range parts {
+			fmt.Printf("%s%s\n", door.CP437_to_Unicode(string(line)), reset)
+		}
+		fmt.Println("")
+	}
+}
+
+// Examine character indexes, are there lower case letter? are they unique?
+// What are the available characters in this font?
+func FontInfo(characters []int) (lower bool, lowerUnique bool, available string) {
+	// Does it have lowercase?
+	// Is lowercase unique?
+	// Available characters in font
+
+	// 33 -126
+	lower = characters[int(rune('a')-33)] != -1
+	lowerUnique = characters[int(rune('A')-33)] != characters[int(rune('a')-33)]
+
+	for idx, offset := range characters {
+		char := idx + 33
+		if offset != -1 {
+			available += string(char)
+		}
+	}
+	return
+}
+
+func ShowBlockFont(name string, bf *door.BlockFont) {
+	low, uniq, avail := FontInfo(bf.Characters)
+	fmt.Printf("Font: %s (LowerCase %t, Unique Lower %t, [%s]\n", name, low, uniq, avail)
+
+	output, _ := bf.Output("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+	Show(output)
+
+	if low && uniq {
+		output, _ := bf.Output("abcdefghijklmnopqrstuvwxyz")
+		Show(output)
+	}
+
+	leftovers := avail
+	reg, _ := regexp.Compile("[a-zA-Z]+")
+	left := reg.ReplaceAllString(leftovers, "")
+	// output, _ = bf.Output("abcdef")
+	// Show(output)
+	if len(left) > 0 {
+		output, _ = bf.Output(left)
+		Show(output)
+	}
+}
+
+func ShowColorFont(name string, cf *door.ColorFont) {
+	low, uniq, avail := FontInfo(cf.Characters)
+	fmt.Printf("Font: %s (LowerCase %t, Unique Lower %t, [%s]\n", name, low, uniq, avail)
+
+	// fmt.Printf("Font: %s\n", name)
+	output, _ := cf.Output("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+	Show(output)
+
+	if low && uniq {
+		output, _ := cf.Output("abcdefghijklmnopqrstuvwxyz")
+		Show(output)
+	}
+
+	leftovers := avail
+	reg, _ := regexp.Compile("[a-zA-Z]+")
+	left := reg.ReplaceAllString(leftovers, "")
+	// output, _ = bf.Output("abcdef")
+	// Show(output)
+	if len(left) > 0 {
+		output, _ = cf.Output(left)
+		Show(output)
+	}
+}
+
+// Example using FontOutput interface
+/*
+func ShowFont(name string, f FontOutput) {
+	var low, uniq bool
+	var avail string
+
+	v, ok := f.(BlockFont)
+	if ok {
+		low, uniq, avail := FontInfo(v.characters)
+	}
+
+	v, ok = f.(ColorFont)
+	if ok {
+		low, uniq, avail := FontInfo(v.characters)
+	}
+
+	// low, uniq, avail := FontInfo((*f).characters)
+	fmt.Printf("Font: %s (LowerCase %t, Unique Lower %t, [%s]\n", name, low, uniq, avail)
+
+	// fmt.Printf("Font: %s\n", name)
+	output, _ := f.Output("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+	Show(output)
+
+	if low && uniq {
+		output, _ = f.Output("abcdefghijklmnopqrstuvwxyz")
+		Show(output)
+	}
+
+	leftovers := avail
+	reg, _ := regexp.Compile("[a-zA-Z]+")
+	left := reg.ReplaceAllString(leftovers, "")
+	//  output, _ = bf.Output("abcdef")
+	// Show(output)
+
+	// left := "0123456789!@#$%^&*()-=_+[]{}~"
+
+	if len(left) > 0 {
+		output, _ = f.Output(left)
+		Show(output)
+	}
+}
+*/
+
+func ExtractFonts(filename string, fonts []string) {
+	f, err := os.Open(filename)
+	if err != nil {
+		fmt.Printf("Open(%s): %s\n", filename, err)
+		panic(err)
+	}
+	defer f.Close()
+	tdfonts := make([]byte, 20)
+	f.Read(tdfonts)
+	for true {
+		fontdef := make([]byte, 4)
+		read, _ := f.Read(fontdef)
+		if read != 4 {
+			break
+		}
+		fontname := make([]byte, 13)
+		f.Read(fontname)
+		Name := strings.Trim(string(fontname[1:]), "\x00")
+		// fmt.Printf("Font: %s\n", Name)
+		f.Read(fontdef)
+		single := make([]byte, 1)
+
+		var FontType int8
+		binary.Read(f, binary.LittleEndian, &FontType)
+
+		// fmt.Printf("Font: %s (type %d)\n", Name, FontType)
+		f.Read(single) // Spacing
+
+		var BlockSize int16
+		binary.Read(f, binary.LittleEndian, &BlockSize)
+
+		letterOffsets := make([]uint16, 94)
+		binary.Read(f, binary.LittleEndian, &letterOffsets)
+
+		if false {
+			for idx, i := range letterOffsets {
+				fmt.Printf(" %04X", i)
+				if (idx+1)%10 == 0 {
+					fmt.Println("")
+				}
+			}
+			fmt.Println("")
+		}
+
+		data := make([]byte, BlockSize)
+		binary.Read(f, binary.LittleEndian, &data)
+
+		// The problem isn't that the offsets are > BlockSize
+		// Detect "truncated" fonts...
+		broken := false
+		for idx, i := range letterOffsets {
+			if i != 65535 {
+				if i >= uint16(BlockSize) {
+					broken = true
+					// Mark character offset as not used
+					letterOffsets[idx] = 65535
+					// fmt.Printf("offset %d / %x is out of range %d / %x\n", i, i, BlockSize, BlockSize)
+				}
+			}
+		}
+
+		if broken {
+			fmt.Println("FONT is corrupted/truncated.  FIX attempted.")
+		}
+
+		if FontFixup(letterOffsets, &data) {
+			fmt.Printf("Attempting to *FIX* Font %s\n", Name)
+		}
+
+		// Special case where they are asking for all fonts
+		if len(fonts) == 1 && fonts[0] == "*" {
+
+			switch FontType {
+			case 1:
+				bf := ExtractBlock(Name, letterOffsets, data)
+				if len(bf.Characters) == 0 {
+					fmt.Printf("%s : BLOCK FONT FAIL\n", Name)
+				} else {
+					// ShowFont(Name, &bf)
+					ShowBlockFont(Name, &bf)
+				}
+			case 2:
+				cf := ExtractColor(Name, letterOffsets, data)
+				if len(cf.Characters) == 0 {
+					fmt.Printf("%s : COLOR FONT FAIL\n", Name)
+				} else {
+					// ShowFont(Name, &cf)
+					ShowColorFont(Name, &cf)
+				}
+			default:
+				fmt.Printf("Sorry, I can't handle Font: %s Type %d!\n", Name, FontType)
+			}
+		} else {
+			for _, f := range fonts {
+				if Name == f {
+					switch FontType {
+					case 1:
+						bf := ExtractBlock(Name, letterOffsets, data)
+						if len(bf.Characters) == 0 {
+							fmt.Printf("%s : BLOCK FONT FAIL\n", Name)
+						} else {
+							ShowBlockFont(Name, &bf)
+						}
+					case 2:
+						cf := ExtractColor(Name, letterOffsets, data)
+						if len(cf.Characters) == 0 {
+							fmt.Printf("%s : COLOR FONT FAIL\n", Name)
+						} else {
+							ShowColorFont(Name, &cf)
+						}
+					default:
+						fmt.Printf("Sorry, I can't handle Font: %s Type %d!\n", Name, FontType)
+					}
+					break
+				}
+			}
+		}
+	}
+}
+
+func main() {
+	fmt.Println("Font-Show - A TDF (TheDraw Font) Viewer.")
+	var fonts string
+	var listFonts bool
+	var allFonts bool
+
+	flag.StringVar(&fonts, "f", "", "Font(s) to show")
+	flag.BoolVar(&allFonts, "a", false, "Show All Fonts")
+	flag.BoolVar(&listFonts, "l", false, "List Fonts")
+	flag.Parse()
+
+	if flag.NArg() == 0 {
+		fmt.Println("I need a TDF filename.")
+		flag.PrintDefaults()
+		os.Exit(2)
+	}
+
+	var fontList []string
+	if len(fonts) > 0 {
+		fontList = strings.Split(fonts, ",")
+	}
+
+	if allFonts {
+		fontList = make([]string, 0)
+		fontList = append(fontList, "*")
+	}
+
+	for _, fontfile := range flag.Args() {
+		if listFonts {
+			ListFonts(fontfile)
+		}
+
+		if len(fontList) > 0 {
+			ExtractFonts(fontfile, fontList)
+		}
+	}
+}

+ 7 - 0
font-show/go.mod

@@ -0,0 +1,7 @@
+module red-green/show-font
+
+go 1.17
+
+replace red-green/door => ../door
+
+require red-green/door v0.0.0-00010101000000-000000000000

+ 0 - 2
testdoor/go.mod

@@ -5,5 +5,3 @@ go 1.17
 replace red-green/door => ../door
 
 require red-green/door v0.0.0-00010101000000-000000000000
-
-require golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect

+ 0 - 2
testdoor/go.sum

@@ -1,2 +0,0 @@
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

+ 9 - 9
testdoor/testdoor.go

@@ -122,7 +122,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(fmt.Sprintf("%s%s%s", centering, CP437Bytes_to_Unicode(o), door.Reset) + door.CRNL)
+				d.Write(fmt.Sprintf("%s%s%s", centering, door.CP437_to_Unicode(string(o)), door.Reset) + door.CRNL)
 			} else {
 				d.Write(fmt.Sprintf("%s%s%s", centering, string(o), door.Reset) + door.CRNL)
 			}
@@ -141,7 +141,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -160,7 +160,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -180,7 +180,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -199,7 +199,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -214,7 +214,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -234,7 +234,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -252,7 +252,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}
@@ -270,7 +270,7 @@ func font_demo(d *door.Door) {
 
 		for _, o := range output {
 			if door.Unicode {
-				d.Write(centering + CP437Bytes_to_Unicode(o) + door.Reset + door.CRNL)
+				d.Write(centering + door.CP437_to_Unicode(string(o)) + door.Reset + door.CRNL)
 			} else {
 				d.Write(centering + string(o) + door.Reset + door.CRNL)
 			}