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