home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / utilities / utilsm / mkdrawf / Source / c / decdrawf next >
Encoding:
Text File  |  1995-04-30  |  16.6 KB  |  538 lines

  1. /* Decode a drawfile into a format mkdrawf (new version) will understand */
  2.  
  3. /* System dependencies:
  4.  *  - I think it assumes 32 bits, LSB first.
  5.  *  - the "lowfile" routines used are RISC OS specific; but you could
  6.  *    substitute |open()| etc on Unix boxes.
  7.  */
  8.  
  9. /* #define ONLINE_MEDIA for a few trivial changes:
  10.  *  - include bbox for text item
  11.  *  - nothing more, so far
  12.  */
  13.  
  14. #define VERSION_STRING "2.35 (30/4/1995)"
  15.  
  16. #include <ctype.h>
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "lowfile.h"
  22.  
  23. int short_errors=0;
  24. char *file_name=0;
  25. int file_handle=0;
  26. int file_size=0;
  27. int *space=0;
  28. int depth=0;
  29. int return_code=0;
  30. char *prog_name="decdrawf";
  31. FILE *sprite_file=0;
  32. char *sprite_file_name=0;
  33. int n_sprites=0;
  34. int n_sprites_space=0;    /* number of sprites space in table */
  35. typedef struct {
  36.   int name[3];    /* 12 bytes, zero-padded, case insignificant */
  37.   int *pos;    /* pointer to place in drawfile */
  38. } sprite_rec;
  39. /* We just have an array, and search sequentially, rather than having
  40.  * a hash table, because (1) it's easier, (2) we generally expect fairly
  41.  * few sprites, and (3) it's more easily extensible.
  42.  */
  43. sprite_rec *sprites;
  44. /* JPEGs are almost always big. We write each to a separate file.
  45.  */
  46. char *jpeg_prefix=0;
  47. int jpeg_next=1;
  48. char *jpeg_name=0;
  49.  
  50. void err_head(int *a, char *type) {
  51.   if (short_errors) {
  52.     if (a) fprintf(stderr,"At offset %X: %s: ",(a-space)<<2,type);
  53.     else fprintf(stderr,"%s: ",type);
  54.   } else {
  55.     if (a)
  56.       fprintf(stderr,"! %s from %s...\nAt or near offset %X in `%s':\n",
  57.               type, prog_name, (a-space)<<2, file_name);
  58.     else
  59.        fprintf(stderr,"! %s from %s...\nIn `%s':\n",
  60.               type, prog_name, file_name);
  61.   }
  62. }
  63.  
  64. void warn(int *a, char *s, ...) {
  65.   va_list ap;
  66.   va_start(ap,s);
  67.   err_head(a,"Warning");
  68.   vfprintf(stderr,s,ap);
  69.   va_end(ap);
  70.   fprintf(stderr,".\n");
  71.   if (return_code<4) return_code=4;
  72. }
  73.  
  74. void error(int *a, char *s, ...) {
  75.   va_list ap;
  76.   va_start(ap,s);
  77.   err_head(a,"Error");
  78.   vfprintf(stderr,s,ap);
  79.   va_end(ap);
  80.   fprintf(stderr,".\n");
  81.   exit(8);
  82. }
  83.  
  84. void *xmalloc(unsigned int n, char *s) {
  85.   void *p=malloc(n);
  86.   if (p) return p;
  87.   error(0,"Out of space, trying to allocate %d bytes for %s",n,s);
  88.   /* this doesn't happen: */
  89.   return 0;
  90. }
  91.  
  92. void *xrealloc(void *p,unsigned n,char *s) {
  93.   void *q=realloc(p,n);
  94.   if (q) return q;
  95.   error(0,"Out of space, trying to reallocate space for %s to %d bytes",
  96.         s,n);
  97.   /* this doesn't happen: */
  98.   return 0;
  99. }
  100.  
  101. void print_coord(int *a) {
  102.   printf("%lg %lg",a[0]/640.,a[1]/640.);
  103. }
  104.  
  105. void print_line(char *s, ...) {
  106.   va_list ap;
  107.   va_start(ap,s);
  108.   printf("%*s",depth*2,"");
  109.   vprintf(s,ap);
  110.   printf("\n");
  111.   va_end(ap);
  112. }
  113.  
  114. void indent(void) {
  115.   printf("%*s",depth*2,"");
  116. }
  117.  
  118. char *int2col(int *a, unsigned int c) {
  119.   static char cc[]="r000g000b000";
  120.   if (c==0xFFFFFFFF) return "Transparent";
  121.   if (c&255) warn(a,"Dodgy RGB colour %08X",c);
  122.   sprintf(cc,"r%dg%db%d",(c>>8)&255,(c>>16)&255,(c>>24)&255);
  123.   return cc;
  124. }
  125.  
  126. void print_string(char *s) {
  127.   char c;
  128.   putchar('"');
  129.   while (c=*s++) {
  130.     if (c=='\\' || c=='"') putchar('\\');
  131.     putchar(c);
  132.   }
  133.   putchar('"');
  134. }
  135.  
  136. /* Return zero for *failure*.
  137.  */
  138. int open_sprite_file(int *s) {
  139.   n_sprites_space=16;
  140.   sprites=(sprite_rec*)xmalloc(n_sprites*sizeof(sprite_rec),"sprites");
  141.   sprite_file=fopen(sprite_file_name,"w+b");
  142.   if (!sprite_file) {
  143.     warn(s,"Couldn't open sprite file `%s'",sprite_file_name);
  144.     return 0; }
  145.   fseek(sprite_file,12,SEEK_SET);
  146.   return 1;
  147. }
  148.  
  149. /* Write relevant things at start of sprite file, and set its type
  150.  * correctly.
  151.  */
  152. void close_sprite_file(void) {
  153.   long z[3];
  154.   char cl[300];
  155.   z[0]=n_sprites;
  156.   z[1]=16;
  157.   z[2]=ftell(sprite_file)+4;
  158.   fseek(sprite_file,0,SEEK_SET);
  159.   fwrite(z,12,1,sprite_file);
  160.   fclose(sprite_file);
  161.   sprintf(cl,"SetType %s Sprite",sprite_file_name);
  162.   system(cl);
  163. }
  164.  
  165. /* return non0 if sprite names equivalent:
  166.  */
  167. static int cistreq12(const int *a, const int *b) {
  168.   int i;
  169.   for (i=0;i<12;++i)
  170.     if (tolower(((char*)a)[i])!=tolower(((char*)b)[i]))
  171.       return 0;
  172.   return 1;
  173. }
  174.  
  175. /* |s| points to sprite; |sz| is size in bytes
  176.  */
  177. void write_sprite(int *s, int sz) {
  178.   if (s[0]!=sz) warn(s,"Sprite size mismatch");
  179.   if (sprite_file_name && (sprite_file || open_sprite_file(s))) {
  180.     /* check whether a sprite with this name has already been written */
  181.     int i;
  182.     for (i=0;i<n_sprites;++i)
  183.       if (cistreq12(sprites[i].name,s+1)) {
  184.         /* Same name. Same sprite? */
  185.         if (!memcmp(sprites[i].pos,s,sz)) goto prn;
  186.         warn(s,"Different sprites with identical name `%.12s'",(char*)(s+1));
  187.         goto zog; }
  188.     /* no earlier sprite had same name */
  189.     if (n_sprites<=n_sprites_space) {
  190.       /* need more space for remembering sprites */
  191.       n_sprites_space<<=1;
  192.       sprites=(sprite_rec*)
  193.               xrealloc(sprites,n_sprites_space*sizeof(sprite_rec),"sprites");
  194.     }
  195. zog:
  196.     memcpy(sprites[n_sprites].name,s+1,12);
  197.     sprites[n_sprites].pos=s;
  198.     if (!fwrite(s,sz,1,sprite_file)) error(s,"Error writing sprite file");
  199.     ++n_sprites;
  200. prn:
  201.     indent();
  202.     printf("FromFile \"%s\" \"%.12s\"\n",sprite_file_name,(char*)(s+1));
  203.   } else {
  204.     int i=0;
  205.     sz>>=2;
  206.     indent();
  207.     while (i<sz) {
  208.       printf("0x%08X",s[i++]);
  209.       if (i&3) printf(" ");
  210.       else if (i<sz) { printf("\n"); indent(); }
  211.     }
  212.     printf("\n");
  213.   }
  214. }
  215.  
  216. int do_object(int *a) {
  217.   int type; int size;
  218.   type=a[0]; size=a[1]/4;
  219.   if (type!=0) {
  220.     indent(); printf("# BoundingBox  ");
  221.     print_coord(a+2); printf("  "); print_coord(a+4); a+=6;
  222.     printf("\n");
  223.     if (type==11) print_line("# (By the way, those should all have been 0)");
  224.   }
  225.   else a+=2;
  226.   switch(type) {
  227.     case 0: /* font table */
  228.       print_line("FontTable {"); ++depth;
  229.       { char *cp=(char *)a; int i=0,l=(size-2)*4;
  230.         while (i+3<l) {
  231.           indent(); printf("%d ",cp[i++]);
  232.           print_string(cp+i); printf("\n");
  233.           i+=strlen(cp+i)+1;
  234.           /* i=(i+3)&~3; */
  235.         }
  236.       }
  237.       --depth; print_line("}");
  238.       break;
  239.     case 1: /* text */
  240.       print_line("Text {"); ++depth;
  241. #ifdef ONLINE_MEDIA
  242.       indent(); printf("BoundingBox  ");
  243.       print_coord(a-4); printf("  ");
  244.       print_coord(a-2); printf("\n");
  245. #endif
  246. do_text:
  247.       print_line("Colour %s",int2col(a,a[0]));
  248.       print_line("Background %s",int2col(a+1,a[1]));
  249.       print_line("Style %d",a[2]);
  250.       indent(); printf("Size "); print_coord(a+3); printf("\n");
  251.       indent(); printf("StartAt "); print_coord(a+5); printf("\n");
  252.       indent(); printf("Text "); print_string((char *)(a+7));
  253.       printf("\n");
  254.       --depth; print_line("}");
  255.       break;
  256.     case 2: /* path */
  257.       print_line("Path {"); ++depth;
  258.       print_line("FillColour %s",int2col(a,a[0]));
  259.       print_line("OutlineColour %s",int2col(a+1,a[1]));
  260.       print_line("Width %lg",((unsigned int)a[2])/640.);
  261.       { unsigned int st=(unsigned int)a[3];
  262.         if (((st&0xFFFF)!=66) ||
  263.             ((((st&12)==12)||((st&48)==48)) && (st>>16!=0x201))) {
  264.           print_line("Style {"); ++depth;
  265.           print_line("# 0x%.08X",st);
  266.           if (st&3) switch(st&3) {
  267.             case 0: print_line("Mitred"); break;
  268.             case 1: print_line("Round"); break;
  269.             case 2: /* print_line("Bevelled"); */ break;
  270.             default: warn(a+3,"Dodgy join type");
  271.           }
  272.           if ((st>>2)&3) switch((st>>2)&3) {
  273.             case 1: print_line("EndCap Round"); break;
  274.             case 2: print_line("EndCap Square"); break;
  275.             case 3: print_line("EndCap Triangular"); break;
  276.           }
  277.           if ((st>>4)&3) switch((st>>4)&3) {
  278.             case 1: print_line("StartCap Round"); break;
  279.             case 2: print_line("StartCap Square"); break;
  280.             case 3: print_line("StartCap Triangular"); break;
  281.           }
  282.           if (!(st&64)) print_line("WindingRule NonZero");
  283.           if (st&128) {
  284.             int i;
  285.             print_line("Dash {"); ++depth;
  286.             print_line("Offset %lg",a[4]/640.);
  287.             indent();
  288.             for (i=0;i<a[5];++i) printf("%lg ",a[6+i]/640.);
  289.             printf("\n");
  290.             --depth; print_line("}");
  291.           }
  292.           if (st&0xFF00) {
  293.             warn(a+3,"Dodgy path style word");
  294.             print_line("# Something I don't understand");
  295.           }
  296.           if (((st&12)==12)||((st&48)==48)) {
  297.             print_line("CapWidth %d",(st>>16)&255);
  298.             print_line("CapLength %d",(st>>24)&255);
  299.             print_line("# Cap dimensions are in 1/16 of line width");
  300.           }
  301.           --depth; print_line("}");
  302.         }
  303.         else print_line("# Default style");
  304.       }
  305.       { int *b=a+4; int n=0;
  306.         if (a[3]&128) { b+=2+a[5]; }
  307.         while (1) {
  308.           switch(b[n++]) {
  309.             case 0: goto path_done;
  310.             case 2: indent(); printf("Move "); print_coord(b+n); n+=2;
  311.                     printf("\n"); break;
  312.             case 5: print_line("Close"); break;
  313.             case 6: indent(); printf("Curve ");
  314.                     print_coord(b+n); n+=2; printf("  ");
  315.                     print_coord(b+n); n+=2; printf("  ");
  316.                     print_coord(b+n); n+=2;
  317.                     printf("\n"); break;
  318.             case 8: indent(); printf("Line "); print_coord(b+n); n+=2;
  319.                     printf("\n"); break;
  320.             default: warn(b+n-1,"Unknown path item %d",b[n-1]);
  321.           }
  322.         }
  323. path_done: ;
  324.       }
  325.       --depth; print_line("}");
  326.       break;
  327.     case 5: /* sprite */
  328.       print_line("Sprite {"); ++depth;
  329.       indent(); printf("BoundingBox  ");
  330.       print_coord(a-4); printf("  ");
  331.       print_coord(a-2); printf("\n");
  332.       write_sprite(a,(size-6)<<2);
  333.       --depth; print_line("}");
  334.       break;
  335.     case 6: /* group */
  336.       print_line("Group {"); ++depth;
  337.       { char q[13]; int *qq=(int*)q; int n=3; q[12]=0;
  338.         qq[0]=a[0]; qq[1]=a[1]; qq[2]=a[2];
  339.         indent(); printf("Name "); print_string(q); printf("\n");
  340.         while (n<size-6) {
  341.           print_line("# offset-in-group is 0x%X",(n+6)*4);
  342.           n+=do_object(a+n);
  343.         }
  344.       }
  345.       --depth; print_line("}");
  346.       break;
  347.     case 7: /* tagged */
  348.       print_line("Tagged {"); ++depth;
  349.       print_line("Identifier 0x%X",a[0]);
  350.       { int n=1+do_object(a+1);
  351.         a+=n;
  352.         while (n<size-6) { print_line("OtherData 0x%X",*a++); ++n;}
  353.       }
  354.       --depth; print_line("}");
  355.       break;
  356.     case 9: /* text area */
  357.       print_line("TextArea {"); ++depth;
  358.       while (*a) {
  359.         if(a[0]!=10||a[1]!=24) {
  360.           warn(a,"Dodgy non-column in text area");
  361.           print_line("# There should be a column here, but there isn't");
  362.           break;
  363.         }
  364.         indent(); printf("Column ");
  365.         print_coord(a+2); printf("  "); print_coord(a+4); printf("\n");
  366.         a+=6;
  367.       }
  368.       print_line("# Reserved (should be 0): %d %d",a[1],a[2]);
  369.       print_line("Colour %s",int2col(a+3,a[3]));
  370.       print_line("Background %s",int2col(a+4,a[4]));
  371.       print_line("Text {"); ++depth; indent();
  372.       { char *cp=(char*)(a+5); char c;
  373.         while (c=*cp++) {
  374.           putchar(c);
  375.           if (c=='\n'&&*cp) indent();
  376.         }
  377.       }
  378.       --depth; print_line("}");
  379.       --depth; print_line("}");
  380.       break;
  381.     case 10: /* text column */
  382.       print_line("# A text column appears here. It shouldn't.");
  383.       warn(a-6,"Misplaced text column");
  384.       break;
  385.     case 11: /* options */
  386.       print_line("Options {"); ++depth;
  387.       indent(); printf("PaperSize %d     # A%d\n",(a[0]>>8)-1,(a[0]>>8)-1);
  388.       print_line("Limits {"); ++depth;
  389.       print_line((a[1]&1)?"Shown":"# not Shown");
  390.       print_line((a[1]&16)?"Landscape":"# Portrait");
  391.       print_line((a[1]&256)?"# Default":"NonDefault");
  392.       --depth; print_line("}");
  393.       print_line("Grid {"); ++depth;
  394.       print_line("Spacing %lg",*((double*)(a+2)));
  395.       print_line("Divisions %d",a[4]);
  396.       print_line(a[5]?"Isometric":"# Rectangular");
  397.       print_line(a[6]?"AutoAdjust":"# no AutoAdjust");
  398.       print_line(a[7]?"Shown":"# not Shown");
  399.       print_line(a[8]?"Lock":"# no Lock");
  400.       print_line(a[9]?"# centimetres":"Inches");
  401.       --depth; print_line("}");
  402.       print_line("Zoom {"); ++depth;
  403.       print_line("Ratio %d %d",a[10],a[11]);
  404.       print_line(a[12]?"Lock":"# no Lock");
  405.       --depth; print_line("}");
  406.       print_line(a[13]?"# toolbox present":"NoToolbox");
  407.       switch(a[14]) {
  408.         case 1: print_line("Mode Line"); break;
  409.         case 2: print_line("Mode ClosedLine"); break;
  410.         case 4: print_line("Mode Curve"); break;
  411.         case 8: print_line("Mode ClosedCurve"); break;
  412.         case 16: print_line("Mode Rectangle"); break;
  413.         case 32: print_line("Mode Ellipse"); break;
  414.         case 64: print_line("Mode Text"); break;
  415.         case 128: print_line("Mode Select"); break;
  416.         default: print_line("# Unknown mode %d",a[14]); break;
  417.       }
  418.       print_line("UndoSize %d",a[15]);
  419.       --depth; print_line("}");
  420.       break;
  421.     case 12: /* xftext */
  422.       print_line("XfText {"); ++depth;
  423.       print_line("Matrix  %lg %lg %lg %lg  %lg %lg",
  424.                  a[0]/65536.,a[1]/65536.,a[2]/65536.,a[3]/65536.,
  425.                  a[4]/1000.,a[5]/1000.);
  426.       indent();
  427.       if (a[6]&1) printf("Kerned ");
  428.       if (a[6]&2) printf("RightToLeft ");
  429.       if ((a[6]&3)!=3) {
  430.         printf("# ");
  431.         if (!(a[6]&1)) printf("not-kerned ");
  432.         if (!(a[6]&2)) printf("left-to-right");
  433.       }
  434.       printf("\n");
  435.       a+=7; goto do_text;
  436.     case 13: /* xfsprite */
  437.       print_line("XfSprite {"); ++depth;
  438.       indent(); printf("BoundingBox  ");
  439.       print_coord(a-4); printf("  ");
  440.       print_coord(a-2); printf("\n");
  441.       print_line("Matrix  %lg %lg %lg %lg  %lg %lg",
  442.                  a[0]/65536.,a[1]/65536.,a[2]/65536.,a[3]/65536.,
  443.                  a[4]/1000.,a[5]/1000.);
  444.       a+=6;
  445.       write_sprite(a,(size-12)<<2);
  446.       --depth; print_line("}");
  447.       break;
  448.     case 16: /* JPEG */
  449.       print_line("JPEG {"); ++depth;
  450.       indent(); printf("BoundingBox  ");
  451.       print_coord(a-4); printf("  ");
  452.       print_coord(a-2); printf("\n");
  453.       indent(); printf("Size "); print_coord(a); printf("\n");
  454.       print_line("DPI %d %d",a[2],a[3]);
  455.       print_line("Matrix  %lg %lg %lg %lg  %lg %lg",
  456.                  a[4]/65536.,a[5]/65536.,a[6]/65536.,a[7]/65536.,
  457.                  a[8]/1000.,a[9]/1000.);
  458.       if (jpeg_prefix) {
  459.         if (jpeg_next>100) {
  460.           warn(a,"Too many JPEGs");
  461.           goto jpeg_done; }
  462.         sprintf(jpeg_name,"%s%.2d",jpeg_prefix,jpeg_next++);
  463.         print_line("FromFile \"%s\"",jpeg_name);
  464.         if (save_file(jpeg_name,a+11,a[10],0xC85)<0)
  465.           warn(a,"Failed to save `%s'",jpeg_name);
  466.       } else {
  467.         int i=0,sz=size-11;
  468.         print_line("Length %d",a[10]); indent();
  469.         while (i<sz) {
  470.           printf("0x%08X",a[11+i++]);
  471.           if (i&3) printf(" ");
  472.           else if (i<sz) { printf("\n"); indent(); }
  473.         }
  474.         printf("\n");
  475.       }
  476. jpeg_done:
  477.       --depth; print_line("}");
  478.       break;
  479.     default:
  480.       warn(a-6,"Unknown object type %d",type);
  481.       printf("# <unknown>\n");
  482.   }
  483.   return size;
  484. }
  485. int main(int ac, char *av[]) {
  486.   int adr=0;
  487.   prog_name=av[0];
  488.   while(++av,--ac) {
  489.     if (!strcmp(*av,"-v")) {
  490.       fprintf(stderr,"This is decdrawf, version " VERSION_STRING ".\n");
  491.       return 0; }
  492.     if (!strcmp(*av,"-s")) {
  493.       if (sprite_file_name) goto usage;
  494.       if (++av,--ac) { sprite_file_name=*av; continue; }
  495.       else goto usage; }
  496.     if (!strcmp(*av,"-j")) {
  497.       if (++av,--ac) { jpeg_prefix=*av; continue; }
  498.       else goto usage; }
  499.     if (!strcmp(*av,"-e")) { short_errors=1; continue; }
  500.     if (file_name) goto usage;
  501.     else file_name=*av;
  502.   }
  503.   if (!file_name) {
  504. usage:
  505.     fprintf(stderr,"Usage: decdrawf [-s spritefile] [-j jpegpfx] drawfile\n");
  506.     return 4; }
  507.   if (jpeg_prefix)
  508.     jpeg_name=(char*)xmalloc(strlen(jpeg_prefix)+3,"buffer for JPEG filename");
  509.   file_handle=low_open(file_name,low_READ);
  510.   if (!file_handle) error(0,"Couldn't open the input file");
  511.   file_size=low_extent(file_handle);
  512.   space=(int*)xmalloc(file_size,"space for drawfile");
  513.   low_read(file_handle,space,file_size);
  514.   low_close(file_handle);
  515.   if (file_size<40) error(space,"This is not a drawfile");
  516.   printf("# Drawfile `%s'\n",file_name);
  517.   printf("# Decoded by decdrawf.\n\n");
  518.   if (space[0]!=0x77617244) error(space,"This is not a drawfile");
  519.   printf("# Header information:\n");
  520.   printf("# Format version %d.%d\n",space[1],space[2]);
  521.   { char q[13]; int *qq=(int*)q; q[12]=0;
  522.     qq[0]=space[3]; qq[1]=space[4]; qq[2]=space[5];
  523.     printf("# Creator: `%s'\n",qq);
  524.   }
  525.   printf("# Global bounding box:  ");
  526.   print_coord(space+6); printf("  "); print_coord(space+8);
  527.   printf("\n");
  528.   adr=10;
  529.   depth=0;
  530.   while (adr<file_size/4) {
  531.     printf("\n\n# At 0x%X\n",adr*4);
  532.     adr+=do_object(space+adr);
  533.   }
  534.   printf("\n# End of decoded drawfile.\n");
  535.   if (sprite_file) close_sprite_file();
  536.   return return_code;
  537. }
  538.