unifont-6.3.20131215.tar.gz
[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    Functions hexprint4 and hexprint6 share the hexdigit array;
73    they print four-digit and six-digit hexadecimal code points
74    in a single glyph, respectively.
75 */
76 char hexdigit[16][5] = {
77    {0x6,0x9,0x9,0x9,0x6},  /* 0x0 */
78    {0x2,0x6,0x2,0x2,0x7},  /* 0x1 */
79    {0xF,0x1,0xF,0x8,0xF},  /* 0x2 */
80    {0xE,0x1,0x7,0x1,0xE},  /* 0x3 */
81    {0x9,0x9,0xF,0x1,0x1},  /* 0x4 */
82    {0xF,0x8,0xF,0x1,0xF},  /* 0x5 */
83    {0x6,0x8,0xE,0x9,0x6},  /* 0x6 */ // {0x8,0x8,0xF,0x9,0xF} [alternate square form of 6]
84    {0xF,0x1,0x2,0x4,0x4},  /* 0x7 */
85    {0x6,0x9,0x6,0x9,0x6},  /* 0x8 */
86    {0x6,0x9,0x7,0x1,0x6},  /* 0x9 */ // {0xF,0x9,0xF,0x1,0x1} [alternate square form of 9]
87    {0xF,0x9,0xF,0x9,0x9},  /* 0xA */
88    {0xE,0x9,0xE,0x9,0xE},  /* 0xB */
89    {0x7,0x8,0x8,0x8,0x7},  /* 0xC */
90    {0xE,0x9,0x9,0x9,0xE},  /* 0xD */
91    {0xF,0x8,0xE,0x8,0xF},  /* 0xE */
92    {0xF,0x8,0xE,0x8,0x8}   /* 0xF */
93 };
94
95
96 int
97 main (int argc, char *argv[])
98 {
99
100    int startcp, endcp, thiscp;
101    void hexprint4(int); /* function to print one 4-digit unifont.hex code point */
102    void hexprint6(int); /* function to print one 6-digit unifont.hex code point */
103
104    if (argc != 3) {
105       fprintf (stderr,"\n%s - generate unifont.hex code points as\n", argv[0]);
106       fprintf (stderr,"four-digit hexadecimal numbers in a 2 by 2 grid,\n");
107       fprintf (stderr,"or six-digit hexadecimal numbers in a 3 by 2 grid.\n");
108       fprintf (stderr,"Syntax:\n\n");
109       fprintf (stderr,"     %s first_code_point last_code_point > glyphs.hex\n\n", argv[0]);
110       fprintf (stderr,"Example (to generate glyphs for the Private Use Area):\n\n");
111       fprintf (stderr,"     %s e000 f8ff > pua.hex\n\n", argv[0]);
112       exit (EXIT_FAILURE);
113    }
114
115    sscanf (argv[1], "%x", &startcp);
116    sscanf (argv[2], "%x", &endcp);
117
118    startcp &= 0xFFFFFF; /* limit to 6 hex digits */
119    endcp   &= 0xFFFFFF; /* limit to 6 hex digits */
120
121    /*
122       For each code point in the desired range, generate a glyph.
123    */
124    for (thiscp = startcp; thiscp <= endcp; thiscp++) {
125       if (thiscp <= 0xFFFF) {
126          hexprint4 (thiscp); /* print digits 2/line, 2 lines */
127       }
128       else {
129          hexprint6 (thiscp); /* print digits 3/line, 2 lines */
130       }
131    }
132    exit (EXIT_SUCCESS);
133 }
134
135
136 /*
137    Takes a 4-digit Unicode code point as an argument
138    and prints a unifont.hex string for it to stdout.
139 */
140 void
141 hexprint4 (int thiscp)
142 {
143
144    int grid[16]; /* the glyph grid we'll build */
145
146    int row;      /* row number in current glyph */
147    int digitrow; /* row number in current hex digit being rendered */
148    int rowbits;  /* 1 & 0 bits to draw current glyph row */
149
150    int d1, d2, d3, d4; /* four hexadecimal digits of each code point */
151
152    d1 = (thiscp >> 12) & 0xF;
153    d2 = (thiscp >>  8) & 0xF;
154    d3 = (thiscp >>  4) & 0xF;
155    d4 = (thiscp      ) & 0xF;
156
157    /* top and bottom rows are white */
158    grid[0] = grid[15] = 0x0000;
159
160    /* 14 inner rows are 14-pixel wide black lines, centered */
161    for (row = 1; row < 15; row++) grid[row] = 0x7FFE;
162
163    printf ("%04X:", thiscp);
164
165    /*
166       Render the first row of 2 hexadecimal digits
167    */
168    digitrow = 0; /* start at top of first row of digits to render */
169    for (row = 2; row < 7; row++) {
170       rowbits = (hexdigit[d1][digitrow] << 9) |
171                 (hexdigit[d2][digitrow] << 3);
172       grid[row] ^= rowbits; /* digits appear as white on black background */
173       digitrow++;
174    }
175
176    /*
177       Render the second row of 2 hexadecimal digits
178    */
179    digitrow = 0; /* start at top of first row of digits to render */
180    for (row = 9; row < 14; row++) {
181       rowbits = (hexdigit[d3][digitrow] << 9) |
182                 (hexdigit[d4][digitrow] << 3);
183       grid[row] ^= rowbits; /* digits appear as white on black background */
184       digitrow++;
185    }
186
187    for (row = 0; row < 16; row++) printf ("%04X", grid[row] & 0xFFFF);
188
189    putchar ('\n');
190
191    return;
192 }
193
194
195 /*
196    Takes a 6-digit Unicode code point as an argument
197    and prints a unifont.hex string for it to stdout.
198 */
199 void
200 hexprint6 (int thiscp)
201 {
202
203    int grid[16]; /* the glyph grid we'll build */
204
205    int row;      /* row number in current glyph */
206    int digitrow; /* row number in current hex digit being rendered */
207    int rowbits;  /* 1 & 0 bits to draw current glyph row */
208
209    int d1, d2, d3, d4, d5, d6; /* six hexadecimal digits of each code point */
210
211    d1 = (thiscp >> 20) & 0xF;
212    d2 = (thiscp >> 16) & 0xF;
213    d3 = (thiscp >> 12) & 0xF;
214    d4 = (thiscp >>  8) & 0xF;
215    d5 = (thiscp >>  4) & 0xF;
216    d6 = (thiscp      ) & 0xF;
217
218    /* top and bottom rows are white */
219    grid[0] = grid[15] = 0x0000;
220
221    /* 14 inner rows are 16-pixel wide black lines, centered */
222    for (row = 1; row < 15; row++) grid[row] = 0xFFFF;
223
224
225    printf ("%06X:", thiscp);
226
227    /*
228       Render the first row of 3 hexadecimal digits
229    */
230    digitrow = 0; /* start at top of first row of digits to render */
231    for (row = 2; row < 7; row++) {
232       rowbits = (hexdigit[d1][digitrow] << 11) |
233                 (hexdigit[d2][digitrow] <<  6) |
234                 (hexdigit[d3][digitrow] <<  1);
235       grid[row] ^= rowbits; /* digits appear as white on black background */
236       digitrow++;
237    }
238
239    /*
240       Render the second row of 3 hexadecimal digits
241    */
242    digitrow = 0; /* start at top of first row of digits to render */
243    for (row = 9; row < 14; row++) {
244       rowbits = (hexdigit[d4][digitrow] << 11) |
245                 (hexdigit[d5][digitrow] <<  6) |
246                 (hexdigit[d6][digitrow] <<  1);
247       grid[row] ^= rowbits; /* digits appear as white on black background */
248       digitrow++;
249    }
250
251    for (row = 0; row < 16; row++) printf ("%04X", grid[row] & 0xFFFF);
252
253    putchar ('\n');
254
255    return;
256 }
257