2020-05-16 23:58:40 +02:00
#!/usr/bin/env python3
2013-11-27 22:35:11 +01:00
"""
C64 Character Set to TrueType Converter
2020-09-05 20:42:52 +02:00
Version 1.4
2013-11-27 22:35:11 +01:00
2020-05-16 23:58:40 +02:00
Copyright ( c ) 2013 - 2020 , A . T . Brask ( atbrask [ at ] gmail [ dot ] com )
2013-11-27 22:35:11 +01:00
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
"""
import argparse
from datetime import date
import getpass
import math
import time
2016-10-19 00:15:42 +02:00
import array
2013-11-27 22:35:11 +01:00
import os
from fontTools . ttLib import TTFont , newTable
from fontTools . ttLib . tables import ttProgram
2014-03-25 19:53:00 +01:00
from fontTools . ttLib . tables . _c_m_a_p import cmap_format_4 , cmap_format_0
2013-11-27 22:35:11 +01:00
from fontTools . ttLib . tables . _h_e_a_d import mac_epoch_diff
2016-10-19 00:15:42 +02:00
from fontTools . ttLib . tables . _g_l_y_f import Glyph , GlyphCoordinates
2013-11-27 22:35:11 +01:00
from fontTools . ttLib . tables . O_S_2f_2 import Panose
from fontTools . ttLib . tables . _n_a_m_e import NameRecord
# DATA SECTION
# Map from a subset of C64 PETSCII to ASCII as well as a few Unicode points.
# Not all PETSCII characters can be mapped into Unicode.
# Each tuple is [C64 character generator index, AGL name, [unicode codes]]
# The rest of the C64 glyphs can be included at 0xEE00...0xEFFF by using the
# command line argument --add-all
# The chars are in the C64 character generator order.
CHAR_HI = [ [ 0 , " at " , [ 0x40 ] ] ,
[ 1 , " A " , [ 0x41 ] ] ,
[ 2 , " B " , [ 0x42 ] ] ,
[ 3 , " C " , [ 0x43 ] ] ,
[ 4 , " D " , [ 0x44 ] ] ,
[ 5 , " E " , [ 0x45 ] ] ,
[ 6 , " F " , [ 0x46 ] ] ,
[ 7 , " G " , [ 0x47 ] ] ,
[ 8 , " H " , [ 0x48 ] ] ,
[ 9 , " I " , [ 0x49 ] ] ,
[ 10 , " J " , [ 0x4a ] ] ,
[ 11 , " K " , [ 0x4b ] ] ,
[ 12 , " L " , [ 0x4c ] ] ,
[ 13 , " M " , [ 0x4d ] ] ,
[ 14 , " N " , [ 0x4e ] ] ,
[ 15 , " O " , [ 0x4f ] ] ,
[ 16 , " P " , [ 0x50 ] ] ,
[ 17 , " Q " , [ 0x51 ] ] ,
[ 18 , " R " , [ 0x52 ] ] ,
[ 19 , " S " , [ 0x53 ] ] ,
[ 20 , " T " , [ 0x54 ] ] ,
[ 21 , " U " , [ 0x55 ] ] ,
[ 22 , " V " , [ 0x56 ] ] ,
[ 23 , " W " , [ 0x57 ] ] ,
[ 24 , " X " , [ 0x58 ] ] ,
[ 25 , " Y " , [ 0x59 ] ] ,
[ 26 , " Z " , [ 0x5a ] ] ,
[ 27 , " bracketleft " , [ 0x5b ] ] ,
[ 28 , " sterling " , [ 0xa3 ] ] ,
[ 29 , " bracketright " , [ 0x5d ] ] ,
[ 30 , " arrowup " , [ 0x2191 ] ] ,
[ 31 , " arrowleft " , [ 0x2190 ] ] ,
[ 32 , " space " , [ 0x20 , 0xa0 ] ] ,
[ 33 , " exclam " , [ 0x21 ] ] ,
[ 34 , " quotedblright " , [ 0x22 , 0x201c , 0x201d ] ] ,
[ 35 , " numbersign " , [ 0x23 ] ] ,
[ 36 , " dollar " , [ 0x24 ] ] ,
[ 37 , " percent " , [ 0x25 ] ] ,
[ 38 , " ampersand " , [ 0x26 ] ] ,
[ 39 , " quoteright " , [ 0x27 , 0x92 , 0x2019 ] ] ,
[ 40 , " parenleft " , [ 0x28 ] ] ,
[ 41 , " parenright " , [ 0x29 ] ] ,
[ 42 , " asterisk " , [ 0x2a ] ] ,
[ 43 , " plus " , [ 0x2b ] ] ,
[ 44 , " comma " , [ 0x2c ] ] ,
[ 45 , " hyphen " , [ 0x2d ] ] ,
[ 46 , " period " , [ 0x2e ] ] ,
[ 47 , " slash " , [ 0x2f ] ] ,
[ 48 , " zero " , [ 0x30 ] ] ,
[ 49 , " one " , [ 0x31 ] ] ,
[ 50 , " two " , [ 0x32 ] ] ,
[ 51 , " three " , [ 0x33 ] ] ,
[ 52 , " four " , [ 0x34 ] ] ,
[ 53 , " five " , [ 0x35 ] ] ,
[ 54 , " six " , [ 0x36 ] ] ,
[ 55 , " seven " , [ 0x37 ] ] ,
[ 56 , " eight " , [ 0x38 ] ] ,
[ 57 , " nine " , [ 0x39 ] ] ,
[ 58 , " colon " , [ 0x3a ] ] ,
[ 59 , " semicolon " , [ 0x3b ] ] ,
[ 60 , " less " , [ 0x3c ] ] ,
[ 61 , " equal " , [ 0x3d ] ] ,
[ 62 , " greater " , [ 0x3e ] ] ,
[ 63 , " question " , [ 0x3f ] ] ,
[ 64 , " SF100000 " , [ 0x2500 , 0x2501 ] ] ,
[ 65 , " spade " , [ 0x2660 ] ] ,
[ 66 , " SF110000 " , [ 0x2502 , 0x2503 ] ] ,
[ 73 , " uni256e " , [ 0x256e ] ] ,
[ 74 , " uni2570 " , [ 0x2570 ] ] ,
[ 75 , " uni256F " , [ 0x256f ] ] ,
[ 77 , " uni2572 " , [ 0x2572 ] ] ,
[ 78 , " uni2571 " , [ 0x2571 ] ] ,
[ 81 , " periodcentered " , [ 0xb7 , 0x2022 , 0x2219 , 0x25cf ] ] ,
[ 83 , " heart " , [ 0x2665 ] ] ,
[ 85 , " uni256D " , [ 0x256d ] ] ,
[ 86 , " uni2573 " , [ 0x2573 ] ] ,
[ 87 , " circle " , [ 0x25cb ] ] ,
[ 88 , " club " , [ 0x2663 ] ] ,
[ 90 , " diamond " , [ 0x25c6 , 0x2666 ] ] ,
[ 91 , " SF050000 " , [ 0x253c , 0x254b ] ] ,
[ 94 , " pi " , [ 0x3c0 ] ] ,
[ 95 , " uni25e5 " , [ 0x25e5 ] ] ,
[ 97 , " lfblock " , [ 0x258c ] ] ,
[ 98 , " dnblock " , [ 0x2584 ] ] ,
[ 99 , " uni2594 " , [ 0x2594 ] ] ,
[ 100 , " uni2581 " , [ 0x2581 ] ] ,
[ 101 , " uni258E " , [ 0x258e ] ] ,
[ 102 , " shade " , [ 0x2592 ] ] ,
[ 105 , " uni25E4 " , [ 0x25e4 ] ] ,
[ 107 , " SF080000 " , [ 0x251c , 0x2523 ] ] ,
[ 108 , " uni2597 " , [ 0x2597 ] ] ,
[ 109 , " SF020000 " , [ 0x2514 , 0x2517 ] ] ,
[ 110 , " SF030000 " , [ 0x2510 , 0x2513 ] ] ,
[ 111 , " uni2582 " , [ 0x2582 ] ] ,
[ 112 , " SF010000 " , [ 0x250c , 0x250f ] ] ,
[ 113 , " SF070000 " , [ 0x2534 , 0x253b ] ] ,
[ 114 , " SF060000 " , [ 0x252c , 0x2533 ] ] ,
[ 115 , " SF090000 " , [ 0x2524 , 0x252b ] ] ,
[ 117 , " uni258D " , [ 0x258d ] ] ,
[ 121 , " uni2583 " , [ 0x2583 ] ] ,
[ 123 , " uni2596 " , [ 0x2596 ] ] ,
[ 124 , " uni259D " , [ 0x259d ] ] ,
[ 125 , " SF040000 " , [ 0x2518 , 0x251b ] ] ,
[ 126 , " uni2598 " , [ 0x2598 ] ] ,
[ 127 , " uni259A " , [ 0x259a ] ] ,
[ 160 , " uni2588 " , [ 0x2588 ] ] ,
[ 223 , " uni25E3 " , [ 0x25e3 ] ] ,
[ 225 , " uni2590 " , [ 0x2590 ] ] ,
[ 226 , " uni2580 " , [ 0x2580 ] ] ,
[ 227 , " uni2587 " , [ 0x2587 ] ] ,
[ 231 , " uni258A " , [ 0x258a ] ] ,
[ 233 , " uni25E2 " , [ 0x25e2 ] ] ,
[ 236 , " uni259B " , [ 0x259b ] ] ,
[ 246 , " uni258B " , [ 0x258b ] ] ,
[ 247 , " uni2586 " , [ 0x2586 ] ] ,
[ 248 , " uni2585 " , [ 0x2585 ] ] ,
[ 251 , " uni259C " , [ 0x259c ] ] ,
[ 252 , " uni2599 " , [ 0x2599 ] ] ,
[ 254 , " uni259F " , [ 0x259f ] ] ,
[ 255 , " uni259E " , [ 0x259e ] ] ]
CHAR_LO = [ [ 0 , " at " , [ 0x40 ] ] ,
[ 1 , " a " , [ 0x61 ] ] ,
[ 2 , " b " , [ 0x62 ] ] ,
[ 3 , " c " , [ 0x63 ] ] ,
[ 4 , " d " , [ 0x64 ] ] ,
[ 5 , " e " , [ 0x65 ] ] ,
[ 6 , " f " , [ 0x66 ] ] ,
[ 7 , " g " , [ 0x67 ] ] ,
[ 8 , " h " , [ 0x68 ] ] ,
[ 9 , " i " , [ 0x69 ] ] ,
[ 10 , " j " , [ 0x6a ] ] ,
[ 11 , " k " , [ 0x6b ] ] ,
[ 12 , " l " , [ 0x6c ] ] ,
[ 13 , " m " , [ 0x6d ] ] ,
[ 14 , " n " , [ 0x6e ] ] ,
[ 15 , " o " , [ 0x6f ] ] ,
[ 16 , " p " , [ 0x70 ] ] ,
[ 17 , " q " , [ 0x71 ] ] ,
[ 18 , " r " , [ 0x72 ] ] ,
[ 19 , " s " , [ 0x73 ] ] ,
[ 20 , " t " , [ 0x74 ] ] ,
[ 21 , " u " , [ 0x75 ] ] ,
[ 22 , " v " , [ 0x76 ] ] ,
[ 23 , " w " , [ 0x77 ] ] ,
[ 24 , " x " , [ 0x78 ] ] ,
[ 25 , " y " , [ 0x79 ] ] ,
[ 26 , " z " , [ 0x7a ] ] ,
[ 27 , " bracketleft " , [ 0x5b ] ] ,
[ 28 , " sterling " , [ 0xa3 ] ] ,
[ 29 , " bracketright " , [ 0x5d ] ] ,
[ 30 , " arrowup " , [ 0x2191 ] ] ,
[ 31 , " arrowleft " , [ 0x2190 ] ] ,
[ 32 , " space " , [ 0x20 , 0xa0 ] ] ,
[ 33 , " exclam " , [ 0x21 ] ] ,
[ 34 , " quotedblright " , [ 0x22 , 0x201c , 0x201d ] ] ,
[ 35 , " numbersign " , [ 0x23 ] ] ,
[ 36 , " dollar " , [ 0x24 ] ] ,
[ 37 , " percent " , [ 0x25 ] ] ,
[ 38 , " ampersand " , [ 0x26 ] ] ,
[ 39 , " quoteright " , [ 0x27 , 0x92 , 0x2019 ] ] ,
[ 40 , " parenleft " , [ 0x28 ] ] ,
[ 41 , " parenright " , [ 0x29 ] ] ,
[ 42 , " asterisk " , [ 0x2a ] ] ,
[ 43 , " plus " , [ 0x2b ] ] ,
[ 44 , " comma " , [ 0x2c ] ] ,
[ 45 , " hyphen " , [ 0x2d ] ] ,
[ 46 , " period " , [ 0x2e ] ] ,
[ 47 , " slash " , [ 0x2f ] ] ,
[ 48 , " zero " , [ 0x30 ] ] ,
[ 49 , " one " , [ 0x31 ] ] ,
[ 50 , " two " , [ 0x32 ] ] ,
[ 51 , " three " , [ 0x33 ] ] ,
[ 52 , " four " , [ 0x34 ] ] ,
[ 53 , " five " , [ 0x35 ] ] ,
[ 54 , " six " , [ 0x36 ] ] ,
[ 55 , " seven " , [ 0x37 ] ] ,
[ 56 , " eight " , [ 0x38 ] ] ,
[ 57 , " nine " , [ 0x39 ] ] ,
[ 58 , " colon " , [ 0x3a ] ] ,
[ 59 , " semicolon " , [ 0x3b ] ] ,
[ 60 , " less " , [ 0x3c ] ] ,
[ 61 , " equal " , [ 0x3d ] ] ,
[ 62 , " greater " , [ 0x3e ] ] ,
[ 63 , " question " , [ 0x3f ] ] ,
[ 64 , " SF100000 " , [ 0x2500 , 0x2501 ] ] ,
[ 65 , " A " , [ 0x41 ] ] ,
[ 66 , " B " , [ 0x42 ] ] ,
[ 67 , " C " , [ 0x43 ] ] ,
[ 68 , " D " , [ 0x44 ] ] ,
[ 69 , " E " , [ 0x45 ] ] ,
[ 70 , " F " , [ 0x46 ] ] ,
[ 71 , " G " , [ 0x47 ] ] ,
[ 72 , " H " , [ 0x48 ] ] ,
[ 73 , " I " , [ 0x49 ] ] ,
[ 74 , " J " , [ 0x4a ] ] ,
[ 75 , " K " , [ 0x4b ] ] ,
[ 76 , " L " , [ 0x4c ] ] ,
[ 77 , " M " , [ 0x4d ] ] ,
[ 78 , " N " , [ 0x4e ] ] ,
[ 79 , " O " , [ 0x4f ] ] ,
[ 80 , " P " , [ 0x50 ] ] ,
[ 81 , " Q " , [ 0x51 ] ] ,
[ 82 , " R " , [ 0x52 ] ] ,
[ 83 , " S " , [ 0x53 ] ] ,
[ 84 , " T " , [ 0x54 ] ] ,
[ 85 , " U " , [ 0x55 ] ] ,
[ 86 , " V " , [ 0x56 ] ] ,
[ 87 , " W " , [ 0x57 ] ] ,
[ 88 , " X " , [ 0x58 ] ] ,
[ 89 , " Y " , [ 0x59 ] ] ,
[ 90 , " Z " , [ 0x5a ] ] ,
[ 91 , " SF050000 " , [ 0x253c , 0x254b ] ] ,
[ 93 , " SF110000 " , [ 0x2502 , 0x2503 ] ] ,
[ 97 , " lfblock " , [ 0x258c ] ] ,
[ 98 , " dnblock " , [ 0x2584 ] ] ,
[ 99 , " uni2594 " , [ 0x2594 ] ] ,
[ 100 , " uni2581 " , [ 0x2581 ] ] ,
[ 101 , " uni258E " , [ 0x258e ] ] ,
[ 102 , " shade " , [ 0x2592 ] ] ,
[ 107 , " SF080000 " , [ 0x251c , 0x2523 ] ] ,
[ 108 , " uni2597 " , [ 0x2597 ] ] ,
[ 109 , " SF020000 " , [ 0x2514 , 0x2517 ] ] ,
[ 110 , " SF030000 " , [ 0x2510 , 0x2513 ] ] ,
[ 111 , " uni2582 " , [ 0x2582 ] ] ,
[ 112 , " SF010000 " , [ 0x250c , 0x250f ] ] ,
[ 113 , " SF070000 " , [ 0x2534 , 0x253b ] ] ,
[ 114 , " SF060000 " , [ 0x252c , 0x2533 ] ] ,
[ 115 , " SF090000 " , [ 0x2524 , 0x252b ] ] ,
[ 117 , " uni258D " , [ 0x258d ] ] ,
[ 121 , " uni2583 " , [ 0x2583 ] ] ,
[ 122 , " uni2713 " , [ 0x2713 ] ] ,
[ 123 , " uni2596 " , [ 0x2596 ] ] ,
[ 124 , " uni259D " , [ 0x259d ] ] ,
[ 125 , " SF040000 " , [ 0x2518 , 0x251b ] ] ,
[ 126 , " uni2598 " , [ 0x2598 ] ] ,
[ 127 , " uni259A " , [ 0x259a ] ] ,
[ 160 , " uni2588 " , [ 0x2588 ] ] ,
[ 225 , " uni2590 " , [ 0x2590 ] ] ,
[ 226 , " uni2580 " , [ 0x2580 ] ] ,
[ 227 , " uni2587 " , [ 0x2587 ] ] ,
[ 231 , " uni258A " , [ 0x258a ] ] ,
[ 236 , " uni259B " , [ 0x259b ] ] ,
[ 246 , " uni258B " , [ 0x258b ] ] ,
[ 247 , " uni2586 " , [ 0x2586 ] ] ,
[ 248 , " uni2585 " , [ 0x2585 ] ] ,
[ 251 , " uni259C " , [ 0x259c ] ] ,
[ 252 , " uni2599 " , [ 0x2599 ] ] ,
[ 254 , " uni259F " , [ 0x259f ] ] ,
[ 255 , " uni259E " , [ 0x259e ] ] ]
# The Mac OS Roman mapping is an 8-bit encoding including 7-bit ASCII and a few
# bits and pieces. The format is [mac roman code, glyph name]
# Indices not in this table will be mapped to ".notdef"
CMAP_MACROMAN = [ [ 0x0 , " .null " ] ,
[ 0x8 , " .null " ] ,
[ 0x9 , " nonmarkingreturn " ] ,
[ 0xd , " nonmarkingreturn " ] ,
[ 0x1d , " .null " ] ,
[ 0x20 , " space " ] ,
[ 0x21 , " exclam " ] ,
[ 0x23 , " numbersign " ] ,
[ 0x24 , " dollar " ] ,
[ 0x25 , " percent " ] ,
[ 0x26 , " ampersand " ] ,
[ 0x28 , " parenleft " ] ,
[ 0x29 , " parenright " ] ,
[ 0x2a , " asterisk " ] ,
[ 0x2b , " plus " ] ,
[ 0x2c , " comma " ] ,
[ 0x2d , " hyphen " ] ,
[ 0x2e , " period " ] ,
[ 0x2f , " slash " ] ,
[ 0x30 , " zero " ] ,
[ 0x31 , " one " ] ,
[ 0x32 , " two " ] ,
[ 0x33 , " three " ] ,
[ 0x34 , " four " ] ,
[ 0x35 , " five " ] ,
[ 0x36 , " six " ] ,
[ 0x37 , " seven " ] ,
[ 0x38 , " eight " ] ,
[ 0x39 , " nine " ] ,
[ 0x3a , " colon " ] ,
[ 0x3b , " semicolon " ] ,
[ 0x3c , " less " ] ,
[ 0x3d , " equal " ] ,
[ 0x3e , " greater " ] ,
[ 0x3f , " question " ] ,
[ 0x40 , " at " ] ,
[ 0x41 , " A " ] ,
[ 0x42 , " B " ] ,
[ 0x43 , " C " ] ,
[ 0x44 , " D " ] ,
[ 0x45 , " E " ] ,
[ 0x46 , " F " ] ,
[ 0x47 , " G " ] ,
[ 0x48 , " H " ] ,
[ 0x49 , " I " ] ,
[ 0x4a , " J " ] ,
[ 0x4b , " K " ] ,
[ 0x4c , " L " ] ,
[ 0x4d , " M " ] ,
[ 0x4e , " N " ] ,
[ 0x4f , " O " ] ,
[ 0x50 , " P " ] ,
[ 0x51 , " Q " ] ,
[ 0x52 , " R " ] ,
[ 0x53 , " S " ] ,
[ 0x54 , " T " ] ,
[ 0x55 , " U " ] ,
[ 0x56 , " V " ] ,
[ 0x57 , " W " ] ,
[ 0x58 , " X " ] ,
[ 0x59 , " Y " ] ,
[ 0x5a , " Z " ] ,
[ 0x5b , " bracketleft " ] ,
[ 0x5c , " backslash " ] ,
[ 0x5d , " bracketright " ] ,
[ 0x5e , " asciicircum " ] ,
[ 0x5f , " underscore " ] ,
[ 0x60 , " grave " ] ,
[ 0x61 , " a " ] ,
[ 0x62 , " b " ] ,
[ 0x63 , " c " ] ,
[ 0x64 , " d " ] ,
[ 0x65 , " e " ] ,
[ 0x66 , " f " ] ,
[ 0x67 , " g " ] ,
[ 0x68 , " h " ] ,
[ 0x69 , " i " ] ,
[ 0x6a , " j " ] ,
[ 0x6b , " k " ] ,
[ 0x6c , " l " ] ,
[ 0x6d , " m " ] ,
[ 0x6e , " n " ] ,
[ 0x6f , " o " ] ,
[ 0x70 , " p " ] ,
[ 0x71 , " q " ] ,
[ 0x72 , " r " ] ,
[ 0x73 , " s " ] ,
[ 0x74 , " t " ] ,
[ 0x75 , " u " ] ,
[ 0x76 , " v " ] ,
[ 0x77 , " w " ] ,
[ 0x78 , " x " ] ,
[ 0x79 , " y " ] ,
[ 0x7a , " z " ] ,
[ 0x7b , " braceleft " ] ,
[ 0x7c , " bar " ] ,
[ 0x7d , " braceright " ] ,
[ 0x7e , " asciitilde " ] ,
2014-03-25 19:53:00 +01:00
[ 0x81 , " Aring " ] ,
[ 0x8c , " aring " ] ,
2013-11-27 22:35:11 +01:00
[ 0xa3 , " sterling " ] ,
2014-03-25 19:53:00 +01:00
[ 0xae , " AE " ] ,
[ 0xaf , " Oslash " ] ,
2013-11-27 22:35:11 +01:00
[ 0xb9 , " pi " ] ,
2014-03-25 19:53:00 +01:00
[ 0xbe , " ae " ] ,
[ 0xbf , " oslash " ] ,
2013-11-27 22:35:11 +01:00
[ 0xca , " space " ] ,
[ 0xd3 , " quotedblright " ] ,
[ 0xd5 , " quoteright " ] ]
def makeEmptyGlyphs ( ) :
bitmap = dict ( )
bitmap [ " .notdef " ] = [ [ 0b00000000 ,
0b01111110 ,
0b01000010 ,
0b01000010 ,
0b01000010 ,
0b01000010 ,
0b01111110 ,
0b00000000 ] , [ ] ]
bitmap [ " .null " ] = [ [ ] , [ ] ]
bitmap [ " nonmarkingreturn " ] = [ [ ] , [ ] ]
return bitmap
2014-03-25 19:53:00 +01:00
def makeMissingDanishChars ( ) :
2020-05-16 23:58:40 +02:00
print ( " Adding Danish characters... " )
2014-03-25 19:53:00 +01:00
bitmap = dict ( )
bitmap [ " ae " ] = [ [ 0b00000000 ,
0b00000000 ,
0b01110110 ,
0b00011011 ,
0b01111111 ,
0b11011000 ,
0b01111110 ,
0b00000000 ] , [ 0xe6 ] ]
bitmap [ " oslash " ] = [ [ 0b00000000 ,
0b00000000 ,
0b00111011 ,
0b01101110 ,
0b01111110 ,
0b01110110 ,
0b11011100 ,
0b00000000 ] , [ 0xf8 ] ]
bitmap [ " aring " ] = [ [ 0b00011000 ,
0b00000000 ,
0b00111100 ,
0b00000110 ,
0b00111110 ,
0b01100110 ,
0b00111110 ,
0b00000000 ] , [ 0xe5 ] ]
bitmap [ " AE " ] = [ [ 0b00011111 ,
0b00111100 ,
0b01101100 ,
0b01111111 ,
0b01101100 ,
0b01101100 ,
0b01101111 ,
0b00000000 ] , [ 0xc6 ] ]
bitmap [ " Oslash " ] = [ [ 0b00111011 ,
0b01101110 ,
0b01101110 ,
0b01111110 ,
0b01110110 ,
0b01110110 ,
0b11011100 ,
0b00000000 ] , [ 0xd8 ] ]
bitmap [ " Aring " ] = [ [ 0b00011000 ,
0b00000000 ,
0b00111100 ,
0b01100110 ,
0b01111110 ,
0b01100110 ,
0b01100110 ,
0b00000000 ] , [ 0xc5 ] ]
return bitmap
2013-11-27 22:35:11 +01:00
def makeMissingASCII ( ) :
2020-05-16 23:58:40 +02:00
print ( " Adding the 8 missing ASCII characters in C64 PETSCII... " )
2013-11-27 22:35:11 +01:00
bitmap = dict ( )
# Grave accent
bitmap [ " grave " ] = [ [ 0b00100000 ,
0b00010000 ,
0b00001000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ] , [ 0x60 ] ]
# Curly left brace
bitmap [ " braceleft " ] = [ [ 0b00001100 ,
0b00011000 ,
0b00011000 ,
0b00110000 ,
0b00011000 ,
0b00011000 ,
0b00001100 ,
0b00000000 ] , [ 0x7b ] ]
# Curly right brace
bitmap [ " braceright " ] = [ [ 0b00110000 ,
0b00011000 ,
0b00011000 ,
0b00001100 ,
0b00011000 ,
0b00011000 ,
0b00110000 ,
0b00000000 ] , [ 0x7d ] ]
# Vertical bar
bitmap [ " bar " ] = [ [ 0b00011000 ,
0b00011000 ,
0b00011000 ,
0b00011000 ,
0b00011000 ,
0b00011000 ,
0b00011000 ,
0b00011000 ] , [ 0x7c ] ]
# Tilde
bitmap [ " asciitilde " ] = [ [ 0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00111001 ,
0b01001110 ,
0b00000000 ,
0b00000000 ,
0b00000000 ] , [ 0x7e ] ]
# Caret
bitmap [ " asciicircum " ] = [ [ 0b00001000 ,
0b00011100 ,
0b00110110 ,
0b01100011 ,
0b01000001 ,
0b00000000 ,
0b00000000 ,
0b00000000 ] , [ 0x5e ] ]
# Backslash
bitmap [ " backslash " ] = [ [ 0b00000000 ,
0b01100000 ,
0b00110000 ,
0b00011000 ,
0b00001100 ,
0b00000110 ,
0b00000011 ,
0b00000000 ] , [ 0x5c ] ]
# Underscore
bitmap [ " underscore " ] = [ [ 0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ,
0b00000000 ,
0b11111111 ] , [ 0x5f ] ]
return bitmap
# THE VECTORIZATION ALGORITHM
def vectorizeGlyph ( glyphData , pixelSize , descent ) :
if glyphData is None or len ( glyphData ) == 0 :
return [ ]
bitmap = unpackChar ( glyphData )
edges = generateEdges ( bitmap )
scaledEdges = scaleEdges ( edges , pixelSize , descent )
return mergeContours ( scaledEdges )
# 1) First, we need to unpack the bits in the bitmap and reverse the order so
# that [0,0] is the lower left corner. This will make the next step easier
# to understand.
def unpackChar ( glyphData ) :
return [ [ ( ( row >> bit ) & 1 ) == 1 for bit in range ( 7 , - 1 , - 1 ) ] for row in reversed ( glyphData ) ]
# 2) A simple way of vectorizing a b/w bitmap is to simply generate (up to)
# four edges going clockwise around each opaque pixel.
def generateEdges ( bitmap ) :
edges = [ ]
height = len ( bitmap )
width = len ( bitmap [ 0 ] )
for y in range ( height ) :
for x in range ( width ) :
if bitmap [ y ] [ x ] :
# Insert edge to the left of the pixel?
if x == 0 or not bitmap [ y ] [ x - 1 ] :
edges . append ( [ [ x , y ] , [ x , y + 1 ] ] )
# Insert edge above the pixel?
if y == height - 1 or not bitmap [ y + 1 ] [ x ] :
edges . append ( [ [ x , y + 1 ] , [ x + 1 , y + 1 ] ] )
# Insert edge to the right of the pixel?
if x == width - 1 or not bitmap [ y ] [ x + 1 ] :
edges . append ( [ [ x + 1 , y + 1 ] , [ x + 1 , y ] ] )
# Insert edge below the pixel?
if y == 0 or not bitmap [ y - 1 ] [ x ] :
edges . append ( [ [ x + 1 , y ] , [ x , y ] ] )
return edges
# 3) Scaling and translation of the vectorized pixels.
def scaleEdges ( edges , pixelSize , descent ) :
return [ [ [ point [ 0 ] * pixelSize , ( point [ 1 ] - descent ) * pixelSize ] for point in edge ] for edge in edges ]
# 4) In a TTF file we have to provide contours rather than just a bunch of
# unordered edges. If possible, consecutive edges are merged.
def mergeContours ( edges ) :
edgeList = sorted ( edges )
contours = [ ]
while len ( edgeList ) > 1 :
start = edgeList [ 0 ]
edgeList . remove ( start )
current = start
contour = [ start [ 0 ] , start [ 1 ] ]
while current [ 1 ] != start [ 0 ] :
next = [ edge for edge in edgeList if edge [ 0 ] == current [ 1 ] ] [ 0 ]
if next [ 1 ] [ 0 ] == current [ 0 ] [ 0 ] or next [ 1 ] [ 1 ] == current [ 0 ] [ 1 ] :
contour [ - 1 ] = next [ 1 ]
else :
contour . append ( next [ 1 ] )
current = next
edgeList . remove ( current )
# We don't need to include the last edge as it's implicit.
contours . append ( contour [ : - 1 ] )
return contours
# TRUETYPE FONT HANDLING
def saveFont ( glyphs , outputFileName , asXML , pixelSize , descent , fontName , copyrightYear , creator , version ) :
f = TTFont ( )
vectorizedGlyphs = { glyph : [ vectorizeGlyph ( glyphs [ glyph ] [ 0 ] , pixelSize , descent ) , glyphs [ glyph ] [ 1 ] ] for glyph in glyphs }
unicodes = [ code for glyph in glyphs for code in glyphs [ glyph ] [ 1 ] ]
# Populate basic tables (there are a few dependencies so order matters)
makeTable_glyf ( f , vectorizedGlyphs )
makeTable_maxp ( f )
makeTable_loca ( f )
makeTable_head ( f )
makeTable_hmtx ( f )
makeTable_hhea ( f , pixelSize , descent )
makeTable_OS2 ( f , pixelSize , descent , min ( unicodes ) , max ( unicodes ) )
makeTable_cmap ( f , glyphs )
makeTable_name ( f , fontName , " Regular " , copyrightYear , creator , version )
makeTable_post ( f , pixelSize , descent )
if asXML :
# We have to compile the TTFont manually when saving as TTX
# (to auto-calculate stuff here and there)
f [ " glyf " ] . compile ( f )
f [ " maxp " ] . compile ( f )
f [ " loca " ] . compile ( f )
f [ " head " ] . compile ( f )
f [ " hmtx " ] . compile ( f )
f [ " hhea " ] . compile ( f )
f [ " OS/2 " ] . compile ( f )
f [ " cmap " ] . compile ( f )
f [ " name " ] . compile ( f )
f [ " post " ] . compile ( f )
2020-05-16 23:58:40 +02:00
print ( " PLEASE NOTE: When exporting directly to XML, the checkSumAdjustment value in the head table will be 0. " )
2013-11-27 22:35:11 +01:00
f . saveXML ( outputFileName )
else :
f . save ( outputFileName )
# glyf - Glyph Data
def makeTable_glyf ( ttf , glyphs ) :
glyf = newTable ( " glyf " )
glyf . glyphs = { glyph : makeTTFGlyph ( glyphs [ glyph ] [ 0 ] ) for glyph in glyphs }
2016-10-19 00:15:42 +02:00
# We need to sort the glyphs in a specific way (so all basic glyphs are below index 256) to work around a MacRoman related quirk.
glyf . glyphOrder = sorted ( [ key for key in glyf . glyphs . keys ( ) if not key . startswith ( ' uni ' ) ] )
glyf . glyphOrder + = sorted ( [ key for key in glyf . glyphs . keys ( ) if key . startswith ( ' uni ' ) ] )
2013-11-27 22:35:11 +01:00
ttf [ " glyf " ] = glyf
ttf . glyphOrder = glyf . glyphOrder
def makeTTFGlyph ( polygons ) :
result = Glyph ( )
result . numberOfContours = len ( polygons )
2016-10-19 00:15:42 +02:00
result . coordinates = GlyphCoordinates ( [ coordinate for polygon in polygons for coordinate in polygon ] )
result . flags = array . array ( " B " , [ 1 ] * len ( result . coordinates ) )
2013-11-27 22:35:11 +01:00
result . endPtsOfContours = [ sum ( len ( polygon ) for polygon in polygons [ : idx + 1 ] ) - 1 for idx in range ( len ( polygons ) ) ]
result . program = ttProgram . Program ( )
result . program . assembly = [ ]
return result
# maxp - Maximum Profile
def makeTable_maxp ( ttf ) :
maxp = newTable ( " maxp " )
maxp . tableVersion = 0x00010000
maxp . numGlyphs = 0 # Auto-calculated by maxp.compile()
maxp . maxPoints = 0 # Auto-calculated by maxp.compile()
maxp . maxContours = 0 # Auto-calculated by maxp.compile()
maxp . maxCompositePoints = 0 # Auto-calculated by maxp.compile()
maxp . maxCompositeContours = 0 # Auto-calculated by maxp.compile()
maxp . maxZones = 2
maxp . maxTwilightPoints = 0
maxp . maxStorage = 0
maxp . maxFunctionDefs = 0
maxp . maxInstructionDefs = 0
maxp . maxStackElements = 0
maxp . maxSizeOfInstructions = 0
maxp . maxComponentElements = 0
maxp . maxComponentDepth = 0 # Auto-calculated by maxp.compile()
ttf [ " maxp " ] = maxp
# loca - Index to Location
def makeTable_loca ( ttf ) :
# Nothing to do here... Locations are auto-calculated by glyf.compile()
ttf [ " loca " ] = newTable ( " loca " )
# head - Font Header
def makeTable_head ( ttf ) :
head = newTable ( " head " )
head . tableVersion = 1.0
head . fontRevision = 1.0
head . checkSumAdjustment = 0 # Auto-calculated when writing the TTF.
head . magicNumber = 0x5F0F3CF5
head . flags = 11 # bits 0, 1, and 3 = 1 + 2 + 8 = 11
head . unitsPerEm = 2048
2020-05-16 23:58:40 +02:00
head . created = int ( time . time ( ) - mac_epoch_diff )
head . modified = int ( time . time ( ) - mac_epoch_diff )
2013-11-27 22:35:11 +01:00
head . xMin = 0 # Auto-calculated by maxp.compile()
head . xMax = 0 # Auto-calculated by maxp.compile()
head . yMin = 0 # Auto-calculated by maxp.compile()
head . yMax = 0 # Auto-calculated by maxp.compile()
head . macStyle = 0
head . lowestRecPPEM = 8
head . fontDirectionHint = 0
head . indexToLocFormat = 0
head . glyphDataFormat = 0
ttf [ " head " ] = head
# hmtx - Horizontal Metrics
def makeTable_hmtx ( ttf ) :
hmtx = newTable ( " hmtx " )
hmtx . metrics = dict ( )
for glyphName in ttf [ " glyf " ] . keys ( ) :
if glyphName == " .null " :
hmtx [ " .null " ] = ( 0 , 0 )
else :
glyph = ttf [ " glyf " ] . glyphs [ glyphName ]
lsb = 0
if hasattr ( glyph , " coordinates " ) and len ( glyph . coordinates ) > 0 :
lsb = min ( [ coord [ 0 ] for coord in glyph . coordinates ] )
hmtx [ glyphName ] = ( 2048 , lsb )
ttf [ " hmtx " ] = hmtx
# hhea - Horizontal Header
def makeTable_hhea ( ttf , pixelSize , descent ) :
hhea = newTable ( " hhea " )
hhea . tableVersion = 1.0
hhea . ascent = ( 8 - descent ) * pixelSize
hhea . descent = - descent * pixelSize
hhea . lineGap = 0
hhea . advanceWidthMax = 0 # Auto-calculated by hhea.compile()
hhea . minLeftSideBearing = 0 # Auto-calculated by hhea.compile()
hhea . minRightSideBearing = 0 # Auto-calculated by hhea.compile()
hhea . xMaxExtent = 0 # Auto-calculated by hhea.compile()
hhea . caretSlopeRise = 1
hhea . caretSlopeRun = 0
hhea . caretOffset = 0
hhea . reserved0 = 0
hhea . reserved1 = 0
hhea . reserved2 = 0
hhea . reserved3 = 0
hhea . metricDataFormat = 0
hhea . numOfLongHorMetrics = 0 # Auto-calculated by hmtx.compile()
ttf [ " hhea " ] = hhea
# OS/2 - OS/2 and Windows Specific Metrics
def makeTable_OS2 ( ttf , pixelSize , descentPixels , minUnicode , maxUnicode ) :
size = 8 * pixelSize
descent = pixelSize * descentPixels
os_2 = newTable ( " OS/2 " )
os_2 . version = 4
os_2 . xAvgCharWidth = size
os_2 . usWeightClass = 400 # Meaning "Normal (Regular)"
os_2 . usWidthClass = 5 # Meaing "Medium (normal)"
os_2 . fsType = 0 # Windows-only licensing bits...
os_2 . ySubscriptXSize = size
2020-05-16 23:58:40 +02:00
os_2 . ySubscriptYSize = size >> 1
2013-11-27 22:35:11 +01:00
os_2 . ySubscriptXOffset = 0
os_2 . ySubscriptYOffset = descent
2020-05-16 23:58:40 +02:00
os_2 . ySuperscriptXSize = size >> 1
os_2 . ySuperscriptYSize = size >> 1
2013-11-27 22:35:11 +01:00
os_2 . ySuperscriptXOffset = 0
2020-05-16 23:58:40 +02:00
os_2 . ySuperscriptYOffset = size >> 1
2013-11-27 22:35:11 +01:00
os_2 . yStrikeoutSize = pixelSize
2020-05-16 23:58:40 +02:00
os_2 . yStrikeoutPosition = ( size >> 1 ) - descent
2013-11-27 22:35:11 +01:00
os_2 . sFamilyClass = 0x080a # Class ID = 8 (Sans Serif), Subclass ID = 10 (Matrix)
panose = Panose ( )
panose . bFamilyType = 2 # Text and Display
panose . bSerifStyle = 1 # No Fit
panose . bWeight = 6 # Medium
panose . bProportion = 9 # Monospaced
panose . bContrast = 6 # Medium
panose . bStrokeVariation = 2 # Gradual/Diagonal
panose . bArmStyle = 2 # Straight Arms/Horizontal
panose . bLetterForm = 8 # Normal/Square
panose . bMidline = 1 # No Fit
panose . bXHeight = 1 # No Fit
os_2 . panose = panose
os_2 . ulUnicodeRange1 = 0b10000000000000000000000010000011 # Basic Latin + Latin-1 supplement + Greek and Coptic + General punctuation
os_2 . ulUnicodeRange2 = 0b00010000000000001111100001100000 # Arrows + Mathematical operators + Box drawing + Block elements + Geometric shapes + Misc. symbols + Dingbats + Private use area
os_2 . ulUnicodeRange3 = 0b00000000000000000000000000000000 # n/a
os_2 . ulUnicodeRange4 = 0b00000000000000000000000000000000 # n/a
os_2 . achVendID = " C=64 " # :-)
os_2 . fsSelection = 64 # Regular
os_2 . fsFirstCharIndex = minUnicode
os_2 . fsLastCharIndex = maxUnicode
os_2 . sTypoAscender = size - descent
os_2 . sTypoDescender = 0 - descent
os_2 . sTypoLineGap = 0
os_2 . usWinAscent = size - descent
os_2 . usWinDescent = descent
os_2 . ulCodePageRange1 = 0b00000000000000000000000000000001 # Latin 1 (Code page 1252)
os_2 . ulCodePageRange2 = 0b11000000000000000000000000000000 # WE/Latin 1 (Code page 850) + US (Code page 437)
os_2 . sxHeight = 6 * pixelSize - descent # Guess (we don't always have a lower-case "x" at 0x78 to measure (as the standard suggests))
os_2 . sCapHeight = size - descent
os_2 . usDefaultChar = 0
os_2 . usBreakChar = 32
os_2 . usMaxContex = 0
ttf [ " OS/2 " ] = os_2
# cmap - Character to Glyph Mapping
def makeTable_cmap ( ttf , glyphs ) :
unicodeCMAP = { index : glyph for glyph in glyphs if glyph in ttf [ " glyf " ] . glyphs for index in glyphs [ glyph ] [ 1 ] }
2014-03-25 19:53:00 +01:00
macRoman = dict ( CMAP_MACROMAN )
macRomanCMAP = { index : macRoman [ index ] if index in macRoman and macRoman [ index ] in ttf [ " glyf " ] . glyphs else ' .notdef ' for index in range ( 256 ) }
2013-11-27 22:35:11 +01:00
# Unicode
cmap4_0_3 = cmap_format_4 ( 4 )
cmap4_0_3 . platformID = 0
cmap4_0_3 . platEncID = 3
cmap4_0_3 . language = 0
cmap4_0_3 . cmap = unicodeCMAP
# Mac Roman
2014-03-25 19:53:00 +01:00
cmap0_1_0 = cmap_format_0 ( 0 )
cmap0_1_0 . platformID = 1
cmap0_1_0 . platEncID = 0
cmap0_1_0 . language = 0
cmap0_1_0 . cmap = macRomanCMAP
2013-11-27 22:35:11 +01:00
# Windows
cmap4_3_1 = cmap_format_4 ( 4 )
cmap4_3_1 . platformID = 3
cmap4_3_1 . platEncID = 1
cmap4_3_1 . language = 0
cmap4_3_1 . cmap = unicodeCMAP
cmap = newTable ( " cmap " )
cmap . tableVersion = 0
2014-03-25 19:53:00 +01:00
cmap . tables = [ cmap4_0_3 , cmap0_1_0 , cmap4_3_1 ]
2013-11-27 22:35:11 +01:00
ttf [ " cmap " ] = cmap
# name - Naming Table
def makeTable_name ( ttf , fontName , subFamily , copyrightYear , creator , version ) :
copyright = " Copyright {0} {1} " . format ( copyrightYear , creator )
fullName = " {0} {1} " . format ( fontName , subFamily )
uniqueID = " {0} {1} " . format ( creator , fullName )
versionText = " Version {0} " . format ( version )
2020-09-05 20:42:52 +02:00
psFontName = " " . join ( [ b for b in " {0} - {1} " . format ( fontName , creator ) if 32 < ord ( b ) < 127 and b not in ' []() {} <>/ % ' ] ) [ : 63 ]
2013-11-27 22:35:11 +01:00
nameEntries = [ copyright , fontName , subFamily , uniqueID , fullName , versionText , psFontName ]
unicodeEnc = [ 0 , 3 , 0 , " utf_16_be " ]
macintoshEnc = [ 1 , 0 , 0 , " latin1 " ]
microsoftEnc = [ 3 , 1 , 0x409 , " utf_16_be " ]
encodings = [ unicodeEnc , macintoshEnc , microsoftEnc ]
name = newTable ( " name " )
name . names = [ makeNameRecord ( idx , entry , * conf ) for idx , entry in enumerate ( nameEntries ) for conf in encodings ]
ttf [ " name " ] = name
def makeNameRecord ( nameID , string , platformID , platEncID , langID , encoding ) :
rec = NameRecord ( )
rec . nameID = nameID
rec . platformID = platformID
rec . platEncID = platEncID
rec . langID = langID
2020-05-16 23:58:40 +02:00
rec . string = str ( string ) . encode ( encoding )
2013-11-27 22:35:11 +01:00
return rec
# post - Postscript Information
def makeTable_post ( ttf , pixelSize , descent ) :
post = newTable ( " post " )
post . glyphOrder = [ ]
post . extraNames = [ ]
post . mapping = dict ( )
post . formatType = 2
post . italicAngle = 0
post . underlinePosition = descent
post . underlineThickness = pixelSize
post . isFixedPitch = 1
post . minMemType42 = 0
post . maxMemType42 = 0
post . minMemType1 = 0
post . maxMemType1 = 0
ttf [ " post " ] = post
# MAIN METHODS
def readCharBitmaps ( fileName ) :
if fileName is None :
return [ ]
2020-05-16 23:58:40 +02:00
print ( " Processing input file {0} ... " . format ( fileName ) )
data = open ( fileName , " rb " ) . read ( )
2013-11-27 22:35:11 +01:00
# Shave off magic bytes and append zeroes so the length of the remaining
# data is an integer multiple of 8.
2020-12-30 17:18:18 +00:00
#data = data[2:]
2013-11-27 22:35:11 +01:00
while len ( data ) % 8 != 0 :
2020-12-30 17:18:18 +00:00
data + = bytes ( [ 0 ] )
2013-11-27 22:35:11 +01:00
if len ( data ) == 0 :
2020-05-16 23:58:40 +02:00
print ( " No data found. " )
2013-11-27 22:35:11 +01:00
return [ ]
elif len ( data ) > 2048 :
2020-05-16 23:58:40 +02:00
print ( " More than 256 chars detected. Are you sure this is a C64 character set??? " )
2013-11-27 22:35:11 +01:00
return [ ]
else :
2020-05-16 23:58:40 +02:00
print ( " {0} glyphs loaded... " . format ( int ( len ( data ) / 8 ) ) )
2013-11-27 22:35:11 +01:00
return [ data [ idx : idx + 8 ] for idx in range ( 0 , len ( data ) , 8 ) ]
def mapGlyphs ( glyphData , charset ) :
return { char [ 1 ] : [ glyphData [ char [ 0 ] ] , char [ 2 ] ] for char in charset if char [ 0 ] < len ( glyphData ) }
def mapAllGlyphs ( existingGlyphs , newGlyphBitmaps , unicodeOffset ) :
newGlyphs = { " uni {0} " . format ( hex ( unicodeOffset + index ) . upper ( ) [ 2 : ] ) : [ data , [ unicodeOffset + index ] ] for index , data in enumerate ( newGlyphBitmaps ) }
updates = { }
for newGlyph in newGlyphs :
newBitmap = newGlyphs [ newGlyph ] [ 0 ]
newUnicodes = newGlyphs [ newGlyph ] [ 1 ]
foundGlyph = False
for oldGlyph in existingGlyphs :
oldBitmap = existingGlyphs [ oldGlyph ] [ 0 ]
oldUnicodes = existingGlyphs [ oldGlyph ] [ 1 ]
if oldBitmap == newBitmap :
if oldGlyph in updates :
updates [ oldGlyph ] = [ oldBitmap , list ( set ( updates [ oldGlyph ] [ 1 ] + newUnicodes ) ) ]
else :
updates [ oldGlyph ] = [ oldBitmap , list ( set ( oldUnicodes + newUnicodes ) ) ]
foundGlyph = True
break
if not foundGlyph :
updates [ newGlyph ] = newGlyphs [ newGlyph ]
return updates
2014-03-25 19:53:00 +01:00
def processCharFiles ( lowercaseInputFileName , uppercaseInputFileName , outputFileName , asXML , addMissingASCII , addMissingDanish , pixelSize , descent , addAll , fontName , copyrightYear , creator , version ) :
2013-11-27 22:35:11 +01:00
glyphs = makeEmptyGlyphs ( )
lowercaseBitmaps = [ ]
uppercaseBitmaps = [ ]
if uppercaseInputFileName is not None :
uppercaseBitmaps = readCharBitmaps ( uppercaseInputFileName )
glyphs . update ( mapGlyphs ( uppercaseBitmaps , CHAR_HI ) )
if lowercaseInputFileName is not None :
lowercaseBitmaps = readCharBitmaps ( lowercaseInputFileName )
glyphs . update ( mapGlyphs ( lowercaseBitmaps , CHAR_LO ) )
if addMissingASCII :
glyphs . update ( makeMissingASCII ( ) )
2014-03-25 19:53:00 +01:00
if addMissingDanish :
glyphs . update ( makeMissingDanishChars ( ) )
2013-11-27 22:35:11 +01:00
if addAll :
glyphs . update ( mapAllGlyphs ( glyphs , uppercaseBitmaps , 0xee00 ) )
glyphs . update ( mapAllGlyphs ( glyphs , lowercaseBitmaps , 0xef00 ) )
saveFont ( glyphs , outputFileName , asXML , pixelSize , descent , fontName , copyrightYear , creator , version )
# "static void main()"
if __name__ == " __main__ " :
2020-09-05 20:42:52 +02:00
parser = argparse . ArgumentParser ( description = " c64ttf.py v1.4 - C64 Character Set to TrueType Converter (c) 2013-20 atbrask " )
2013-11-27 22:35:11 +01:00
# Files
parser . add_argument ( " -l " , " --lowercase " , help = " Input 64C file with lowercase and uppercase characters. " )
parser . add_argument ( " -u " , " --uppercase " , help = " Input 64C file with uppercase and graphics characters. " )
parser . add_argument ( " -o " , " --output " , help = " Output filename (default is font name + ' .TTF ' or ' .TTX ' ) " )
parser . add_argument ( " -x " , " --xml " , help = " Enable XML output (for debugging purposes) " , action = " store_true " )
parser . add_argument ( " -m " , " --add-missing-ascii " , help = " Add non-PETSCII characters for ASCII compatibility (ie. grave accent, curly braces, vertical bar, tilde, caret, backslash, and underscore) " , action = " store_true " )
2014-03-25 19:53:00 +01:00
parser . add_argument ( " -i " , " --add-missing-danish " , help = " Add special Danish characters. Needed for proper compatibility with the Danish version of MAC OSX. " , action = " store_true " )
2013-11-27 22:35:11 +01:00
# Vectorization
parser . add_argument ( " -p " , " --pixelsize " , help = " Pixel size in the resulting TTF file (default is 256) " , default = 256 )
parser . add_argument ( " -d " , " --descent " , help = " The descent below baseline in pixels (default is 1) " , default = 1 )
# Font stuff
parser . add_argument ( " -a " , " --add-all " , help = " Inserts the uppercase character set (if any) at 0xEE00...0xEEFF and the lowercase character set (if any) at 0xEF00...0xEFFF " , action = " store_true " )
parser . add_argument ( " -n " , " --name " , help = " Font name (default is C64) " )
parser . add_argument ( " -y " , " --copyrightyear " , help = " Sets copyright year (default is {0} ) " . format ( date . today ( ) . year ) , default = date . today ( ) . year )
parser . add_argument ( " -c " , " --creator " , help = " Font creator (default is ' {0} ' ) " . format ( getpass . getuser ( ) ) , default = getpass . getuser ( ) )
parser . add_argument ( " -v " , " --version " , help = " Sets font version number (default is ' 1.00 ' ) " , default = " 1.00 " )
args = parser . parse_args ( )
if args . lowercase is None and args . uppercase is None :
parser . print_help ( )
2020-05-16 23:58:40 +02:00
print ( " " )
print ( " No input files! Aborting... " )
2013-11-27 22:35:11 +01:00
exit ( 1 )
fontName = args . name
if fontName is None :
fontName = " C64 "
outputFileName = args . output
if outputFileName is None :
if args . xml :
outputFileName = fontName + " .ttx "
else :
outputFileName = fontName + " .ttf "
2014-03-25 19:53:00 +01:00
processCharFiles ( args . lowercase , args . uppercase , outputFileName , args . xml , args . add_missing_ascii , args . add_missing_danish , int ( args . pixelsize ) , int ( args . descent ) , args . add_all , fontName , int ( args . copyrightyear ) , args . creator , args . version )