ATM1.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 1.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 OpenFX Development Team
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 You may contact the OpenFX development team via elecronic mail
00020 at core@openfx.org, or visit our website at http://openfx.org for
00021 further information and support details.
00022 -- */
00023 
00024 /* file ATM1.C   ATM descryption  */
00025 
00026 
00027 /* decryption stuff */
00028 static unsigned short chs_er, chs_cr;
00029 static unsigned short c1 = 52845, c2 = 22719;
00030 static char *key = "currentfile eexec\n";
00031 static point PP[4];
00032 
00033 /* local variables that must be initialized for each font reading */
00034 static char *p_key = 0;
00035 static int first_byte = 1;
00036 static int is_pfa = 0;
00037 static int is_pfb = 0;
00038 static int pfb_remaining = 0;
00039 static int reported = 0;
00040 static int in_eexec = 0;
00041 static int start = 1;
00042 static int start_charstring = 0,in_charstring=0;
00043 static int lenIV = 4;
00044 static int in_EncodingArray = 0;
00045 static int in_Subroutines = 0,n_Subroutines=0,i_Subroutine;
00046 static int StandardEncoding = 0;
00047 /* the program subroutines and the program itself */
00048 static character_program *C_Subs,Cprogram;
00049 
00050 static int eexec_scanner(char c){
00051 /* This function looks for `currentfile eexec' string and returns 1 once found.
00052    If c == 0, then simply check the status. */
00053   if (!p_key)
00054     p_key = key;
00055   if (c && *p_key) {
00056     if (c == *p_key)
00057       ++p_key;
00058     else
00059       p_key = key;
00060   }
00061   return *p_key == '\0';
00062 }
00063 
00064 /* This function returns the value of a single hex digit. */
00065 
00066 static int hexval(char c){
00067   if (c >= 'A' && c <= 'F')
00068     return c - 'A' + 10;
00069   else if (c >= 'a' && c <= 'f')
00070     return c - 'a' + 10;
00071   else if (c >= '0' && c <= '9')
00072     return c - '0';
00073   else
00074     return 0;
00075 }
00076 
00077 /* This function returns a single character at a time from a PFA or PFB file.
00078    This stream is mixed ASCII and binary bytes.  For PFB files, the section
00079    headers are removed, and \r is replaced by \n in ASCII sections.  For PFA
00080    files, the hexdecimal data is turned into binary bytes. */
00081 
00082 static int bgetc(void){
00083   int c, val;
00084 /* is_pfa == 1 means PFA initial ASCII section
00085    is_pfa == 2 means PFA hexadecimal section
00086    is_pfb == 1 means PFB ASCII section
00087    is_pfB == 2 means PFB binary section */
00088   c = fgetc(ifp);
00089   if (c == EOF)
00090     return EOF;
00091   if (first_byte) {
00092     /* Determine if this is a PFA or PFB file by looking at first byte. */
00093     if (c == 0x80) {
00094       is_pfb = 1;
00095       is_pfa = 0;
00096     } else {
00097       is_pfb = 0;
00098       is_pfa = 1;
00099     }
00100     first_byte = 0;
00101   }
00102   if (is_pfb) {
00103     /* PFB */
00104     if (pfb_remaining == 0) {
00105       /* beginning of block---we know c == 0x80 at this point */
00106       switch (fgetc(ifp)) {
00107       case 1:
00108         is_pfb = 1;
00109         break;
00110       case 2:
00111         is_pfb = 2;
00112         break;
00113       case 3:
00114         return EOF;
00115       default:
00116         PS_fail = 1;
00117         return EOF;
00118       }
00119       /* get block length */
00120       pfb_remaining = fgetc(ifp) & 0xff;
00121       pfb_remaining |= (fgetc(ifp) & 0xff) << 8;
00122       pfb_remaining |= (fgetc(ifp) & 0xff) << 16;
00123       pfb_remaining |= (fgetc(ifp) & 0xff) << 24;
00124       /* get character */
00125       c = fgetc(ifp);
00126       if (c == EOF)return EOF;
00127     }
00128     --pfb_remaining;
00129     /* in ASCII section change return to newline */
00130     if (is_pfb == 1 && c == '\r')
00131       c = '\n';
00132     (void)eexec_scanner(c);
00133     return c;
00134   } else {
00135     /* PFA */
00136     if (is_pfa == 1) {
00137       /* in initial ASCII */
00138       if (eexec_scanner(c))is_pfa = 2;
00139       return c;
00140     } else {
00141       /* in hexadecimal */
00142       while (isspace(c))c = fgetc(ifp);
00143       val = hexval((char)c) << 4;
00144       val |= hexval((char)(c = fgetc(ifp)));
00145       if (c == EOF)return EOF;
00146       return val;
00147     }
00148   }
00149 }
00150 
00151 /* Two separate decryption functions because eexec and charstring decryption
00152    must proceed in parallel. */
00153 
00154 static byte edecrypt(byte cipher){
00155   byte plain;
00156   plain = (cipher ^ (chs_er >> 8));
00157   chs_er = (cipher + chs_er) * c1 + c2;
00158   return plain;
00159 }
00160 
00161 static byte cdecrypt(byte cipher){
00162   byte plain;
00163   plain = (cipher ^ (chs_cr >> 8));
00164   chs_cr = (cipher + chs_cr) * c1 + c2;
00165   return plain;
00166 }
00167 
00168 /* This function returns 1 the first time the eexec_scanner returns 1. */
00169 
00170 static int immediate_eexec(void){
00171   if (!reported && eexec_scanner(0)) {
00172     reported = 1;
00173     return 1;
00174   } else {
00175     return 0;
00176   }
00177 }
00178 
00179 /* This function returns a single byte at a time through (possible) eexec
00180    decryption.  When immediate_eexec returns 1 it fires up the eexec decryption
00181    machinery. */
00182 
00183 static int egetc(void){
00184   int c;
00185   if ((c = bgetc()) == EOF)return EOF;
00186   if (!in_eexec) {
00187     if (immediate_eexec()) {
00188       /* start eexec decryption */
00189       in_eexec = 1;
00190       chs_er = 55665;
00191       /* toss out four random bytes */
00192       (void) edecrypt(bgetc());
00193       (void) edecrypt(bgetc());
00194       (void) edecrypt(bgetc());
00195       (void) edecrypt(bgetc());
00196     }
00197     return c;
00198   } else {
00199     return edecrypt(c);
00200   }
00201 }
00202 
00203 /* This function returns a line of eexec decrypted characters.  A line is
00204    terminated by length (including terminating null) greater than LINESIZE, a
00205    newline \n, or one of the special charstring start sequences ` -| ' or
00206    ` RD '.  The line, including the terminating newline or charstring start
00207    sequence is put into load_line[].  If terminated by a charstring start sequence,
00208    the flag start_charstring is set to 1. */
00209 
00210 static void egetline(void){
00211   int c;
00212   char *p = load_line;
00213   start_charstring = 0;
00214   while (p < load_line + LINESIZE) {
00215     c = egetc();
00216     if (c == EOF)
00217       break;
00218     *p++ = (char) c;
00219     if (p >= load_line + 4 && (strncmp(p - 4, " -| ", 4) == 0 ||
00220              strncmp(p - 4, " RD ", 4) == 0)) {
00221       p -= 4;
00222       start_charstring = 1;
00223       break;
00224     }
00225     if(!in_eexec){ /* in ASCII part check for Encoding names */
00226       if (p >= load_line + 5 && (strncmp(p-5," put ",5) == 0 )){
00227         p[-1]='\n';
00228         break;
00229       }
00230     }
00231     if (c == '\r') {      /* map \r to \n */
00232       p[-1] = '\n';
00233       break;
00234     }
00235     if (c == '\n')
00236       break;
00237   }
00238   *p = '\0';
00239 }
00240 
00241 /* If the line contains an entry of the form `/lenIV <num>' then set the global
00242    lenIV to <num>.  This indicates the number of random bytes at the beginning
00243    of each charstring. */
00244 
00245 static void set_lenIV(void){
00246   char *p = strstr(load_line, "/lenIV ");
00247   if (p && isdigit(p[7])) {
00248     lenIV = atoi(p + 7);
00249   }
00250 }
00251 
00252 static void output_token(char *token){
00253 #if 0
00254   if(in_Subroutines)return;
00255   if (strcmp(token, "\n") == 0) {
00256     fprintf(debug, "\n");
00257     start = 1;
00258   } else {
00259     fprintf(debug, "%s%s", start ? "\t" : " ", token);
00260     start = 0;
00261   }
00262 #endif
00263 }
00264 
00265 static short add_build_command(int b, int com){ /* com = 1 for command */
00266   int i,j;
00267   two_integers *ip;
00268   if(in_Subroutines){
00269     if((i=i_Subroutine) < 0 || i >= n_Subroutines)return MEMFAIL;
00270     if(C_Subs[i].p == NULL){
00271       if((ip = (two_integers *)X__Malloc((C_Subs[i].n+1)*
00272                sizeof(two_integers))) == NULL)
00273         return MEMFAIL;
00274     }
00275     else{
00276       if((ip = (two_integers *)X__Realloc(C_Subs[i].p,(C_Subs[i].n+1)*
00277                sizeof(two_integers))) == NULL)
00278         return MEMFAIL;
00279     }
00280     j=C_Subs[i].n;
00281     ip[j].i=(short)b; ip[j].com=(short)com;
00282     C_Subs[i].n++;
00283     C_Subs[i].p=ip;
00284   }
00285   else{
00286     if(Cprogram.p == NULL){
00287       if((ip = (two_integers *)X__Malloc((Cprogram.n+1)*
00288                sizeof(two_integers))) == NULL)
00289         return MEMFAIL;
00290     }
00291     else{
00292       if((ip = (two_integers *)X__Realloc(Cprogram.p,(Cprogram.n+1)*
00293                sizeof(two_integers))) == NULL)
00294         return MEMFAIL;
00295     }
00296     j=Cprogram.n;
00297     ip[j].i=(short)b; ip[j].com=(short)com;
00298     Cprogram.n++;
00299     Cprogram.p=ip;
00300   }
00301   return OK;
00302 }
00303 
00304 /* Subroutine to decrypt and ASCII-ify tokens in charstring data.  First, the
00305    length (in bytes) of the charstring is determined from load_line[].  Then the
00306    charstring decryption machinery is fired up, skipping the first lenIV bytes.
00307    Finally, the decrypted tokens are expanded into human-readable form. */
00308 
00309 static short do_charstring(void){
00310   int l = strlen(load_line);
00311   char *p = load_line + l - 1;
00312   int cs_len;
00313   int i;
00314   int b, val;
00315   char buf[20];
00316   while (p >= load_line && *p != ' ' && *p != '\t') --p;
00317   cs_len = atoi(p);
00318   /* skip this character if it is not the one we want */
00319   /* or is not in the charstring or subroutine */
00320   /* this hopefully fixes a problem wit COO font which has 2 sets of
00321      subroutines - it does it by only trying to find the character
00322      once in_charstrings is TRUE */
00323   if((in_charstring && strcmp(this_character,character_name) != 0) ||
00324      (!in_charstring && !in_Subroutines)){
00325     while (cs_len > 0) { --cs_len; b = cgetc(); }
00326     return 0;
00327   }
00328   *p = '\0';
00329   chs_cr = 4330;
00330   for (i = 0; i < lenIV; i++, cs_len--) (void) cgetc();
00331   while (cs_len > 0) {
00332     --cs_len;
00333     b = cgetc();
00334     if (b >= 32) {
00335       if (b >= 32 && b <= 246) {
00336         val = b - 139;
00337       } else if (b >= 247 && b <= 250) {
00338         --cs_len;
00339         val = (b - 247)*256 + 108 + cgetc();
00340       } else if (b >= 251 && b <= 254) {
00341         --cs_len;
00342         val = -(b - 251)*256 - 108 - cgetc();
00343       } else if (b == 255) {
00344         cs_len -= 4;
00345         val =  (cgetc() & 0xff) << 24;
00346         val |= (cgetc() & 0xff) << 16;
00347         val |= (cgetc() & 0xff) <<  8;
00348         val |= (cgetc() & 0xff) <<  0;
00349         /* in case an int is larger than four bytes---sign extend */
00350         if (sizeof(int) > 4 && val & (1U << 31))
00351           for (i = 4; i < sizeof(int); i++)
00352           val |= 0xff << (i * 8);
00353       }
00354       if(add_build_command(val,0) != OK)return MEMFAIL;
00355       sprintf(buf, "%d", val); output_token(buf);
00356     }
00357     else {
00358       if(add_build_command(b,1) != OK)return MEMFAIL;
00359       switch (b) {
00360         case 1: output_token("hstem"); break;
00361         case 3: output_token("vstem"); break;
00362         case 4: output_token("vmoveto"); break;
00363         case 5: output_token("rlineto"); break;
00364         case 6: output_token("hlineto"); break;
00365         case 7: output_token("vlineto"); break;
00366         case 8: output_token("rrcurveto"); break;
00367         case 9: output_token("closepath"); break;
00368         case 10: output_token("callsubr"); break;
00369         case 11: output_token("return"); break;
00370         case 13: output_token("hsbw"); break;
00371         case 14: output_token("endchar"); break;
00372         case 21: output_token("rmoveto"); break;
00373         case 22: output_token("hmoveto"); break;
00374         case 30: output_token("vhcurveto"); break;
00375         case 31: output_token("hvcurveto"); break;
00376         case 12:
00377           --cs_len;
00378           b = cgetc();
00379           if(add_build_command(b,1) != OK)return MEMFAIL;
00380           switch (b) {
00381             case 0: output_token("dotsection"); break;
00382             case 1: output_token("vstem3"); break;
00383             case 2: output_token("hstem3"); break;
00384             case 6: output_token("seac"); break;
00385             case 7: output_token("sbw"); break;
00386             case 12: output_token("div"); break;
00387             case 16: output_token("callothersubr"); break;
00388             case 17: output_token("pop"); break;
00389             case 33: output_token("setcurrentpoint"); break;
00390             default:
00391               sprintf(buf, "UNKNOWN_12_%d", b);
00392               output_token(buf);
00393               break;
00394           }
00395           break;
00396         default:
00397           sprintf(buf, "UNKNOWN_%d", b);
00398           output_token(buf);
00399           break;
00400       }
00401       output_token("\n");
00402     }
00403   }
00404   if(!in_Subroutines){  /* ready to process the character now */
00405     return 1;
00406   }
00407   return 0;
00408 }
00409 
00410 static int get_Subroutines(void){
00411   char *p,temp_line[LINESIZE];
00412   strcpy(temp_line,load_line);
00413   if((p=strstr(temp_line,"/Subrs")) != NULL){
00414     p=strtok(p,"\n\t ");
00415     p=strtok(NULL,"\n\t ");
00416     return atoi(p);
00417   }
00418   return 0;
00419 }
00420 
00421 static int get_subroutine_number(void){
00422   char *p,temp_line[LINESIZE];
00423   strcpy(temp_line,load_line);
00424   if((p=strstr(temp_line,"dup")) != NULL){
00425     p=strtok(p,"\n\t ");
00426     p=strtok(NULL,"\n\t ");
00427     return atoi(p);
00428   }
00429   return -1;
00430 }
00431 
00432 static int get_character_name(void){ /* and posibly encoding number */
00433   char *p1,*p2,*p3,*pend;
00434   p2=character_name;
00435   if((p1=strstr(load_line,"/")) != NULL){
00436     pend=(load_line+strlen(load_line));
00437     p3=p1; while(*p1 != ' ' && *p1 != '\t' && p1 < pend)*p2++ = *p1++;
00438     *p2 = 0;
00439     if(p3 == load_line)return -1;
00440     p3--;
00441     while (p3 != load_line && (*p3 == ' ' || *p3 == '\t')) --p3;
00442     if(p3 == load_line)return -1;
00443     while (p3 != load_line && *p3 != ' ' && *p3 != '\t') --p3;
00444     return atoi(p3);
00445   }
00446   *p2=0;
00447   return -1;
00448 }
00449 
00450 static short decode_build_type1(int tc, char *PSfile){
00451   char encoding_file[255];
00452   short ic,character_found;
00453   int wc,i;
00454   FILE *ef;
00455   sprintf(encoding_file,"%smodeler.atm",szRoot);
00456 //  MessageBox(hwndParent,encoding_file,"ATM",MB_OK);
00457   if((ef=fopen(encoding_file,"rb")) == NULL)return FAIL;
00458   fseek(ef,tc*64,SEEK_SET);
00459   if(fread(this_character,1,64,ef) != 64){
00460     fclose(ef); return FAIL;
00461   }
00462   fclose(ef);
00463   if((ifp = fopen(PSfile,"rb")) == NULL)return FAIL;
00464   p_key = 0; first_byte = 1; is_pfa = 0; is_pfb = 0;  pfb_remaining = 0;
00465   reported = 0; in_eexec = 0; start = 1; start_charstring = 0; lenIV = 4;
00466   in_EncodingArray = 0; in_Subroutines = 0;  in_charstring = 0; PS_fail=0;
00467   StandardEncoding=0;
00468   /* main loop---normally done when reach `mark currentfile closefile' on
00469      output (rest is garbage). */
00470   for (;;) {
00471     egetline();
00472     if (load_line[0] == '\0') break;
00473     set_lenIV();
00474     if(!in_eexec){
00475       if      (!in_EncodingArray && strstr(load_line,"/Encoding"))
00476         in_EncodingArray=1;
00477       else if ( in_EncodingArray){
00478         if(strstr(load_line,"readonly def"))in_EncodingArray=0;
00479         else{
00480           wc=get_character_name();
00481           if(wc == tc){
00482             strcpy(this_character,character_name);
00483             character_found=1;
00484           }
00485         }
00486       }
00487     }
00488     else {
00489       if(!in_charstring){
00490         if(strstr(load_line,"/CharStrings")){
00491           in_charstring=1; in_Subroutines=0; /* in_Su.. needed to get first */
00492           if( ! character_found){            /* in some fonts               */
00493             StandardEncoding=1;
00494           }
00495         }
00496       }
00497       if(n_Subroutines == 0 && ! in_Subroutines){
00498         n_Subroutines=get_Subroutines();
00499         if(n_Subroutines > 0){
00500           in_Subroutines=1;
00501           if((C_Subs=(character_program *)X__Malloc((long)n_Subroutines *
00502              (long)sizeof(character_program))) == NULL)return MEMFAIL;
00503           for(i=0;i<n_Subroutines;i++){C_Subs[i].n=0; C_Subs[i].p=NULL;}
00504         }
00505       }
00506       else if(in_Subroutines &&
00507         (strstr(load_line," ND") || strstr(load_line,"|-")))
00508         in_Subroutines=0;
00509 
00510     }
00511     if (start_charstring){
00512       if(!in_Subroutines){
00513         (void)get_character_name();
00514       }
00515       else{
00516         i_Subroutine=get_subroutine_number();
00517       }
00518       ic=do_charstring();
00519       if(ic == 1)break; /* found the character break out */
00520       else if(ic == MEMFAIL){ /* out of memory some where */
00521         fclose(ifp);
00522         return MEMFAIL;
00523       }
00524     }
00525     if (strcmp(load_line, "mark currentfile closefile\n") == 0){
00526       MessageBox(NULL,"No character in font","ATM",MB_OK);
00527       break;
00528     }
00529   }
00530   fclose(ifp);
00531   return OK;
00532 }
00533 

Generated on Sun Apr 27 14:20:10 2014 for OpenFX by  doxygen 1.5.6