xref: /plan9-contrib/sys/src/cmd/gs/src/scfdgen.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
1 /* Copyright (C) 1992, 1994, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This file is part of AFPL Ghostscript.
4 
5   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
6   distributor accepts any responsibility for the consequences of using it, or
7   for whether it serves any particular purpose or works at all, unless he or
8   she says so in writing.  Refer to the Aladdin Free Public License (the
9   "License") for full details.
10 
11   Every copy of AFPL Ghostscript must include a copy of the License, normally
12   in a plain ASCII text file named PUBLIC.  The License grants you the right
13   to copy, modify and redistribute AFPL Ghostscript, but only under certain
14   conditions described in the License.  Among other things, the License
15   requires that the copyright notice and this notice be preserved on all
16   copies.
17 */
18 
19 /*$Id: scfdgen.c,v 1.2 2000/09/19 19:00:48 lpd Exp $ */
20 /* Generate the CCITTFaxDecode tables */
21 #include "stdio_.h"		/* includes std.h */
22 #include "scf.h"
23 #include "malloc_.h"
24 #include "memory_.h"
25 
26 typedef void (*cfd_node_proc) (P6(cfd_node *, cfd_node *,
27 				  uint, int, int, int));
28 typedef void (*cfd_enum_proc) (P4(cfd_node_proc,
29 				  cfd_node *, cfd_node *, int));
30 private void cfd_build_tree(P4(cfd_node *, cfd_enum_proc, int, FILE *));
31 private void cfd_enumerate_white(P4(cfd_node_proc,
32 				    cfd_node *, cfd_node *, int));
33 private void cfd_enumerate_black(P4(cfd_node_proc,
34 				    cfd_node *, cfd_node *, int));
35 private void cfd_enumerate_2d(P4(cfd_node_proc,
36 				 cfd_node *, cfd_node *, int));
37 private void cfd_enumerate_uncompressed(P4(cfd_node_proc,
38 					   cfd_node *, cfd_node *, int));
39 
40 main()
41 {
42     FILE *out = fopen("scfdtab.c", "w");
43     cfd_node area[1 << max(cfd_white_initial_bits, cfd_black_initial_bits)];
44 
45     fputs("/* Copyright (C) 1992, 1993, 1998, 1999 Aladdin Enterprises.  All rights reserved. */\n\n", out);
46     fputs("/* $Id: scfdgen.c,v 1.2 2000/09/19 19:00:48 lpd Exp $ */\n", out);
47     fputs("/* Tables for CCITTFaxDecode filter. */\n\n", out);
48     fputs("/* This file was generated automatically.  It is governed by the same terms */\n", out);
49     fputs("/* as the files scfetab.c and scfdgen.c from which it was derived. */\n", out);
50     fputs("/* Consult those files for the licensing terms and conditions. */\n\n", out);
51     fputs("#include \"std.h\"\n", out);
52     fputs("#include \"scommon.h\"\t\t/* for scf.h */\n", out);
53     fputs("#include \"scf.h\"\n\n", out);
54     fputs("/* White decoding table. */\n", out);
55     fputs("const cfd_node cf_white_decode[] = {\n", out);
56     cfd_build_tree(area, cfd_enumerate_white, cfd_white_initial_bits, out);
57     fputs("\n};\n\n", out);
58     fputs("/* Black decoding table. */\n", out);
59     fputs("const cfd_node cf_black_decode[] = {\n", out);
60     cfd_build_tree(area, cfd_enumerate_black, cfd_black_initial_bits, out);
61     fputs("\n};\n\n", out);
62     fputs("/* 2-D decoding table. */\n", out);
63     fputs("const cfd_node cf_2d_decode[] = {\n", out);
64     cfd_build_tree(area, cfd_enumerate_2d, cfd_2d_initial_bits, out);
65     fputs("\n};\n\n", out);
66     fputs("/* Uncompresssed decoding table. */\n", out);
67     fputs("const cfd_node cf_uncompressed_decode[] = {\n", out);
68     cfd_build_tree(area, cfd_enumerate_uncompressed, cfd_uncompressed_initial_bits, out);
69     fputs("\n};\n\n", out);
70     fputs("/* Dummy executable code to pacify compilers. */\n", out);
71     fputs("void scfdtab_dummy(P0());\n", out);
72     fputs("void\nscfdtab_dummy()\n{\n}\n", out);
73     fclose(out);
74     return 0;
75 }
76 
77 /* Initialize first-level leaves, count second-level nodes. */
78 private void
79 cfd_count_nodes(cfd_node * tree, cfd_node * ignore_extn,
80 		uint code, int code_length, int run_length, int initial_bits)
81 {
82     if (code_length <= initial_bits) {
83 	/* Initialize one or more first-level leaves. */
84 	int sh = initial_bits - code_length;
85 	cfd_node *np = &tree[code << sh];
86 	int i;
87 
88 	for (i = 1 << sh; i > 0; i--, np++)
89 	    np->run_length = run_length,
90 		np->code_length = code_length;
91     } else {
92 	/* Note the need for a second level. */
93 	cfd_node *np = &tree[code >> (code_length - initial_bits)];
94 
95 	np->code_length = max(np->code_length, code_length);
96     }
97 }
98 
99 /* Initialize second-level nodes. */
100 private void
101 cfd_init2_nodes(cfd_node * tree, cfd_node * extn,
102 		uint code, int code_length, int run_length, int initial_bits)
103 {
104     int xbits = code_length - initial_bits;
105     int xrep;
106     cfd_node *np1, *np2;
107     int i;
108 
109     if (xbits <= 0)
110 	return;
111     np1 = &tree[code >> xbits];
112     np2 = &extn[np1->run_length - (1 << initial_bits)];
113     xrep = np1->code_length - code_length;
114     i = 1 << xrep;
115     np2 += (code & ((1 << xbits) - 1)) * i;
116     for (; i > 0; i--, np2++)
117 	np2->run_length = run_length,
118 	    np2->code_length = xbits;
119 }
120 
121 /* Enumerate all the relevant white or black codes. */
122 private void
123 cfd_enumerate_codes(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
124 		  int initial_bits, const cfe_run * tt, const cfe_run * mut)
125 {
126     int i;
127     const cfe_run *ep;
128 
129     for (i = 0, ep = tt; i < 64; i++, ep++)
130 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
131     for (i = 1, ep = mut + 1; i < 41; i++, ep++)
132 	(*proc) (tree, extn, ep->code, ep->code_length, i << 6, initial_bits);
133     (*proc) (tree, extn,
134 	     cf1_run_uncompressed.code, cf1_run_uncompressed.code_length,
135 	     run_uncompressed, initial_bits);
136     (*proc) (tree, extn,
137 	     0, run_eol_code_length - 1,
138 	     run_zeros, initial_bits);
139 }
140 private void
141 cfd_enumerate_white(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
142 		    int initial_bits)
143 {
144     cfd_enumerate_codes(proc, tree, extn, initial_bits,
145 			cf_white_runs.termination, cf_white_runs.make_up);
146 }
147 private void
148 cfd_enumerate_black(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
149 		    int initial_bits)
150 {
151     cfd_enumerate_codes(proc, tree, extn, initial_bits,
152 			cf_black_runs.termination, cf_black_runs.make_up);
153 }
154 
155 /* Enumerate the 2-D codes. */
156 private void
157 cfd_enumerate_2d(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
158 		 int initial_bits)
159 {
160     int i;
161     const cfe_run *ep;
162 
163     (*proc) (tree, extn, cf2_run_pass.code, cf2_run_pass.code_length,
164 	     run2_pass, initial_bits);
165     (*proc) (tree, extn, cf2_run_horizontal.code, cf2_run_horizontal.code_length,
166 	     run2_horizontal, initial_bits);
167     for (i = 0; i < countof(cf2_run_vertical); i++) {
168 	ep = &cf2_run_vertical[i];
169 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
170     }
171     (*proc) (tree, extn, cf2_run_uncompressed.code, cf2_run_uncompressed.code_length,
172 	     run_uncompressed, initial_bits);
173     (*proc) (tree, extn, 0, run_eol_code_length - 1, run_zeros, initial_bits);
174 }
175 
176 /* Enumerate the uncompressed codes. */
177 private void
178 cfd_enumerate_uncompressed(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
179 			   int initial_bits)
180 {
181     int i;
182     const cfe_run *ep;
183 
184     for (i = 0; i < countof(cf_uncompressed); i++) {
185 	ep = &cf_uncompressed[i];
186 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
187     }
188     for (i = 0; i < countof(cf_uncompressed_exit); i++) {
189 	ep = &cf_uncompressed_exit[i];
190 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
191     }
192 }
193 
194 /* Build and write out the table. */
195 private void
196 cfd_build_tree(cfd_node * tree, cfd_enum_proc enum_proc, int initial_bits,
197 	       FILE * f)
198 {
199     cfd_node *np;
200     const char *prev = "";
201     int i, next;
202     cfd_node *extn;
203 
204     memset(tree, 0, sizeof(cfd_node) << initial_bits);
205     /* Construct and write the first level of the tree. */
206     (*enum_proc) (cfd_count_nodes, tree, (cfd_node *) 0, initial_bits);
207     next = 0;
208     for (i = 0, np = tree; i < 1 << initial_bits; i++, np++) {
209 	if (np->code_length > initial_bits) {	/* second level needed */
210 	    np->run_length = next + (1 << initial_bits);
211 	    next += 1 << (np->code_length - initial_bits);
212 	}
213 	fprintf(f, "%s\t{ %d, %d }", prev, np->run_length, np->code_length);
214 	prev = ",\n";
215     }
216     /* Construct and write the second level. */
217     extn = (cfd_node *) malloc(sizeof(cfd_node) * next);
218     for (i = 0, np = extn; i < next; i++, np++)
219 	np->run_length = run_error,
220 	    np->code_length = 0;
221     (*enum_proc) (cfd_init2_nodes, tree, extn, initial_bits);
222     for (i = 0, np = extn; i < next; i++, np++)
223 	fprintf(f, ",\n\t{ %d, %d }", np->run_length, np->code_length);
224     free((char *)extn);
225 }
226