genht.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: genht.c,v 1.5 2005/10/04 06:30:02 ray Exp $ */
  14. /* Generate C code for compiling halftones into ROM. */
  15. #include "malloc_.h"
  16. #include "stdio_.h"
  17. #include "string_.h"
  18. #include "gscdefs.h"
  19. #include "gsmemory.h"
  20. #include "gxbitmap.h"
  21. #include "gxhttile.h"
  22. #include "gxtmap.h"
  23. #include "gxdht.h"
  24. #include "gxdhtres.h"
  25. #include "strimpl.h"
  26. #include "sstring.h"
  27. /*
  28. * This program translates PostScript halftone resources into C data
  29. * structures that can then be compiled into executables and put in shared,
  30. * read-only memory. The syntax of the resource file is a subset of
  31. * PostScript, tightly constrained so that it can be parsed easily. Blank
  32. * lines and PostScript comments are ignored, but otherwise each halftone
  33. * in the file (there may be more than one) must follow this format,
  34. * where ... indicates arbitrary text:
  35. (optionally:)
  36. /halftone_name ...
  37. /HalftoneType 5
  38. (zero or more times:)
  39. /halftone_name ...
  40. /HalftoneType 3
  41. /Width xxx
  42. /Height xxx
  43. /Thresholds ...
  44. --hex data terminated by a >--
  45. (zero or more times:)
  46. /halftone_name 1 index
  47. (finally)
  48. ... defineresource
  49. * Lines that don't follow the above syntax may appear anywhere in the file
  50. * except in the middle of the hex data. Width and Height must precede
  51. * Thresholds, but otherwise the 4 parameters may appear in any order.
  52. * White space at the beginning or end of a line is ignored, and any
  53. * amount of white space may separate the parameter name from its value.
  54. *
  55. * We envision that this format will eventually be extended to cover
  56. * HalftoneType 16 halftones with a single rectangle, allowing 16-bit
  57. * threshold values.
  58. */
  59. /* Read a source file into memory. */
  60. private char *
  61. read_file(FILE *in, char *cname)
  62. {
  63. int len, nread;
  64. char *cont;
  65. fseek(in, 0L, 2 /*SEEK_END*/);
  66. len = ftell(in);
  67. cont = malloc(len + 1);
  68. if (cont == 0) {
  69. fprintf(stderr, "Can't allocate %d bytes to read %s.\n",
  70. len + 1, cname);
  71. return 0;
  72. }
  73. rewind(in);
  74. nread = fread(cont, 1, len, in);
  75. cont[nread] = 0;
  76. return cont;
  77. }
  78. /* Parse a Halftone resource file into memory. */
  79. private bool
  80. parse_line(char **pstr, char **pline)
  81. {
  82. char *str = *pstr;
  83. top:
  84. while (*str && strchr(" \t\r\n", *str)) /* trim leading space */
  85. ++str;
  86. if (*str == 0) {
  87. *pline = 0;
  88. return false;
  89. }
  90. *pline = str;
  91. while (*str && !strchr("\r\n", *str)) /* find EOL */
  92. ++str;
  93. while (str > *pline && strchr(" \t", str[-1])) /* trim trailing space */
  94. --str;
  95. *str = 0;
  96. *pstr = str + 1;
  97. return true;
  98. }
  99. private int
  100. parse_halftone(gx_device_halftone_resource_t *phtr, byte **pThresholds,
  101. char **pprefix, char **pcont)
  102. {
  103. char *str;
  104. char *line;
  105. char *rname = 0;
  106. int HalftoneType = -1;
  107. int Width = -1, Height = -1;
  108. byte *Thresholds = 0;
  109. stream_AXD_state ss;
  110. /* Parse the file. */
  111. for (str = *pcont; parse_line(&str, &line);) {
  112. char *end;
  113. char *prefix;
  114. char terminator;
  115. if (line[0] == '%')
  116. continue;
  117. if (strlen(line) >= 14 &&
  118. !strcmp(line + strlen(line) - 14, "defineresource")
  119. )
  120. break;
  121. if (line[0] != '/')
  122. continue;
  123. if (strlen(line) >= 8 &&
  124. !strcmp(line + strlen(line) - 8, " 1 index")
  125. )
  126. continue;
  127. end = ++line;
  128. while (*end && !strchr(" \t<", *end)) /* find end of name */
  129. ++end;
  130. terminator = *end;
  131. *end = 0;
  132. if (rname == 0) { /* first name is halftone name */
  133. rname = malloc(strlen(line) + 1);
  134. strcpy(rname, line);
  135. continue;
  136. }
  137. if (terminator == 0) /* name alone */
  138. continue;
  139. ++end;
  140. if (!strcmp(line, "HalftoneType")) {
  141. if (sscanf(end, "%d", &HalftoneType) != 1) {
  142. fprintf(stderr, "Invalid HalftoneType syntax: %s\n", line - 1);
  143. return -1;
  144. }
  145. switch (HalftoneType) {
  146. case 3:
  147. break;
  148. case 5:
  149. if (*pprefix)
  150. free(*pprefix);
  151. *pprefix = rname;
  152. rname = 0;
  153. break;
  154. default:
  155. fprintf(stderr, "Invalid HalftoneType: %s\n", end);
  156. return -1;
  157. }
  158. continue;
  159. } else if (!strcmp(line, "Width")) {
  160. if (sscanf(end, "%d", &Width) != 1 ||
  161. Width <= 0 || Width > 0x4000
  162. ) {
  163. fprintf(stderr, "Invalid Width: %s\n", end);
  164. return -1;
  165. }
  166. } else if (!strcmp(line, "Height")) {
  167. if (sscanf(end, "%d", &Height) != 1 ||
  168. Height <= 0 || Height > 0x4000
  169. ) {
  170. fprintf(stderr, "Invalid Height: %s\n", end);
  171. return -1;
  172. }
  173. } else if (!strcmp(line, "Thresholds")) {
  174. uint ignore;
  175. uint num_levels = 256;
  176. uint num_bits = Width * Height;
  177. char *eol = end + strlen(end); /* skip rest of line */
  178. stream_cursor_read r;
  179. stream_cursor_write w;
  180. if (Width < 0 || Height < 0) {
  181. fprintf(stderr, "Width and Height must precede Thresholds.\n");
  182. return -1;
  183. }
  184. phtr->num_levels = num_levels;
  185. phtr->levels =
  186. malloc(num_levels * sizeof(*phtr->levels));
  187. phtr->bit_data =
  188. malloc(num_bits * sizeof(ushort));
  189. Thresholds = malloc(num_bits);
  190. s_AXD_init_inline(&ss);
  191. r.ptr = (const byte *)eol;
  192. r.limit = (const byte *)eol + strlen(eol + 1);
  193. w.ptr = Thresholds - 1;
  194. w.limit = w.ptr + num_bits;
  195. s_AXD_template.process((stream_state *)&ss, &r, &w, true);
  196. str = (char *)r.ptr + 1;
  197. break;
  198. }
  199. }
  200. /* Check for successful parsing. */
  201. if (rname == 0)
  202. return 1; /* end of definitions */
  203. if (HalftoneType < 0)
  204. fprintf(stderr, "HalftoneType not found.\n");
  205. if (Width < 0)
  206. fprintf(stderr, "Width not found.\n");
  207. if (Height < 0)
  208. fprintf(stderr, "Height not found.\n");
  209. if (Thresholds == 0)
  210. fprintf(stderr, "Thresholds not found.\n");
  211. if (rname == 0 || Thresholds == 0)
  212. return -1;
  213. phtr->rname = rname;
  214. phtr->HalftoneType = HalftoneType;
  215. phtr->Width = Width;
  216. phtr->Height = Height;
  217. *pThresholds = Thresholds;
  218. *pcont = str;
  219. return 0;
  220. }
  221. /* Write a halftone as a C procedure. */
  222. private int
  223. write_halftone(FILE *out, gx_device_halftone_resource_t *phtr,
  224. const char *prefix, int index)
  225. {
  226. int num_bits = phtr->Width * phtr->Height;
  227. int i;
  228. /* Write the initial comment. */
  229. fputs("\n/* ", out);
  230. if (prefix)
  231. fprintf(out, "%s.", prefix);
  232. fprintf(out, "%s */\n", phtr->rname);
  233. /* Write the levels array. */
  234. fprintf(out, "static const unsigned int levels_%d[] = {", index);
  235. for (i = 0; i < phtr->num_levels; ++i) {
  236. if (i % 10 == 0)
  237. fputs("\n", out);
  238. fprintf(out, "%5u,", phtr->levels[i]);
  239. }
  240. fputs("\n0};\n", out);
  241. /* Write the bit_data array. */
  242. fprintf(out, "static const unsigned short bit_data_%d[] = {", index);
  243. for (i = 0; i < num_bits; ++i) {
  244. if (i % 10 == 0)
  245. fputs("\n", out);
  246. fprintf(out, "%5u,", ((const ushort *)phtr->bit_data)[i]);
  247. }
  248. fputs("\n0};\n", out);
  249. /* Write the top-level structure. */
  250. fprintf(out, "static const gx_device_halftone_resource_t res_%d = {\n \"%s\", %d, %d, %d, %d, levels_%d, bit_data_%d, %u\n};\n",
  251. index, phtr->rname, phtr->HalftoneType, phtr->Width, phtr->Height,
  252. phtr->num_levels, index, index,
  253. ht_order_procs_short.bit_data_elt_size);
  254. return 0;
  255. }
  256. /* Main program */
  257. int
  258. main(int argc, char *argv[])
  259. {
  260. char *iname;
  261. FILE *in;
  262. char *oname;
  263. FILE *out;
  264. int code;
  265. char *cont;
  266. char *line;
  267. gx_device_halftone_resource_t res;
  268. char *prefix = 0;
  269. byte *Thresholds;
  270. gx_ht_order order;
  271. int index, i;
  272. if (argc != 3) {
  273. fprintf(stderr, "Usage: genht ht_res.ps ht_data.c\n");
  274. exit(1);
  275. }
  276. iname = argv[1];
  277. oname = argv[2];
  278. in = fopen(iname, "rb");
  279. if (in == 0) {
  280. in = fopen(iname, "r");
  281. if (in == 0) {
  282. fprintf(stderr, "Can't read %s.\n", iname);
  283. exit(1);
  284. }
  285. }
  286. cont = read_file(in, iname);
  287. if (cont == 0)
  288. exit(1);
  289. fclose(in);
  290. out = fopen(oname, "w");
  291. if (out == 0) {
  292. fprintf(stderr, "Can't open %s for output.\n", oname);
  293. exit(1);
  294. }
  295. fprintf(out, "/*\n * This file %s was generated from %s by genht.\n * Do not edit this file.\n *\n", oname, iname);
  296. /* Copy initial comments from the input file. */
  297. while (parse_line(&cont, &line) && line[0] == '%')
  298. if (line[1] != '!')
  299. fprintf(out, " * %s\n", line + 1);
  300. cont[-1] = '\n';
  301. cont = line;
  302. fputs(" */\n#include \"gxdhtres.h\"\n", out);
  303. for (index = 0;
  304. (code = parse_halftone(&res, &Thresholds, &prefix, &cont)) == 0;
  305. ++index) {
  306. order.width = res.Width;
  307. order.num_levels = res.num_levels;
  308. order.levels = (uint *)res.levels;
  309. order.num_bits = res.Width * res.Height;
  310. order.bit_data = (void *)res.bit_data;
  311. ht_order_procs_short.construct_order(&order, Thresholds);
  312. write_halftone(out, &res, prefix, index);
  313. }
  314. if (prefix == 0)
  315. prefix = res.rname;
  316. fputs("/* Check the prototype. */\n", out);
  317. fprintf(out, "DEVICE_HALFTONE_RESOURCE_PROC(gs_dht_%s);\n", prefix);
  318. fputs("\nconst gx_device_halftone_resource_t *const *\n", out);
  319. fprintf(out, "gs_dht_%s(void)\n{\n static const gx_device_halftone_resource_t *const res[] = {\n\t",
  320. prefix);
  321. for (i = 0; i < index; ++i)
  322. fprintf(out, "&res_%d, ", i);
  323. fputs("0\n };\n return res;\n}\n", out);
  324. fclose(out);
  325. if (code < 0)
  326. exit(1);
  327. return 0;
  328. }
  329. /* Stubs */
  330. ENUM_PTRS_BEGIN_PROC(gs_no_struct_enum_ptrs)
  331. {
  332. return 0;
  333. ENUM_PTRS_END_PROC
  334. }
  335. RELOC_PTRS_BEGIN(gs_no_struct_reloc_ptrs)
  336. {
  337. }
  338. RELOC_PTRS_END
  339. public_st_stream_state();
  340. void
  341. gx_ht_complete_threshold_order(gx_ht_order *porder)
  342. {
  343. }
  344. /*
  345. * In order to avoid a linking step, we #include the required files here
  346. * rather than compiling them separately.
  347. */
  348. #include "gxhtbit.c"
  349. #include "scantab.c"
  350. #include "sstring.c"
  351. const gx_dht_proc gx_device_halftone_list[] = { 0 };