Browse Source

Make: clean up after fonts build. Add font-out.

Steve Thielemann 3 năm trước cách đây
mục cha
commit
27c1cb7821
1 tập tin đã thay đổi với 441 bổ sung0 xóa
  1. 441 0
      font-out.go

+ 441 - 0
font-out.go

@@ -0,0 +1,441 @@
+package main
+
+import (
+	"bufio"
+	"encoding/binary"
+	"flag"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+)
+
+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)
+
+		// f.Read(single) // FontType
+		// FontType := int(single[0])
+		fmt.Printf("Font: %s (type %d)\n", Name, FontType)
+		f.Read(single) // Spacing
+
+		// blocksize := make([]byte, 2)
+		// f.Read(blocksize)
+
+		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("")
+		}
+
+		data := make([]byte, BlockSize)
+		binary.Read(f, binary.LittleEndian, &data)
+	}
+}
+
+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
+}
+
+func text_to_hextext(line string) string {
+	var output string
+	// output = "\""
+	for _, ch := range []byte(line) {
+		// output += fmt.Sprintf("\\x%02x", ch)
+		output += fmt.Sprintf("0x%02x,", ch)
+	}
+	if len(output) > 1 {
+		output = output[:len(output)-1]
+	}
+	// output += "\""
+	return output
+}
+
+func ExtractColor(name string, offsets []uint16, data []byte) {
+	fmt.Printf("Extract Color Font: %s\n", name)
+	var indexes []int
+	var blocks [][][]byte
+	var current [][]byte
+	w := -1
+	h := -1
+	ch := -1
+	var line []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 += string(rune(ch))
+			line = append(line, byte(ch))
+			ch = -1
+		}
+	}
+
+	// offset optimization:
+	var single []int
+	for _, o := range offsets {
+		if o == 65535 {
+			single = append(single, -1)
+			continue
+		}
+		for idx, i := range indexes {
+			if o == uint16(i) {
+				single = append(single, idx)
+				break
+			}
+		}
+	}
+
+	// Handle Names with spaces
+	filename := fmt.Sprintf("%s_font.go", strings.Replace(name, " ", "", -1))
+
+	fp, err := os.Create(filename)
+	if err != nil {
+		panic(err)
+	}
+	fmt.Printf("Writing: %s\n", filename)
+
+	defer fp.Close()
+	writer := bufio.NewWriter(fp)
+
+	// writer.WriteString("package main\n")
+	writer.WriteString("// " + name + "\n\n")
+
+	// Name := strings.ToUpper(name)
+	Name := strings.Replace(name, " ", "", -1)
+
+	writer.WriteString("func Font" + Name + "() ColorFont {\n")
+	var output string
+	output = "  return ColorFont{characters: []int{"
+	for _, s := range single {
+		output += strconv.Itoa(s) + ", "
+	}
+	output = output[:len(output)-2] + "},\n"
+	writer.WriteString(output)
+	writer.Flush()
+
+	output = "    data: [][][]byte{"
+	for _, blk := range blocks {
+		output += "{"
+		if len(blk) == 0 {
+			output += "{},"
+		} else {
+			for _, inner := range blk {
+				// output += text_to_hextext(b) + ","
+				output += "{" + byte_to_text(inner) + "},"
+			}
+			output = output[:len(output)-1]
+		}
+
+		output += "},\n"
+		writer.WriteString(output)
+		output = "      "
+	}
+	writer.WriteString("    }}\n")
+	writer.WriteString("}\n")
+	writer.Flush()
+}
+
+func ExtractBlock(name string, offsets []uint16, data []byte) {
+	fmt.Printf("Extract Block Font: %s\n", name)
+	var indexes []int
+	var blocks [][][]byte
+	var current [][]byte
+	w := -1
+	h := -1
+	ch := -1
+	var line []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 {
+		if o == 65535 {
+			single = append(single, -1)
+			continue
+		}
+		for idx, i := range indexes {
+			if o == uint16(i) {
+				single = append(single, idx)
+				break
+			}
+		}
+	}
+
+	// Handle Names with spaces
+	filename := fmt.Sprintf("%s_font.go", strings.Replace(name, " ", "", -1))
+
+	fp, err := os.Create(filename)
+	if err != nil {
+		panic(err)
+	}
+	fmt.Printf("Writing: %s\n", filename)
+
+	defer fp.Close()
+	writer := bufio.NewWriter(fp)
+
+	// writer.WriteString("package main\n")
+	writer.WriteString("// " + name + "\n\n")
+
+	// Name := strings.ToUpper(name)
+	Name := strings.Replace(name, " ", "", -1)
+
+	writer.WriteString("func Font" + Name + "() BlockFont {\n")
+	var output string
+	output = "  return BlockFont{characters: []int{"
+	for _, s := range single {
+		output += strconv.Itoa(s) + ", "
+	}
+	output = output[:len(output)-2] + "},\n"
+	writer.WriteString(output)
+	writer.Flush()
+
+	output = "    data: [][][]byte{"
+	for _, blk := range blocks {
+		output += "{"
+		if len(blk) == 0 {
+			output += "{},"
+		} else {
+			for _, inner := range blk {
+				output += "{" + byte_to_text(inner) + "},"
+			}
+			output = output[:len(output)-1]
+		}
+
+		output += "},\n"
+
+		// output = output[:len(output)-1]
+		// output += "},\n"
+		writer.WriteString(output)
+		output = "      "
+	}
+	writer.WriteString("    }}\n")
+	writer.WriteString("}\n")
+	writer.Flush()
+}
+
+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)
+
+		// Special case where they are asking for all fonts
+		if len(fonts) == 1 && fonts[0] == "*" {
+			switch FontType {
+			case 1:
+				ExtractBlock(Name, letterOffsets, data)
+			case 2:
+				ExtractColor(Name, letterOffsets, data)
+			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:
+						ExtractBlock(Name, letterOffsets, data)
+					case 2:
+						ExtractColor(Name, letterOffsets, data)
+					default:
+						fmt.Printf("Sorry, I can't handle Font: %s Type %d!\n", Name, FontType)
+					}
+					break
+				}
+			}
+		}
+	}
+}
+
+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.")
+		flag.PrintDefaults()
+		os.Exit(2)
+	}
+
+	if listFonts {
+		ListFonts(fontfile)
+	}
+
+	var fontList []string
+	if len(fonts) > 0 {
+		fontList = strings.Split(fonts, ",")
+	}
+
+	if allFonts {
+		fontList = make([]string, 0)
+		fontList = append(fontList, "*")
+	}
+
+	if len(fontList) > 0 {
+		ExtractFonts(fontfile, fontList)
+	}
+}