123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- package main
- import (
- "bufio"
- "encoding/binary"
- "flag"
- "fmt"
- "os"
- "strconv"
- "strings"
- )
- var Conversion [][2]int
- // copied from tdfont.go, and modified
- func thedraw_to_ansi(c int) int {
- trans := []int{0, 4, 2, 6, 1, 5, 3, 7}
- // 0, 1, 2, 3, 4, 5, 6, 7
- return trans[c]
- }
- func MatchStyle(color byte, look byte) int {
- var match int = 0
- if ((color >> 4) & 0x07) == look {
- // Top
- match |= 1
- }
- if (color & 0x07) == look {
- // Bottom
- match |= 2
- }
- return match
- }
- func PatchColor(color byte, new_color byte, style int) byte {
- var c byte = color
- if style&1 == 1 {
- c = (c & 0x8f) | new_color<<4
- }
- if style&2 == 2 {
- c = (c & 0xf8) | new_color
- }
- return c
- }
- type ColorMap map[[2]int][][2]int
- func Scan(block [][][]byte, find_color int) ColorMap {
- var Targets ColorMap = make(ColorMap, 0)
- // Scan the font looking for the given color FG/BG
- // Covert color code to TheDraw Color
- actual := byte(thedraw_to_ansi(find_color))
- for charIndex := range block {
- for lineIndex := range block[charIndex] {
- var found bool = false
- var patches [][2]int = make([][2]int, 0)
- for offset := 1; offset < len(block[charIndex][lineIndex]); offset += 2 {
- color := block[charIndex][lineIndex][offset]
- style := MatchStyle(color, actual)
- if style != 0 {
- // log.Printf("color: %x actual %x style: %d\n", color, actual, style)
- patches = append(patches, [2]int{offset, style})
- found = true
- }
- }
- if found {
- pos := [2]int{charIndex, lineIndex}
- Targets[pos] = make([][2]int, len(patches))
- for i := range patches {
- Targets[pos][i] = patches[i]
- }
- // Targets[pos] = patches
- }
- }
- }
- return Targets
- }
- func Modify(block [][][]byte, new_color int, Targets ColorMap) {
- // Covert color code to TheDraw Color
- actual := byte(thedraw_to_ansi(new_color))
- for pos, patch := range Targets {
- for _, p := range patch {
- block[pos[0]][pos[1]][p[0]] = PatchColor(block[pos[0]][pos[1]][p[0]], actual, p[1])
- }
- }
- }
- 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
- 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
- }
- 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 := bufio.NewWriter(os.Stdout)
- // writer.WriteString("package main\n")
- writer.WriteString("// " + name + "\n\n")
- // Name := strings.ToUpper(name)
- Name := strings.Replace(name, " ", "", -1)
- writer.WriteString("func Font" + Name + "() door.ColorFont {\n")
- var output string
- output = " return door.ColorFont{Characters: []int{"
- for _, s := range single {
- output += strconv.Itoa(s) + ", "
- }
- output = output[:len(output)-2] + "},\n"
- writer.WriteString(output)
- writer.Flush()
- if len(Conversion) > 0 {
- // Color Convert time!
- var Maps []map[[2]int][][2]int = make([]map[[2]int][][2]int, len(Conversion))
- for idx, codes := range Conversion {
- Maps[idx] = Scan(blocks, codes[0])
- }
- for idx, codes := range Conversion {
- Modify(blocks, codes[1], Maps[idx])
- }
- }
- 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
- 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
- }
- 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 := bufio.NewWriter(os.Stdout)
- // Should this output routine be part of the BlockFont?
- // I think so!
- // writer.WriteString("package main\n")
- writer.WriteString("// " + name + "\n\n")
- // Name := strings.ToUpper(name)
- Name := strings.Replace(name, " ", "", -1)
- writer.WriteString("func Font" + Name + "() door.BlockFont {\n")
- var output string
- output = " return door.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
- }
- }
- }
- }
- }
- // Created so that multiple inputs can be accecpted
- type arrayFlags []string
- func (i *arrayFlags) String() string {
- // change this, this is just can example to satisfy the interface
- result := ""
- for _, str := range *i {
- if result != "" {
- result += ", "
- }
- result += str
- }
- return result
- }
- func (i *arrayFlags) Set(value string) error {
- *i = append(*i, strings.TrimSpace(value))
- return nil
- }
- func ParseColorConvert(convert arrayFlags) {
- Conversion = make([][2]int, 0)
- if len(convert) > 0 {
- // Something to do
- for _, color := range convert {
- split := strings.Split(color, ",")
- v1, _ := strconv.Atoi(split[0])
- v2, _ := strconv.Atoi(split[1])
- Conversion = append(Conversion, [2]int{v1, v2})
- }
- }
- }
- func main() {
- var fonts string
- var defaultPackage string = "main"
- var listFonts bool
- var allFonts bool
- var convert arrayFlags
- 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.Var(&convert, "c", "Convert Color to Color n,n")
- flag.Parse()
- ParseColorConvert(convert)
- // fmt.Printf("Convert: %#v\n", convert)
- // fmt.Printf("Conversion: %#v\n", Conversion)
- if flag.NArg() == 0 {
- fmt.Println("Font-Out - A TDF (TheDraw Font) file processor.")
- fmt.Println("No TDF filenames given.")
- flag.PrintDefaults()
- os.Exit(2)
- }
- if !listFonts {
- fmt.Printf("package %s\n\n", defaultPackage)
- fmt.Println("import (")
- fmt.Println(" \"red-green/door\"")
- fmt.Println(")")
- fmt.Println("")
- } else {
- fmt.Println("Font-Out - A TDF (TheDraw Font) file processor.")
- }
- var fontList []string
- if len(fonts) > 0 {
- fontList = strings.Split(fonts, ",")
- }
- if allFonts {
- fontList = make([]string, 0)
- fontList = append(fontList, "*")
- }
- if !listFonts && len(fontList) == 0 {
- fmt.Println("Default to -l (List Fonts)")
- listFonts = true
- }
- for _, fontfile := range flag.Args() {
- if listFonts {
- ListFonts(fontfile)
- } else {
- if len(fontList) > 0 {
- ExtractFonts(fontfile, fontList)
- }
- }
- }
- }
|