a115e81a5cd3b5193e539e555223e616c9aabf91
[unifont.git] / src / unihexgen.c
1 /*
2    unihexgen.c - generate a series of four- or six-digit hexadecimal
3                  numbers within a 16x16 glyph, rendered as white digits
4                  on a black background.
5
6                  argv[1] is the starting code point (as a hexadecimal
7                  string, with no leading "0x".
8
9                  argv[2] is the ending code point (as a hexadecimal
10                  string, with no leading "0x".
11
12                  For example:
13
14                     unihexgen e000 f8ff > pua.hex
15
16                  This generates the Private Use Area glyph file.
17
18    This utility program works in Roman Czyborra's unifont.hex file
19    format, the basis of the GNU Unifont package.
20
21    This program is released under the terms of the GNU General Public
22    License version 2, or (at your option) a later version.
23
24    Author: Paul Hardy, 2013
25
26    Copyright (C) 2013 Paul Hardy
27
28    LICENSE:
29
30       This program is free software: you can redistribute it and/or modify
31       it under the terms of the GNU General Public License as published by
32       the Free Software Foundation, either version 2 of the License, or
33       (at your option) any later version.
34    
35       This program is distributed in the hope that it will be useful,
36       but WITHOUT ANY WARRANTY; without even the implied warranty of
37       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
38       GNU General Public License for more details.
39    
40       You should have received a copy of the GNU General Public License
41       along with this program.  If not, see <http://www.gnu.org/licenses/>.
42 */
43
44 #include <stdio.h>
45 #include <stdlib.h>
46
47
48 /*
49    hexdigit[][] definition: the bitmap pattern for
50    each hexadecimal digit.
51
52    Each digit is drawn as a 4 wide by 5 high bitmap,
53    so each digit row is one hexadecimal digit, and
54    each entry has 5 rows.
55
56    For example, the entry for digit 1 is:
57
58       {0x2,0x6,0x2,0x2,0x7},
59
60    which corresponds graphically to:
61
62       --#-  ==>  0010  ==>  0x2
63       -##-  ==>  0110  ==>  0x6
64       --#-  ==>  0010  ==>  0x2
65       --#-  ==>  0010  ==>  0x2
66       -###  ==>  0111  ==>  0x7
67
68    These row values will then be exclusive-ORed with four one bits
69    (binary 1111, or 0xF) to form white digits on a black background.
70
71
72    The hexdigit[][] array is shared by hexprint4() and hexprint6().
73 */
74 char hexdigit[16][5] = {
75    {0x6,0x9,0x9,0x9,0x6},  /* 0x0 */
76    {0x2,0x6,0x2,0x2,0x7},  /* 0x1 */
77    {0xF,0x1,0xF,0x8,0xF},  /* 0x2 */
78    {0xE,0x1,0x7,0x1,0xE},  /* 0x3 */
79    {0x9,0x9,0xF,0x1,0x1},  /* 0x4 */
80    {0xF,0x8,0xF,0x1,0xF},  /* 0x5 */
81    {0x6,0x8,0xE,0x9,0x6},  /* 0x6 */ // {0x8,0x8,0xF,0x9,0xF} [alternate square form of 6]
82    {0xF,0x1,0x2,0x4,0x4},  /* 0x7 */
83    {0x6,0x9,0x6,0x9,0x6},  /* 0x8 */
84    {0x6,0x9,0x7,0x1,0x6},  /* 0x9 */ // {0xF,0x9,0xF,0x1,0x1} [alternate square form of 9]
85    {0xF,0x9,0xF,0x9,0x9},  /* 0xA */
86    {0xE,0x9,0xE,0x9,0xE},  /* 0xB */
87    {0x7,0x8,0x8,0x8,0x7},  /* 0xC */
88    {0xE,0x9,0x9,0x9,0xE},  /* 0xD */
89    {0xF,0x8,0xE,0x8,0xF},  /* 0xE */
90    {0xF,0x8,0xE,0x8,0x8}   /* 0xF */
91 };
92
93
94 int main(int argc, char *argv[]) {
95
96    int startcp, endcp, thiscp;
97    void hexprint4(int); /* function to print one 4-digit unifont.hex code point */
98    void hexprint6(int); /* function to print one 6-digit unifont.hex code point */
99
100    if (argc != 3) {
101       fprintf(stderr,"\n%s - generate unifont.hex code points as\n", argv[0]);
102       fprintf(stderr,"four-digit hexadecimal numbers in a 2 by 2 grid,\n");
103       fprintf(stderr,"or six-digit hexadecimal numbers in a 3 by 2 grid.\n");
104       fprintf(stderr,"Syntax:\n\n");
105       fprintf(stderr,"     %s first_code_point last_code_point > glyphs.hex\n\n", argv[0]);
106       fprintf(stderr,"Example (to generate glyphs for the Private Use Area):\n\n");
107       fprintf(stderr,"     %s e000 f8ff > pua.hex\n\n", argv[0]);
108       exit(EXIT_FAILURE);
109    }
110
111    sscanf(argv[1], "%x", &startcp);
112    sscanf(argv[2], "%x", &endcp);
113
114    startcp &= 0xFFFFFF; /* limit to 6 hex digits */
115    endcp   &= 0xFFFFFF; /* limit to 6 hex digits */
116
117    /*
118       For each code point in the desired range, generate a glyph.
119    */
120    for (thiscp = startcp; thiscp <= endcp; thiscp++) {
121       if (thiscp <= 0xFFFF) {
122          hexprint4(thiscp); /* print digits 2/line, 2 lines */
123       }
124       else {
125          hexprint6(thiscp); /* print digits 3/line, 2 lines */
126       }
127    }
128    exit(EXIT_SUCCESS);
129 }
130
131
132 /*
133    Takes a 4-digit Unicode code point as an argument
134    and prints a unifont.hex string for it to stdout.
135 */
136 void hexprint4(int thiscp) {
137
138    int grid[16]; /* the glyph grid we'll build */
139
140    int row;      /* row number in current glyph */
141    int digitrow; /* row number in current hex digit being rendered */
142    int rowbits;  /* 1 & 0 bits to draw current glyph row */
143
144    int d1, d2, d3, d4; /* four hexadecimal digits of each code point */
145
146    d1 = (thiscp >> 12) & 0xF;
147    d2 = (thiscp >>  8) & 0xF;
148    d3 = (thiscp >>  4) & 0xF;
149    d4 = (thiscp      ) & 0xF;
150
151    /* top and bottom rows are white */
152    grid[0] = grid[15] = 0x0000;
153
154    /* 14 inner rows are 14-pixel wide black lines, centered */
155    for (row = 1; row < 15; row++) grid[row] = 0x7FFE;
156
157    printf("%04X:", thiscp);
158
159    /*
160       Render the first row of 2 hexadecimal digits
161    */
162    digitrow = 0; /* start at top of first row of digits to render */
163    for (row = 2; row < 7; row++) {
164       rowbits = (hexdigit[d1][digitrow] << 9) |
165                 (hexdigit[d2][digitrow] << 3);
166       grid[row] ^= rowbits; /* digits appear as white on black background */
167       digitrow++;
168    }
169
170    /*
171       Render the second row of 2 hexadecimal digits
172    */
173    digitrow = 0; /* start at top of first row of digits to render */
174    for (row = 9; row < 14; row++) {
175       rowbits = (hexdigit[d3][digitrow] << 9) |
176                 (hexdigit[d4][digitrow] << 3);
177       grid[row] ^= rowbits; /* digits appear as white on black background */
178       digitrow++;
179    }
180
181    for (row = 0; row < 16; row++) printf("%04X", grid[row] & 0xFFFF);
182
183    putchar('\n');
184
185    return;
186 }
187
188
189 /*
190    Takes a 6-digit Unicode code point as an argument
191    and prints a unifont.hex string for it to stdout.
192 */
193 void hexprint6(int thiscp) {
194
195    int grid[16]; /* the glyph grid we'll build */
196
197    int row;      /* row number in current glyph */
198    int digitrow; /* row number in current hex digit being rendered */
199    int rowbits;  /* 1 & 0 bits to draw current glyph row */
200
201    int d1, d2, d3, d4, d5, d6; /* six hexadecimal digits of each code point */
202
203    d1 = (thiscp >> 20) & 0xF;
204    d2 = (thiscp >> 16) & 0xF;
205    d3 = (thiscp >> 12) & 0xF;
206    d4 = (thiscp >>  8) & 0xF;
207    d5 = (thiscp >>  4) & 0xF;
208    d6 = (thiscp      ) & 0xF;
209
210    /* top and bottom rows are white */
211    grid[0] = grid[15] = 0x0000;
212
213    /* 14 inner rows are 16-pixel wide black lines, centered */
214    for (row = 1; row < 15; row++) grid[row] = 0xFFFF;
215
216
217    printf("%06X:", thiscp);
218
219    /*
220       Render the first row of 3 hexadecimal digits
221    */
222    digitrow = 0; /* start at top of first row of digits to render */
223    for (row = 2; row < 7; row++) {
224       rowbits = (hexdigit[d1][digitrow] << 11) |
225                 (hexdigit[d2][digitrow] <<  6) |
226                 (hexdigit[d3][digitrow] <<  1);
227       grid[row] ^= rowbits; /* digits appear as white on black background */
228       digitrow++;
229    }
230
231    /*
232       Render the second row of 3 hexadecimal digits
233    */
234    digitrow = 0; /* start at top of first row of digits to render */
235    for (row = 9; row < 14; row++) {
236       rowbits = (hexdigit[d4][digitrow] << 11) |
237                 (hexdigit[d5][digitrow] <<  6) |
238                 (hexdigit[d6][digitrow] <<  1);
239       grid[row] ^= rowbits; /* digits appear as white on black background */
240       digitrow++;
241    }
242
243    for (row = 0; row < 16; row++) printf("%04X", grid[row] & 0xFFFF);
244
245    putchar('\n');
246
247    return;
248 }
249