1/***********************************************************************
2 *                                                                     *
3 * $Id: hpgsmkrop.c 270 2006-01-29 21:12:23Z softadm $
4 *                                                                     *
5 * hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript   *
6 *        API for rendering a scene and thus renders to a variety of   *
7 *        devices and fileformats.                                     *
8 *                                                                     *
9 * (C) 2004-2006 ev-i Informationstechnologie GmbH  http://www.ev-i.at *
10 *                                                                     *
11 * Author: Wolfgang Glas                                               *
12 *                                                                     *
13 *  hpgs is free software; you can redistribute it and/or              *
14 * modify it under the terms of the GNU Lesser General Public          *
15 * License as published by the Free Software Foundation; either        *
16 * version 2.1 of the License, or (at your option) any later version.  *
17 *                                                                     *
18 * hpgs is distributed in the hope that it will be useful,             *
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   *
21 * Lesser General Public License for more details.                     *
22 *                                                                     *
23 * You should have received a copy of the GNU Lesser General Public    *
24 * License along with this library; if not, write to the               *
25 * Free Software  Foundation, Inc., 59 Temple Place, Suite 330,        *
26 * Boston, MA  02111-1307  USA                                         *
27 *                                                                     *
28 ***********************************************************************
29 *                                                                     *
30 * A small programm, which generates the raster operations hpgsrop.c   *
31 *                                                                     *
32 ***********************************************************************/
33
34#include <stdio.h>
35#include <stdarg.h>
36#include <string.h>
37#include <time.h>
38#include <errno.h>
39
40#ifdef __GNUC__
41__attribute__((format(printf,4,5)))
42#endif
43static int apprintf (char *str, size_t str_sz, size_t *str_len,
44                     const char *fmt, ...)
45{
46  int n;
47  va_list ap;
48
49  va_start(ap, fmt);
50
51  n = vsnprintf(str+*str_len,str_sz-*str_len,fmt,ap);
52
53  va_end(ap);
54
55  if (n<0) { perror("snprintf"); return -1; }
56  *str_len+=n;
57
58  return 0;
59}
60
61static void mk_operand (char *operand, size_t operand_sz, const char *stack, int i)
62{
63  switch (stack[i])
64    {
65    case 'D':
66      strcpy(operand,"*D");
67      break;
68    case 'S':
69    case 'T':
70      operand[0] = stack[i];
71      operand[1] = '\0';
72      break;
73    default:
74      snprintf(operand,operand_sz,"stk%d",i+1);
75    }
76}
77
78static void mk_xoperand (char *operand, size_t operand_sz, const char *stack, int i)
79{
80  switch (stack[i])
81    {
82    case 'D':
83      strcpy(operand,"D");
84      break;
85    case 'S':
86    case 'T':
87      operand[0] = stack[i];
88      operand[1] = '\0';
89      break;
90    default:
91      snprintf(operand,operand_sz,"stk%d",i+1);
92    }
93}
94
95/*
96  This function converts a ROP3 description cf. to
97
98    PCL 5 Comparison Guide, Edition 2, 6/2003, Hewlett Packard
99    (May be downloaded as bpl13206.pdf from http://www.hp.com)
100
101  into 4 C-programs for all transparency modes supported by
102  HPGL/2 and PCL.
103
104  Additional information may be found under
105
106    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50grfTernaryRasterOperations.asp
107
108  (especially typos in HP's documentation are corrected from
109   this source of information).
110
111*/
112static int write_rop3_func(FILE *out, int irop, const char *ropstr)
113{
114  int stacksz = 0;
115  int max_stacksz = 0;
116  char stack[32];
117  char operand[32];
118  char operand2[32];
119  const char *c;
120
121  int D_used = 0;
122  int S_used = 0;
123  int T_used = 0;
124
125  char defn[2048],op;
126  size_t defn_len=0;
127  char xdefn[2048];
128  size_t xdefn_len=0;
129  int i;
130
131  defn[0] = '\0';
132  xdefn[0] = '\0';
133
134  for (c=ropstr;*c;++c)
135    switch (*c)
136      {
137      case '0':
138      case '1':
139        i = (*c == '0') ? 0 : 255;
140        max_stacksz = stacksz = 1;
141
142        if (c!=ropstr || *(c+1))
143          {
144            fprintf (stderr,"Misplaced %c in rop string %s.\n",
145                     *c,ropstr);
146            return -1;
147          }
148
149        if (apprintf(defn,sizeof(defn),&defn_len,
150                     "  stk1 = %d;\n",i ))
151         return -1;
152
153        if (apprintf(xdefn,sizeof(xdefn),&xdefn_len,
154                     "  stk1 = %s;\n", (*c == '0') ? "0x0000" : "0xffff"))
155          return -1;
156
157        break;
158
159      case 'S':
160      case 'T':
161      case 'D':
162        if (stacksz >= sizeof(stack)-1)
163          {
164            fprintf (stderr,"Stack overflow in rop string %s.\n",ropstr);
165            return -1;
166          }
167
168        stack[stacksz] = *c;
169        ++stacksz;
170
171        if (*c == 'D')
172          D_used = 1;
173
174        if (*c == 'T')
175          T_used = 1;
176
177        if (*c == 'S')
178          S_used = 1;
179        break;
180
181      case 'o':
182      case 'a':
183      case 'x':
184        if (stacksz<1)
185          {
186            fprintf (stderr,"Stack underflow in rop string %s.\n",ropstr);
187            return -1;
188          }
189
190        mk_operand(operand,sizeof(operand),stack,stacksz-2);
191        mk_operand(operand2,sizeof(operand),stack,stacksz-1);
192
193        op = (*c == 'o') ? '|' : ((*c == 'a') ? '&' : '^');
194
195        if (apprintf(defn,sizeof(defn),&defn_len,
196                     "  stk%d = %s %c %s;\n",
197                     stacksz-1,operand,op,operand2 ))
198          return -1;
199
200        mk_xoperand(operand,sizeof(operand),stack,stacksz-2);
201        mk_xoperand(operand2,sizeof(operand),stack,stacksz-1);
202
203        if (apprintf(xdefn,sizeof(xdefn),&xdefn_len,
204                     "  stk%d = %s %c %s;\n",
205                     stacksz-1,operand,op,operand2 ))
206          return -1;
207
208        --stacksz;
209        // account for the max intermediate result on the stack.
210        if (stacksz > max_stacksz) max_stacksz = stacksz;
211
212        stack[stacksz-1] = '\0';
213        break;
214
215      case 'n':
216        mk_operand(operand,sizeof(operand),stack,stacksz-1);
217
218        if (apprintf(defn,sizeof(defn),&defn_len,
219                     "  stk%d = ~%s;\n",
220                     stacksz,operand ))
221          return -1;
222
223        mk_xoperand(operand,sizeof(operand),stack,stacksz-1);
224
225        if (apprintf(xdefn,sizeof(xdefn),&xdefn_len,
226                     "  stk%d = ~%s;\n",
227                     stacksz,operand ))
228          return -1;
229
230        // account for the max intermediate result on the stack.
231        if (stacksz > max_stacksz) max_stacksz = stacksz;
232
233        stack[stacksz-1] = '\0';
234        break;
235
236      default:
237        fprintf (stderr,"Illegal character %c in rop string %s.\n",
238                 *c,ropstr);
239        return -1;
240      }
241
242  if (stacksz!=1)
243    {
244      fprintf (stderr,"Unbalanced shift/reduce in rop string %s.\n",ropstr);
245      return -1;
246    }
247
248  mk_operand(operand,sizeof(operand),stack,0);
249
250  // ******** normal ROP functions
251  // case 1: source/pattern opaque.
252  fprintf (out,
253           "/* %s source/pattern opaque. */\n"
254           "static void rop3_%d_0_0 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
255           ropstr,irop);
256
257  for (i=1;i<=max_stacksz;++i)
258    fprintf(out,"  unsigned char stk%d;\n",i);
259
260  fputs(defn,out);
261
262  // optimize for noop.
263  if (stack[0] != 'D')
264    fprintf(out,"  *D = %s;\n",operand);
265
266  fprintf(out,"}\n\n");
267
268  // case 2: source opaque/pattern transparent.
269  fprintf (out,
270           "/* %s source opaque/pattern transparent. */\n"
271           "static void rop3_%d_0_1 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
272           ropstr,irop);
273
274  for (i=1;i<=max_stacksz;++i)
275    fprintf(out,"  unsigned char stk%d;\n",i);
276
277  fputs(defn,out);
278
279  // Image_A = Temporary_ROP3, & Not Src.
280  // Image_B = Temporary_ROP3 & Pattern.
281  // Image_C = Not Pattern & Src & Dest.
282  // Return Image_A | Image_B | Image_C
283  fprintf(out,"  *D = (%s & S) | (%s & (~T)) | (T & (~S) & *D);\n",operand,operand);
284
285  fprintf(out,"}\n\n");
286
287  // case 3: source transparent/pattern opaque.
288  fprintf (out,
289           "/* %s source transparent/pattern opaque. */\n"
290           "static void rop3_%d_1_0 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
291           ropstr,irop);
292
293  for (i=1;i<=max_stacksz;++i)
294    fprintf(out,"  unsigned char stk%d;\n",i);
295
296  fputs(defn,out);
297
298  // Image_A = Temporary_ROP3 & Src.
299  // Image_B = Dest & Not Src.
300  // Return Image_A | Image_B
301  fprintf(out,"  *D = (%s & (~S)) | (*D & S);\n",operand);
302
303  fprintf(out,"}\n\n");
304
305  // case 4: source/pattern transparent.
306  fprintf (out,
307           "/* %s source/pattern transparent. */\n"
308           "static void rop3_%d_1_1 (unsigned char *D, unsigned char S, unsigned char T)\n{\n",
309           ropstr,irop);
310
311  for (i=1;i<=max_stacksz;++i)
312    fprintf(out,"  unsigned char stk%d;\n",i);
313
314  fputs(defn,out);
315  // Image_A = Temporary_ROP3 & Src & Pattern.
316  // Image_B = Dest & Not Src.
317  // Image_C = Dest & Not Pattern.
318  // Return Image_A | Image_B | Image_C.
319  fprintf(out,"  *D = (%s & (~S) & (~T)) | (*D & S) | (*D & T);\n",operand);
320
321  fprintf(out,"}\n\n");
322
323  // ******** ROP transfer functions
324  mk_xoperand(operand,sizeof(operand),stack,0);
325  // case 1: source/pattern opaque.
326  fprintf (out,
327           "/* %s source/pattern opaque. */\n"
328           "static unsigned xrop3_%d_0_0 (unsigned char s, unsigned char t)\n{\n",
329           ropstr,irop);
330
331  if (D_used)
332    fprintf (out,"  unsigned D = 0x00ff;\n");
333  if (S_used)
334    fprintf (out,"  unsigned S = ((unsigned)s << 8) | s;\n");
335  if (T_used)
336    fprintf (out,"  unsigned T = ((unsigned)t << 8) | t;\n");
337
338  for (i=1;i<=max_stacksz;++i)
339    fprintf(out,"  unsigned stk%d;\n",i);
340
341  fputs(xdefn,out);
342
343  fprintf(out,"  return %s;\n",operand);
344
345  fprintf(out,"}\n\n");
346
347  // case 2: source opaque/pattern transparent.
348  fprintf (out,
349           "/* %s source opaque/pattern transparent. */\n"
350           "static unsigned xrop3_%d_0_1 (unsigned char s, unsigned char t)\n{\n",
351           ropstr,irop);
352
353  fprintf (out,"  unsigned D = 0x00ff;\n");
354  fprintf (out,"  unsigned S = ((unsigned)s << 8) | s;\n");
355  fprintf (out,"  unsigned T = ((unsigned)t << 8) | t;\n");
356
357  for (i=1;i<=max_stacksz;++i)
358    fprintf(out,"  unsigned stk%d;\n",i);
359
360  fputs(xdefn,out);
361
362  // Image_A = Temporary_ROP3, & Not Src.
363  // Image_B = Temporary_ROP3 & Pattern.
364  // Image_C = Not Pattern & Src & Dest.
365  // Return Image_A | Image_B | Image_C
366  fprintf(out,"  return (%s & S) | (%s & (~T)) | (T & (~S) & D);\n",operand,operand);
367
368  fprintf(out,"}\n\n");
369
370  // case 3: source transparent/pattern opaque.
371  fprintf (out,
372           "/* %s source transparent/pattern opaque. */\n"
373           "static unsigned xrop3_%d_1_0 (unsigned char s, unsigned char t)\n{\n",
374           ropstr,irop);
375
376  fprintf (out,"  unsigned D = 0x00ff;\n");
377  fprintf (out,"  unsigned S = ((unsigned)s << 8) | s;\n");
378  if (T_used)
379    fprintf (out,"  unsigned T = ((unsigned)t << 8) | t;\n");
380
381  for (i=1;i<=max_stacksz;++i)
382    fprintf(out,"  unsigned stk%d;\n",i);
383
384  fputs(xdefn,out);
385
386  // Image_A = Temporary_ROP3 & Src.
387  // Image_B = Dest & Not Src.
388  // Return Image_A | Image_B
389  fprintf(out,"  return (%s & (~S)) | (D & S);\n",operand);
390
391  fprintf(out,"}\n\n");
392
393  // case 4: source/pattern transparent.
394  fprintf (out,
395           "/* %s source/pattern transparent. */\n"
396           "static unsigned xrop3_%d_1_1 (unsigned char s, unsigned char t)\n{\n",
397           ropstr,irop);
398
399  fprintf (out,"  unsigned D = 0x00ff;\n");
400  fprintf (out,"  unsigned S = ((unsigned)s << 8) | s;\n");
401  fprintf (out,"  unsigned T = ((unsigned)t << 8) | t;\n");
402
403  for (i=1;i<=max_stacksz;++i)
404    fprintf(out,"  unsigned stk%d;\n",i);
405
406  fputs(xdefn,out);
407  // Image_A = Temporary_ROP3 & Src & Pattern.
408  // Image_B = Dest & Not Src.
409  // Image_C = Dest & Not Pattern.
410  // Return Image_A | Image_B | Image_C.
411  fprintf(out,"  return (%s & (~S) & (~T)) | (D & S) | (D & T);\n",operand);
412
413  fprintf(out,"}\n\n");
414
415  return 0;
416}
417
418int main (int argc, const char *argv[])
419{
420  FILE *in=0;
421  FILE *out=0;
422  int irop=0,i;
423  char ropstr[32];
424  int ret = 0;
425  time_t now;
426
427  if (argc != 3)
428    {
429      fprintf(stderr,"usage: %s <in> <out>.\n",argv[0]);
430      return 1;
431    }
432
433  in = fopen(argv[1],"rb");
434
435  if (!in)
436    {
437      fprintf(stderr,"%s: Error opening file <%s>: %s.\n",
438              argv[0],argv[1],strerror(errno));
439      ret = 1;
440      goto cleanup;
441    }
442
443  out = fopen(argv[2],"wb");
444
445  if (!out)
446    {
447      fprintf(stderr,"%s: Error opening file <%s>: %s.\n",
448              argv[0],argv[2],strerror(errno));
449      ret = 1;
450      goto cleanup;
451    }
452
453  now = time(0);
454  fprintf(out,"/* Generated automatically by %s at %.24s.\n",argv[0],ctime(&now));
455  fprintf(out,"   Do not edit!\n");
456  fprintf(out," */\n");
457  fprintf(out,"#include <hpgs.h>\n\n");
458
459
460  // go through all ROP descritions in hpgsrop.dat
461  while (fscanf(in,"%d %31s",&i,ropstr) == 2)
462    {
463      if (i!=irop)
464        {
465          fprintf(stderr,"%s: Illegal count %d in stanza %d.\n",
466                  argv[0],i,irop);
467          ret = 1;
468          goto cleanup;
469        }
470
471      if (write_rop3_func(out,irop,ropstr))
472        goto cleanup;
473
474      ++irop;
475    }
476
477  // Collect all rop function in one big lookup table...
478  fprintf(out,
479          "static hpgs_rop3_func_t rop3_table[][2][2] = {\n");
480
481  for (i=0;i<irop;++i)
482    fprintf(out,
483            "  {{rop3_%d_0_0,rop3_%d_0_1},{rop3_%d_1_0,rop3_%d_1_1}}%s\n",
484            i,i,i,i,i<irop-1 ? "," : "");
485
486  fprintf(out,
487          "};\n\n");
488
489  // generate our public interface hpgs_rop3_func.
490  fprintf(out,
491          "hpgs_rop3_func_t hpgs_rop3_func(int rop3,\n"
492          "                                hpgs_bool src_transparency,\n"
493          "                                hpgs_bool pattern_transparency)\n"
494          "{\n"
495          "  if (rop3 < 0 || rop3 >= %d) return 0;\n"
496          "  return rop3_table[rop3][src_transparency!=0][pattern_transparency!=0];\n"
497          "}\n",
498          irop);
499
500  // Collect all rop xfer function in one big lookup table...
501  fprintf(out,
502          "static hpgs_xrop3_func_t xrop3_table[][2][2] = {\n");
503
504  for (i=0;i<irop;++i)
505    fprintf(out,
506            "  {{xrop3_%d_0_0,xrop3_%d_0_1},{xrop3_%d_1_0,xrop3_%d_1_1}}%s\n",
507            i,i,i,i,i<irop-1 ? "," : "");
508
509  fprintf(out,
510          "};\n\n");
511
512  // generate our public interface hpgs_xrop3_func.
513  fprintf(out,
514          "hpgs_xrop3_func_t hpgs_xrop3_func(int rop3,\n"
515          "                                  hpgs_bool src_transparency,\n"
516          "                                  hpgs_bool pattern_transparency)\n"
517          "{\n"
518          "  if (rop3 < 0 || rop3 >= %d) return 0;\n"
519          "  return xrop3_table[rop3][src_transparency!=0][pattern_transparency!=0];\n"
520          "}\n",
521          irop);
522
523 cleanup:
524  if (in) fclose(in);
525  if (out) fclose(out);
526  return ret;
527}
528