weber@brand.UUCP (Allan G. Weber) (12/19/85)
This is part 1 of 2 of my MacDraw to imPress program for printing MacDraw pictures on Imagen laser printers. Allan Weber USC Signal and Image Processing Institute Arpa: Weber%Brand@USC-ECL Usenet: ...sdcrdcf!oberon!brand!weber #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # Makefile # drawimp.h # macdraw.info # drawimp.c # drawimp.man # error.c # impress.c # machint.s # pxl.c # This archive created: Wed Dec 18 15:12:15 1985 export PATH; PATH=/bin:$PATH if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' README for drawimp distribution Last edit: 18-Dec-85 This is the fourth version of the MacDraw to Impress program, "drawimp". The program is used to convert a MacDraw picture to a close approximation that will print on an Imagen laser printer. The following things have not been implemented yet but hopefully will be eventually. Smoothed polygons PICT objects from MacPaint Clipping of objects that cross 8x10 inch page boundaries Rotated, centered, or flushed-right text Various notes about the program (in no particular order): 1. The file patterns.c contains the data for the 36 patterns available for filling and drawing in MacDraw. Some of the patterns that represent a 1/2 or 1/4 density grey level have been entered at the higher resolution level so the pattern will look different than that from a MacPaint image. The patterns are also slightly smaller than they should be since they have been expanded by a factor of 4 whereas the rest of the image has been expanded by about 4.17. Because of this, any image that relies on the phase of the pattern being correct at some point in the image will not come out right. 2. Impress on the 8/300 has a limit of 14 patterns that can be downloaded, not counting clear, white, and black. It is up to the user to make sure the picture does not exceed this limit. 3. The file impress.c contains functions to output the Impress command strings. So far it only contains the function needed by drawimp, others will be added when required. 4. The text output uses the fonts supplied with the Unix TeX distribution. If you don't have the TeX "am" fonts, it probably won't work. The program will look for fonts in the directory pointed to by the environment variable TEXFONTS. If TEXFONTS is not defined, it will use the default path specifed in pxl.h. 6. The routines for handling the text fonts were taken from the Imagen driver supplied with the Unix Tex distribution. These files (including one VAX machine language routine) may not be too portable to other non-VAX systems. The rest of drawimp should run on non-VAX systems with few changes. The program can be run without the text routines by defining NO_TEXT in drawimp.c and linking just drawimp.o, patterns.o, and impress.o: % cc -o drawimp -DNO_TEXT drawimp.c patterns.o impress.o -lm 7. Currently all MacDraw fonts default to the same times-roman type of TeX font. Bold and Italic are supported as are most of the special characters that can be printed with one character (no vowels with accent marks, etc.). The selection of which character to use for each MacDraw character is done in mactext.c and can be changed to suit individual tastes. 8. The TeX characters are slightly different sizes than the Mac characters so text strings will not come out the same length. Things like tables where it is necessary to line things up should be done with multiple short text strings on each line rather than one long line that uses spaces or tabs to achieve the alignment. I recommend using the New York font when putting text in the drawing since it appears to be the closest in size and will give the best approximation to the correct length of text strings. 8. IMPORTANT! Check the font filename definitions at the beginning of mactext.c to make sure the font files that will be required are on the system. The parameters in the tables can be changed to match existing font files. It's all documented in mactext.c near the tables. The way fonts are specified is a bit crude but it works. 9. The -t option is used to generate imPress files that do not have a header and is used for drawings that are to be included in a LaTex document. This allows one to print a LaTeX document on the Imagen, complete with figures, so as to avoid doing any cutting and pasting afterwards. The results generally look great and we have high hopes it. However, the process is still being fine-tuned so I haven't included any of the software for combining LaTeX and MacDraw output files. If somebody is really desperate to do this, let me know and I'll send what we have. 10. Some changes in the user interface (by popular demand) since the last version. Drawimp now accepts multiple input files and will process them one after the other to create a single output stream. The imPRESS data will have ENDPAGE commands separating the data from different files. Input from stdin is no longer supported. In normal mode, all output goes to stdout (-o option has been removed). The -d option now causes the debugging information to be written to stderr, and does not inhibit the imPRESS output from being written to stdout. If all you want is a list of objects in the file, use "drawimp -d myfile.data >/dev/null". 999. Please send any question, comments or bug reports to me at one of the addresses shown below. Note that this is a different address than where I was for the previous distributions. Allan Weber USC Signal & Image Processing Institute Powell Hall 306, MC-0272 Los Angeles, CA 90089 (213) 743-5519 Arpa: Weber%Brand@USC-ECL Usenet: ...sdcrdcf!oberon!brand!weber SHAR_EOF fi # end of overwriting check if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else cat << \SHAR_EOF > 'Makefile' drawimp: drawimp.o impress.o patterns.o mactext.o textimp.o pxl.o scaletfm.o error.o machint.o cc -o drawimp drawimp.o impress.o patterns.o mactext.o textimp.o pxl.o scaletfm.o error.o machint.o -lm drawimp.o: drawimp.c drawimp.h impress.o: impress.c patterns.o: patterns.c mactext.o: mactext.c drawimp.h textimp.o: textimp.c pxl.h types.h drawimp.h pxl.o: pxl.c pxl.h scaletfm.o: scaletfm.c pxl.h types.h error.o: error.c machint.o: machint.s SHAR_EOF fi # end of overwriting check if test -f 'drawimp.h' then echo shar: will not over-write existing file "'drawimp.h'" else cat << \SHAR_EOF > 'drawimp.h' /* This is an include file for the MacDraw file reading program. Some of the structs are not really used but are here to show the way data is stored in the file. In the structs, char = 1 byte, short = 2 bytes. Allan Weber (Weber%Brand@USC-ECL) USC Signal and Image Processing Institute Last edit: 5-Dec-85 */ #define DEF_RES 300 /* default Imagen resolution */ #define H_SHIFT 18 /* shifts to center page on paper */ #define V_SHIFT 36 #define TEXTURE_FAMILY 95 #define FONT_FAMILY_TOP (TEXTURE_FAMILY - 1) #define TEMP_PREFIX "/tmp/McDXXXXXX" #define TEX_EXT ".imp" /* file extension for LaTex files */ #define MAC_EXT ".data" /* file extension for MacDraw file */ #define MAC_H_SIZE 576 #define MAC_V_SIZE 720 #define MAC_H_PAGES 12 #define MAC_V_PAGES 5 #define HEADER_SIZE 512 #define ARROW_ANGLE 15 /* The following #define values relate to the different attributes used by MacDraw for various objects. */ /* Text style */ #define PLAIN 0 #define BOLD 1 #define ITALIC 2 #define UNDERLINE 4 #define HOLLOW 8 #define SHADOW 16 /* Font type */ #define CHICAGO 1 #define GENEVA 2 #define NEW_YORK 3 /* Font size */ #define SIZE_9 1 #define SIZE_10 2 #define SIZE_12 3 #define SIZE_14 4 #define SIZE_18 5 /* Text spacing */ #define SINGLE 1 #define THREE_HALF 2 #define DOUBLE 3 /* Text alignment */ #define LEFT 1 #define CENTER 2 #define RIGHT 3 /* Line width */ #define LINE_0 1 #define LINE_1 2 #define LINE_2 3 #define LINE_4 4 #define LINE_6 5 /* Arrow direction */ #define NO_ARROW 0 #define RIGHT_ARROW 1 #define LEFT_ARROW 2 #define BOTH_ARROW 3 /* The following structs are for various data structures used in the MacDraw data records. */ struct lcoord { /* long coordinate - radix point between halves */ unsigned short i,f; }; struct lpoint { /* long point */ struct lcoord v,h; }; struct lrect { /* long rectangle */ struct lcoord top, left, bottom, right; }; struct srect { /* short rectangle */ short top, left, bottom, right; }; struct frect { /* float rectangle */ float top, left, bottom, right; }; struct bpoint { /* incremental point */ char x,y; }; /* The following are structs for the data records. Fields with unknown purposes are named Z1, Z2, etc. */ struct MDheader { /* record header for each object */ char code; char Z1,Z2,Z3; char line; char pen; char fill; char special; }; struct MDtext { /* Text record */ short Z1,Z2; char style; char font; char size; char spacing; char alignment; char angle; short count; struct srect rect; }; struct MDvector { /* Vector record (right angle and sloped) */ struct lpoint start, stop; }; struct MDbox { /* Rectangle, Ellipse, and RoundRect record */ struct lrect rect; }; struct MDarc { /* Arc record */ struct lrect rect; unsigned short start, angle; }; struct MDgroup { /* Group identifier record */ struct lrect rect; unsigned short Z1, Z2, Z3, Z4, Z5, Z6, Z7, Z8; }; struct MDpolygon { /* Polygon record */ unsigned short Z1; unsigned short rec_size; unsigned short points; struct lrect rect; char closed; char Z2; }; struct MDcurve { /* Curve record */ unsigned short Z1; unsigned short rec_size; unsigned short points; struct lrect rect; char closed; char Z2; struct lpoint start; }; #define MAX_RECORD 40 SHAR_EOF fi # end of overwriting check if test -f 'macdraw.info' then echo shar: will not over-write existing file "'macdraw.info'" else cat << \SHAR_EOF > 'macdraw.info' MacDraw data file information Allan Weber (Weber@USC-ECLC) USC Signal and Image Processing Institute Last edit: 16-Dec-85 This file contains a description of the data records produced by "Macdraw Version 1.7 3/18/85". Some of the information in the data records has not yet been deciphered and is indicated below by question marks. Note: Many of the data structures for points and rectangles use 4-byte "fixed-point numbers" instead of the normal 2-byte integers. Fixed-point numbers are described in "Inside Macintosh", page MI-11. They are similar to integers with the addition of a 2-byte fractional part, thus yielding a number with the same range but greater precision. A MacDraw file starts with a 512 byte header. There does not appear to be any information in the header required for recreating the image on a device like a laser printer. File header (512 bytes) Offset 0..213 ? 214..229 Enclosing rectangle for entire drawing (Fixed-point) 230..511 ? After the file header is a sequence of data records, one for each object in the image. Each object data record starts with an 8-byte record header, followed in most cases by varible length object dependent data. The first byte in each of the record headers indicates the type of object. At the end of the file is a terminator (type 0) record. Record header (8 bytes) Offset 0 code 0 = terminator 1 = text 2 = right angle vector 3 = sloped vector 4 = rectangle 5 = round rectangle 6 = ellipse 7 = arc 8 = curve 9 = polygon 10= group 11 = PICT data (from MacPaint) 1 lock 0 = unlocked, 1 = locked 2 ? 3 ? 4 line width code: 1 = 0 pixels, 2 = 1 pixel, 3 = 2 pixels, 4 = 4 pixels, 5 = 6 pixels 5 pen pattern number: 1..36 6 fill pattern number: 1..36 7 special for vectors, the arrow type 0 = ------, 1 = ----->, 2 = <-----, 3 = <-----> for round rectangles, the corner radius: 1 = 0", 2 = 1/8, 3 = 3/16, 4 = 1/4, 5 = 5/16, 6 = 3/8 8.. An object-specific record (if any) follows after the header Object Specific Data (follows record header) 0: Terminator record (0 bytes) A terminator record is used to mark the end of the list of objects or the end of a set of objects that have been grouped together. 1: Text record (20 bytes + length of string) 0..3 ? 4 style 0 = plain, 1 = bold, 2 = italic, 4 = underline, 8 = hollow, 16 = shadow 5 font 1 = Chicago, 2 = Geneva, 3 = New York, 4 = Monaco, 5 = Venice, 6 = London, 7 = Athens 6 size 1 = 9 pt, 2 = 10 pt, 3 = 12 pt, 4 = 14 pt, 5 = 18 pt, etc. 7 spacing 1 = single, 2 = three halves, 3 = double 8 align 1 = left, 2 = center, 3 = right 9 angle 0 = normal 4 = flip horizontal 1 = rotate right 5 = flip vertical 2 = upsidedown 6 = rotate right and flip horizontal 3 = rotate left 7 = rotate left and flip horizontal 10:11 Number of characters in text string 12:19 Rectangle enclosing text (Integer) (Note: the rectangle gives the location of the text BEFORE doing any rotating and/or flipping according to byte 9.) 20 Start of text string (not terminated with null) 2,3: Vector record (16 bytes) 0:7 Start point (Fixed-point) 8:15 End point (Fixed-point) 4,5,6: Rectangles and Ellipse record (16 bytes) 0:15 Rectangle enclosing object (Fixed-point) 7: Arc record (20 bytes) 0:15 Rectangle enclosing ellipse used to generate arc (Fixed-point) 16:17 Start angle (degrees) 18:19 Extent of arc (degrees) 8: Curve record (32 bytes + 2 bytes/point) 0..1 ? 2:3 Number of bytes in rest of record 4:5 Number of points in curve including start point and ending null point 6:21 Rectangle enclosing curve (Fixed-point) 22 1 = make closed (add final point same as first point) 23 ? 24:31 Start point (Fixed-point) 32 Start of X,Y increment pairs (2 bytes/pair), 2's complement, terminated by a pair of zero bytes. 9: Polygon record (24 bytes + 8 bytes/point) 0..1 ? 2:3 Number of bytes in rest of record 4:5 Number of points in polygon 6:21 Rectangle enclosing curve (Fixed-point) 22 1 = make closed (add final point same as first point) 2 = smoothed polygon 23 ? 24 Start of list of points in the polygon (Fixed-point), 8 bytes/pnt 10: Group record (32 bytes) A group record is used to indicate the beginning of a collection of objects that have been grouped together using the Group command under the Arrange menu. The group contains all the following objects until a terminator record is encountered. 0:15 Rectangle enclosing all members in the group (Fixed-point) 16..31 ? 11: PICT record (42+) 0..3 ? 4:11 ? Rectangle (Integer) 12:27 Rectangle enclosing picture (Fixed-point) 28..31 ? 32:33 Width of picture in bytes 34:41 ? Rectangle (Integer) 42.. Bitmap SHAR_EOF fi # end of overwriting check if test -f 'drawimp.c' then echo shar: will not over-write existing file "'drawimp.c'" else cat << \SHAR_EOF > 'drawimp.c' /* drawimp - MacDraw to Impress translator This program will read a MacDraw file and output a sequence of Impress commands to draw the picture on an Imagen laser printer. Program is compatible with MacDraw files created by "MacDraw Version 1.7 3/18/85". Drawimp has two processing modes. The normal mode causes the MacDraw files listed on the command line to be processed in order listed with the Impress data written to stdout with ENDPAGE commands between data from each file. This will put each file on separate pages. In TeX mode (with -t switch) each input file, is processed and the results are written to a separate output file with the extension (if any) changed to .imp. The output files have no header or trailing ENDPAGE or EOF commands. The -d switch causes debugging information to be written to stderr. This consists of a list of objects and some info about them. The -p switch is used to select which pages of the MacDraw file to output. Syntax is: -pr1-r2:c1-c2[,r1-r2:c1-c2] The -R switch is used to specify the Image resolution in dots per inch. The default is set in drawimp.h A few examples: drawimp Picture.data >Picture.imp drawimp -p1:2 Picture.data >Picture.imp drawimp -d Picture.data >/dev/null drawimp -d Picture.data >Picture.imp drawimp -t Picture1.data Picture2.data drawimp -R240 Picture1.data | ipr Not (yet) implemented: Smoothed polygons PICT objects from MacPaint Clipping of objects that cross 8x10 inch page boundaries Please send any bug reports to Weber%Brand@USC-ECL.ARPA. Allan Weber (Weber%Brand@USC-ECL) USC Signal and Image Processing Institute History: 16-Apr-85 Version 1 23-Apr-85 Version 2 - Fixed bug in arcs, added arrows, added rest of patterns, changed cvtpnt to use 32-bit coordinates, added -p switch for page select 28-Aug-85 Version 3 - Added text using TeX fonts and routines from the Unix TeX distribution. Added fix to arc routine from Richard Roy (dick@su-dit). 16-Dec-85 Version 4 Added -t switch to produce impress file without header, endpage, or eof bytes for including output file in TeX documents going to Imagen. Also moves whatever is on page to upper left corner. More fixes to arcs to handle filled arcs and arcs of other than 90 degrees. Implemented different radius corners for the rounded rectangles. */ #include <stdio.h> #include <ctype.h> #include <math.h> #include "drawimp.h" /* #define NO_TEXT */ /* define NO_TEXT to build without text capability */ FILE *infp, *outfp, *fontfp; int gdepth, done; int debug = 0; int tex_output = 0; int draw_top, draw_left; int line_table[] = { 0, 0, 1, 8, 16, 20 }; /* line width table */ int ar_size[] = { 0, 0, 10, 15, 20, 25}; /* arrowhead size table */ int corner_rad[] = { 0, 0, 9, 14, 18, 23, 27 }; /* corner radius table */ int texture_table[37]; char *ProgName; char fheader[HEADER_SIZE]; char tmp[MAX_RECORD]; char filename[80]; struct MDheader rheader; struct srect cur_page; double ar_angle, ar_size2[6], ar_radius[6]; extern char pattern[37][128]; /* This array contains info about each page of the file begin drawn. The objects in the MacDraw file can occur in any order and we have to sort them out into separate page for output. The .flag indicates whether this page is to be output or not (from -p option). The .font field is used to store the ImFamily value from the textimp.c file that was in use the last time we were doing that page. By remembering which font was in use on a page, we don't have to send the imPress SetFamily commands each time we go back to put more stuff on that page if the font hasn't changed. The .name field holds the name of the temporary file so we can delete it later. The file pointer is in .fp and is 0 if no file open for that page yet. The page_ptr variable points to the entry for the page currently being worked on. */ struct page { /* table of drawing pages */ int flag; /* flag for page in use */ int font; /* font in use on this page */ char name[20]; /* file name of where the data went */ FILE *fp; /* file pointer */ } pagetbl[MAC_V_PAGES][MAC_H_PAGES], *page_ptr; /* This table contains the values used to convert from MacDraw units (1/72 inch) to the resolution of the Imagen. The .res field is the Imagen resolution in pixels/inch. The .num and .den fields are the numerator and denoninator used to do the multiplication, as in: Imagen = MacDraw * .num / .den The scaling factor is split into separate numerator and denominator to allow conversion without overflow problems. */ struct { int res; int num,den; } restbl[] = { 240, 10, 3, 300, 25, 6, -1, 0, 0 }; int md2im_num, md2im_den; int resolution = DEF_RES; char *getpages(); int terminal(), text(), vector(), rectangle(), roundrect(); int ellipse(), arc(), curve(), polygon(), group(); int (*opfun[])() = {terminal, text, vector, vector, rectangle, roundrect, ellipse, arc, curve, polygon, group }; char *USAGE = "[-Rres] [-d] [-t] [-ppages] in_file > out_file"; extern char *malloc(); extern char *mktemp(); extern char *strcpy(); extern FILE *impout(); #ifndef NO_TEXT extern int ImFamily; /* current Imagen font number from textimp */ #endif main(argc,argv) int argc; char *argv[]; { int i; int h,h1,h2; int v,v1,v2; int gotpages = 0; char *s,c; struct lrect r; struct page *pp; ProgName = argv[0]; while(--argc > 0 && (*++argv)[0] == '-') { for (s = argv[0]+1; *s != '\0'; s++) switch(*s) { case 'd': /* debug */ debug = 1; break; case 'p': /* page select */ ++s; while (*s != '\0') { v1 = 1; v2 = 5; s = getpages(s,&v1,&v2); if (*s != ':') { fprintf(stderr, "%s: error in page list\n", ProgName); argc = -1; while (*s != '\0') s++; break; } else s++; h1 = 1; h2 = 12; s = getpages(s,&h1,&h2); if (v1 == 0) v1 = 1; if (h1 == 0) h1 = 1; for (v = v1; v <= v2; v++) for (h = h1; h <= h2; h++) pagetbl[v-1][h-1].flag=1; if (*s == ',') s++; } s--; /* back pointer up one place */ gotpages = 1; break; case 't': tex_output = 1; break; case 'R': /* Image resolution */ s++; if (sscanf(s,"%d",&resolution) != 1) { fprintf(stderr,"%s: Bad resolution - %s\n", ProgName,s); argc = -1; } while (*s != '\0') s++; s--; break; default: fprintf(stderr,"%s: illegal option - %c\n", ProgName,*s); argc = -1; break; } } if (argc <= 0) { usage(); exit(1); } if (tex_output) { if (gotpages == 0) pagetbl[0][0].flag = 1; /* only first page for tex */ else { fprintf(stderr, "Cannot use -t and -p options at same time\n"); usage(); exit(1); } } else if (gotpages == 0) { for (v = 0; v < MAC_V_PAGES; v++) /* do all */ for (h = 0; h < MAC_H_PAGES; h++) pagetbl[v][h].flag = 1; } /* figure out what resolution and conversion factors to use */ i = 0; while (restbl[i].res > 0) { if (restbl[i].res == resolution) { md2im_num = restbl[i].num; md2im_den = restbl[i].den; break; } i++; } if (md2im_num == 0) { fprintf(stderr,"%s: Unknown resolution - %d\n", ProgName,resolution); exit(1); } /* calculate some things for doing arrows */ ar_angle = ARROW_ANGLE * 2 * 3.14159 / 360; for (i = 0; i <= 5; i++) { ar_radius[i] = md2im(ar_size[i]); ar_size2[i] = pow(ar_radius[i] * cos(ar_angle), (float) 2); } /* calculate some things for doing rectangle corners */ for (i = 1; i <= 6; i++) { corner_rad[i] = md2im(corner_rad[i]); } if (tex_output == 0) { printf("@document(language impress)"); impout(stdout); imP_set_abs_h(md2im(H_SHIFT)); /* shift origin */ imP_set_abs_v(md2im(V_SHIFT)); imP_set_hv_system(3,0,0); /* set new origin */ } while (argc-- > 0) { if ((infp = fopen(*argv,"r")) == NULL) { fprintf(stderr,"%s: can't open input file %s\n", ProgName,*argv); exit(1); } if (tex_output) { makename(*argv,filename); if ((outfp = fopen(filename,"w")) == NULL) { fprintf(stderr, "%s: can't open output file %s\n", ProgName,filename); exit(1); } fontfp = outfp; /* put font info at front */ } else { outfp = stdout; fontfp = stdout; } argv++; page_ptr = NULL; fread(fheader,1,HEADER_SIZE,infp); /* read header */ if (debug) { makelrect(fheader+214,&r); fprintf(stderr, "Drawing rectangle: t=%d, l=%d, b=%d, r=%d\n", r.top.i,r.left.i,r.bottom.i,r.right.i); } draw_top = draw_left = 0; if (tex_output != 0) cvtpnt(&r.top, &r.left, &draw_top, &draw_left); /* read the MacDraw objects and process them */ done = gdepth = 0; while (fread((char *)&rheader, sizeof(struct MDheader), 1, infp) == 1) { c = rheader.code; if (c >= 0 && c <= 10) (opfun[c])(); else { fprintf(stderr,"Unrecognized type - %d\n",c); break; } if (done) break; } fclose(infp); /* now output all the collected picture data */ impout(outfp); if (tex_output) imP_set_hv_system(3,0,0); /* set new origin */ for (v = 0; v < MAC_V_PAGES; v++) for (h = 0; h < MAC_H_PAGES; h++) { pp = &pagetbl[v][h]; if (pp->fp != NULL) { fseek(pp->fp,0L,0); while ((c = getc(pp->fp)) != EOF) putc(c,outfp); fclose(pp->fp); pp->fp = NULL; unlink(pp->name); if (tex_output == 0) imP_endpage(); } } #ifndef NO_TEXT reset_text(); /* reset text for next file */ #endif if (tex_output) { #ifndef NO_TEXT reset_fonts(); /* set fonts as not downloaded yet */ #endif reset_textures(); /* same for texture glyphs */ fclose(outfp); } } /* finish the file off */ if (tex_output == 0) imP_eof(); } usage() { fprintf(stderr,"Usage: %s %s\n",ProgName, USAGE); } /*****************************************************************************/ terminal() { if (debug) fprintf(stderr, "Terminator: depth = %d\n",gdepth); if (gdepth > 0) gdepth--; else done = 1; } text() { int n, doit; int style, font, size, spacing, align, angle; int top, left, bottom, right; int v[5], h[5], tv, th; char *s, *s0; struct lrect r; fread(tmp,sizeof(struct MDtext),1,infp); style = makenum(1,tmp+4); font = makenum(1,tmp+5); size = makenum(1,tmp+6); spacing = makenum(1,tmp+7); align = makenum(1,tmp+8); angle = makenum(1,tmp+9); n = makenum(2,tmp+10); makelrect0(tmp+12,&r); doit = dopage(&r.top,&r.left) != 0; if (debug && doit) { fprintf(stderr, "Text: %d characters, rect: t=%d, l=%d, b=%d, r=%d\n", n,r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "\tstyle=%d, font=%d, size=%d, spacing=%d\n", style, font, size, spacing); fprintf(stderr, "\talign=%d, angle=%d, fill=%d\n", align, angle, rheader.fill); } if ((s = s0 = malloc(n+1)) == 0) fprintf(stderr,"Unable to malloc %d byte\n",n+1); while (n--) *s++ = getc(infp); *s = '\0'; if (debug && doit) fprintf(stderr, "\"%s\"\n",s0); if (doit) { if (rheader.fill > 1) { cvtpnt(&r.top,&r.left,&top,&left); cvtpnt(&r.bottom,&r.right,&bottom,&right); h[0] = h[3] = h[4] = left; v[0] = v[1] = v[4] = top; h[1] = h[2] = right - 1; v[3] = v[2] = bottom - 1; imP_create_path(5,h,v); imP_fill_path(use_pattern(rheader.fill)); } cvtpnt(&r.top,&r.left,&tv,&th); #ifndef NO_TEXT mactext(s0,tv,th,style,font,size,spacing,align,angle); #endif } free(s0); } vector() { struct lpoint pnt1, pnt2; int h[2], v[2], ha[3], va[3]; int pat, ar, s; double dh, dv, t; fread(tmp,sizeof(struct MDvector),1,infp); makelpoint(tmp+0,&pnt1); makelpoint(tmp+8,&pnt2); if (dopage(&pnt1.v,&pnt1.h) == 0) return; if (debug) { fprintf(stderr, "Vector: From (%dv %dh) to (%dv %dh), ", pnt1.v.i,pnt1.h.i,pnt2.v.i,pnt2.h.i); fprintf(stderr, "line=%d, pen=%d, fill=%d, arrow=%d\n", rheader.line,rheader.pen,rheader.fill,rheader.special); } if (onpage(&pnt1.v,&pnt1.h) && onpage(&pnt2.v,&pnt2.h) && rheader.line > 1) { cvtpnt(&pnt1.v,&pnt1.h,v,h); cvtpnt(&pnt2.v,&pnt2.h,v+1,h+1); if (rheader.pen > 1) pat = use_pattern(rheader.pen); if ((ar = rheader.special) > 0) { dh = h[1] - h[0]; dv = v[1] - v[0]; s = rheader.line; if (dh*dh + dv*dv > ar_size2[s]) { t = atan2(dv,dh); if (ar == 1 || ar == 3) { make_arrow(h+1,v+1,t,s,ha,va); imP_create_path(3,ha,va); imP_fill_path(pat); } if (ar == 2 || ar == 3) { t += 3.14159; make_arrow(h,v,t,s,ha,va); imP_create_path(3,ha,va); imP_fill_path(pat); } } } imP_create_path(2,h,v); imP_set_pen(use_line(rheader.line)); imP_draw_path(pat); } } rectangle() { struct lrect r; int top, left, bottom, right; int h[5], v[5]; fread(tmp,sizeof(struct MDbox),1,infp); makelrect(tmp,&r); if (dopage(&r.top,&r.left) == 0) return; if (debug) { fprintf(stderr, "Rectangle: t=%d, l=%d, b=%d, r=%d, ", r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "line=%d, pen=%d, fill=%d, corner=%d\n", rheader.line,rheader.pen,rheader.fill,rheader.special); } if (onpage(&r.top,&r.left) && onpage(&r.bottom,&r.right)) { cvtpnt(&r.top,&r.left,&top,&left); cvtpnt(&r.bottom,&r.right,&bottom,&right); h[0] = h[3] = h[4] = left; v[0] = v[1] = v[4] = top; h[1] = h[2] = right - 1; v[3] = v[2] = bottom - 1; if (h[0] >= h[1]) /* vertical line? */ imP_create_path(2,h+1,v+1); else if (v[1] >= v[2]) /* horizontal line? */ imP_create_path(2,h,v); else /* rectangle */ imP_create_path(5,h,v); if (rheader.fill > 1) imP_fill_path(use_pattern(rheader.fill)); if (rheader.line > 1) { imP_set_pen(use_line(rheader.line)); imP_draw_path(use_pattern(rheader.pen)); } } } roundrect() { struct lrect r; int top, left, bottom, right, ra, rb, rad, corner; int h[9], v[9]; fread(tmp,sizeof(struct MDbox),1,infp); makelrect(tmp,&r); if (dopage(&r.top,&r.left) == 0) return; if (debug) { fprintf(stderr, "RoundRect: t=%d, l=%d, b=%d, r=%d, ", r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "line=%d, pen=%d, fill=%d, corner=%d\n", rheader.line,rheader.pen,rheader.fill,rheader.special); } if (onpage(&r.top,&r.left) && onpage(&r.bottom,&r.right)) { cvtpnt(&r.top,&r.left,&top,&left); cvtpnt(&r.bottom,&r.right,&bottom,&right); ra = (right-1 - left) / 2; rb = (bottom-1 - top) / 2; rad = corner_rad[rheader.special]; if (ra > rad) ra = rad; if (rb > rad) rb = rad; corner = (ra != 0) || (rb != 0); h[0] = h[5] = h[8] = left + ra; h[1] = h[4] = right-1 - ra; h[2] = h[3] = right-1; h[6] = h[7] = left; v[0] = v[1] = v[8] = top; v[2] = v[7] = top + rb; v[3] = v[6] = bottom-1 - rb; v[4] = v[5] = bottom-1; if (h[0] < h[1]) imP_create_path(2,h,v); imP_set_pum(1); if (corner) { imP_set_abs_h(h[1]); imP_set_abs_v(v[2]); imP_ellipse_arc(ra,rb,0,12288,16383); } if (v[2] < v[3]) imP_create_path(2,h+2,v+2); if (corner) { imP_set_abs_h(h[4]); imP_set_abs_v(v[3]); imP_ellipse_arc(ra,rb,0,0,4096); } if (h[5] < h[4]) imP_create_path(2,h+4,v+4); if (corner) { imP_set_abs_h(h[5]); imP_set_abs_v(v[6]); imP_ellipse_arc(ra,rb,0,4096,8192); } if (v[7] < v[6]) imP_create_path(2,h+6,v+6); if (corner) { imP_set_abs_h(h[0]); imP_set_abs_v(v[7]); imP_ellipse_arc(ra,rb,0,8192,12288); } if (rheader.fill > 1) imP_fill_path(use_pattern(rheader.fill)); if (rheader.line > 1) { imP_set_pen(use_line(rheader.line)); imP_draw_path(use_pattern(rheader.pen)); } imP_set_pum(0); } } ellipse() { struct lrect r; int top, left, bottom, right, ra, rb; fread(tmp,sizeof(struct MDbox),1,infp); makelrect(tmp, &r); if (dopage(&r.top,&r.left) == 0) return; if (debug) { fprintf(stderr, "Ellipse: t=%d, l=%d, b=%d, r=%d, ", r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "line=%d, pen=%d, fill=%d\n", rheader.line,rheader.pen,rheader.fill,rheader.special); } if (onpage(&r.top,&r.left) && onpage(&r.bottom,&r.right)) { cvtpnt(&r.top,&r.left,&top,&left); cvtpnt(&r.bottom,&r.right,&bottom,&right); imP_set_abs_h((left + right-1) / 2); imP_set_abs_v((top + bottom-1) / 2); ra = (right-1 - left) / 2; rb = (bottom-1 - top) / 2; imP_ellipse_arc(ra,rb,0,0,16383); if (rheader.fill > 1) imP_fill_path(use_pattern(rheader.fill)); if (rheader.line > 1) { imP_set_pen(use_line(rheader.line)); imP_draw_path(use_pattern(rheader.pen)); } } } arc() { struct lrect r; int top, left, bottom, right, ra, rb, ch, cv; int start, extent; int alpha0, alpha1; fread(tmp,sizeof(struct MDarc),1,infp); makelrect(tmp, &r); start = makenum(2,tmp+16); extent = makenum(2,tmp+18); if (dopage(&r.top,&r.left) == 0) return; if (debug) { fprintf(stderr, "Arc: t=%d, l=%d, b=%d, r=%d, ", r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "line=%d, pen=%d, fill=%d\n", rheader.line,rheader.pen,rheader.fill); fprintf(stderr, "\tstart = %d, extent = %d\n",start,extent); } if (onpage(&r.top,&r.left) && onpage(&r.bottom,&r.right)) { cvtpnt(&r.top,&r.left,&top,&left); cvtpnt(&r.bottom,&r.right,&bottom,&right); ch = (left + right-1) / 2; cv = (top + bottom-1) / 2; imP_set_abs_h(ch); imP_set_abs_v(cv); ra = (right-1 - left) / 2; rb = (bottom-1 - top) / 2; /* changed 8/22/85 by rhr - apparently MacDraw allows arcs to be traversed * in negative direction (Imagen does not)! Debug output gave extent=65446! * which for 16 bit 2's complement would be about -90! So, this fix assumes * all arcs are 90 degrees in extent, plus or minus, and adjusts start * accordingly */ /* changed again 11/4/85 by AGW to allow arcs of other than 90 degrees */ if (extent > 32768) { /* negative direction? */ extent = 65536 - extent; start = start - extent; } if (rb > ra) /* v axis = major axis */ start = (start + 270) % 360; alpha0 = ((start - 90) * 4096) / 90; if (alpha0 < 0) alpha0 += 16384; if (extent == 360) alpha1 = alpha0 + 16383; else alpha1 = alpha0 + ((extent * 4096) / 90); if (rheader.fill > 1) { imP_create_path(1, &ch, &cv); imP_set_pum(1); imP_ellipse_arc(ra,rb,0,alpha0,alpha1); imP_fill_path(use_pattern(rheader.fill)); imP_set_pum(0); } if (rheader.line > 1) { imP_ellipse_arc(ra,rb,0,alpha0,alpha1); imP_set_pen(use_line(rheader.line)); imP_draw_path(use_pattern(rheader.pen)); } } } curve() { int n, n0, dx, dy; struct lpoint pnt; int *h, *h0, *v, *v0; int doit; struct lrect r; fread(tmp,sizeof(struct MDcurve),1,infp); n = makenum(2,tmp+4); makelrect(tmp+6, &r); doit = dopage(&r.top,&r.left) != 0; if (debug && doit) { fprintf(stderr, "Curve: n=%d, t=%d, l=%d, b=%d, r=%d, ", n,r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "line=%d, pen=%d, fill=%d\n", rheader.line,rheader.pen,rheader.fill); } makelpoint(tmp+24,&pnt); /* null point at end gets discarded which gives room in array for point to close region if needed */ h = h0 = (int *) malloc((unsigned) sizeof(int) * n); v = v0 = (int *) malloc((unsigned) sizeof(int) * n); n0 = 0; while (--n) { if (debug && doit) fprintf(stderr, "\t%d: (%dv %dh)\n", n0,pnt.v.i,pnt.h.i); cvtpnt(&pnt.v,&pnt.h,v++,h++); n0++; dx = getc(infp); dy = getc(infp); if (dx > 127) dx -= 256; if (dy > 127) dy -= 256; pnt.h.i += dx; pnt.v.i += dy; } if (debug && doit) fprintf(stderr, "\t%d: (%dv %dh)\n",n0,pnt.v.i,pnt.h.i); if (tmp[22] == 1) { /* check for closed curve */ *h = *h0; *v = *v0; n0++; } if (doit) { if (onpage(&r.top,&r.left) && onpage(&r.bottom,&r.right)) { imP_create_path(n0,h0,v0); if (rheader.fill > 1) imP_fill_path(use_pattern(rheader.fill)); if (rheader.line > 1) { imP_set_pen(use_line(rheader.line)); imP_draw_path(use_pattern(rheader.pen)); } } } free((char *) h0); free((char *) v0); } polygon() { int n, n0; struct lpoint pnt; int *h, *h0, *v, *v0; int doit; struct lrect r; fread(tmp,sizeof(struct MDpolygon),1,infp); n = makenum(2,tmp+4); makelrect(tmp+6, &r); doit = dopage(&r.top,&r.left) != 0; if (debug && doit) { fprintf(stderr, "Polygon: n=%d, t=%d, l=%d, b=%d, r=%d, ", n,r.top.i,r.left.i,r.bottom.i,r.right.i); fprintf(stderr, "line=%d, pen=%d, fill=%d\n", rheader.line,rheader.pen,rheader.fill); } h = h0 = (int *) malloc((unsigned) sizeof(int) * (n+1)); v = v0 = (int *) malloc((unsigned) sizeof(int) * (n+1)); n0 = 0; while (n--) { fread(tmp,1,8,infp); makelpoint(tmp,&pnt); if (debug && doit) fprintf(stderr, "\t%d: (%dv %dh)\n", n0,pnt.v.i,pnt.h.i); cvtpnt(&pnt.v,&pnt.h,v++,h++); n0++; } if (tmp[22] == 1) { /* check for closed polygon */ *h = *h0; *v = *v0; n0++; } if (doit) { if (onpage(&r.top,&r.left) && onpage(&r.bottom,&r.right)) { imP_create_path(n0,h0,v0); if (rheader.fill > 1) imP_fill_path(use_pattern(rheader.fill)); if (rheader.line > 1) { imP_set_pen(use_line(rheader.line)); imP_draw_path(use_pattern(rheader.pen)); } } } free((char *) h0); free((char *) v0); } group() { struct lrect r; fread(tmp,sizeof(struct MDgroup),1,infp); makelrect(tmp, &r); gdepth += 1; if (debug) { fprintf(stderr, "Group start: depth = %d, ", gdepth); fprintf(stderr, "rectangle: t=%d, l=%d, b=%d, r=%d\n", gdepth,r.top.i,r.left.i,r.bottom.i,r.right.i); } } /*****************************************************************************/ makenum(i,p) /* make a number from bytes in 68000 order */ int i; char *p; { int n = 0; while (i--) n = (n << 8) + (*p++ & 0xff); return(n); } makelpoint(cp, pp) /* swap bytes 4 times to make a lpoint struct */ char *cp; struct lpoint *pp; { swapbyte(cp, (char *)pp, 4); } makelrect(cp, rp) /* swap bytes 8 times to make a lrect struct */ char *cp; struct lrect *rp; { swapbyte(cp, (char *)rp, 8); } makelrect0(cp, rp) /* same as makelrect except fractional part = 0 */ char *cp; struct lrect *rp; { swapbyte(cp+0, (char *)&rp->top.i, 1); swapbyte(cp+2, (char *)&rp->left.i, 1); swapbyte(cp+4, (char *)&rp->bottom.i, 1); swapbyte(cp+6, (char *)&rp->right.i, 1); rp->top.f = rp->left.f = rp->bottom.f = rp->right.f = 0; } swapbyte(p1, p2, n) register char *p1, *p2; register int n; { while (n-- > 0) { *(p2+1) = *p1++; *p2 = *p1++; p2 += 2; } } cvtpnt(mv,mh,iv,ih) /* convert point from MacDraw to Imagen coord. */ struct lcoord *mv, *mh; int *iv, *ih; { int a,b; a = mv->i - cur_page.top; b = mv->f; *iv = (md2im((a << 8) + (b >> 8 & 0xff)) >> 8) - draw_top; a = mh->i - cur_page.left; b = mh->f; *ih = (md2im((a << 8) + (b >> 8 & 0xff)) >> 8) - draw_left; #ifdef DEBUG fprintf(stderr, "\tv.i=%d v.f=%d v=%d, h.i=%d h.f=%d h=%d\n", mv->i,mv->f,*iv,mh->i,mh->f,*ih); */ #endif } md2im(x) /* convert a value from MacDraw to Imagen */ int x; { return(x * md2im_num / md2im_den); } onpage(pv,ph) struct lcoord *pv, *ph; { return(pv->i >= cur_page.top && pv->i <= cur_page.bottom && ph->i >= cur_page.left && ph->i <= cur_page.right); } use_pattern(f) char f; { if (f == 2) /* white */ return(0); else if (f == 3) /* black */ return(15); else { /* something else */ load_texture(f); return(3); } } use_line(n) char n; { if (n < 1 || n > 5) return(1); else return(line_table[n]); } load_texture(n) int n; { FILE *oldfp; if (n < 1 || n > 36) return; if (texture_table[n] == 0) { oldfp = impout(fontfp); /* send textures out to font file */ imP_bgly(0,TEXTURE_FAMILY,n,32,32,0,32,32,pattern[n]); impout(oldfp); texture_table[n] = 1; } imP_set_texture(TEXTURE_FAMILY,n); } reset_textures() /* mark all textures as not yet loaded */ { int i; for (i = 1; i <= 36; i++) texture_table[i] = 0; } dopage(pv, ph) struct lcoord *pv, *ph; { struct page *pp; int r,c; char s[20]; r = pv->i / MAC_V_SIZE; c = ph->i / MAC_H_SIZE; pp = &pagetbl[r][c]; if (r > MAC_V_PAGES || c > MAC_H_PAGES) return(0); else if (pp->flag == 0) return(0); else { if (pp->fp == NULL) { strcpy(s,mktemp(TEMP_PREFIX)); sprintf(pp->name,"%s.%01d%02d",s,r+1,c+1); pp->fp = fopen(pp->name,"w+"); pp->font = -1; /* force a imP_set_family() */ } impout(pp->fp); #ifndef NO_TEXT if (page_ptr != NULL) page_ptr->font = ImFamily; /* font for last page */ ImFamily = pp->font; /* font in use on new page */ #endif page_ptr = pp; /* points to current page */ cur_page.bottom = (cur_page.top= r * MAC_V_SIZE) + MAC_V_SIZE; cur_page.right = (cur_page.left= c * MAC_H_SIZE) + MAC_H_SIZE; return(1); } } /* This routine parses a page select specification of the form n-m where n is the first one to do and m is the last one to do. If either is missing, the value in n or m is left unchanged. If only one number is given, m and n will both be set equal to it. The parameter s is a pointer to the string and the function returns an updated pointer to the next character in the string after doing the parsing. */ char * getpages(s,n,m) char *s; int *n,*m; { int x; if (isdigit(*s)) { x = 0; while (isdigit(*s)) x = x * 10 + (*s++ - '0'); *n = x; } if (*s == '-') { if (isdigit(*++s)) { x = 0; while (isdigit(*s)) x = x * 10 + (*s++ - '0'); *m = x; } } else *m = *n; return(s); } /* This routine take the endpoint of the vector (*h, *v), its angle (t), and the line size (n) as input and fills the ha[] and va[] arrays with the three points needed to draw the arrowhead. It also modifies the endpoint location to move it inside the arrowhead. If this isn't done, the line will show around the arrow tip when using wide line sizes. */ make_arrow(h,v,t,n,ha,va) int *h, *v, n, ha[3], va[3]; double t; { double tp, tm ,r; r = ar_radius[n]; tp = t + ar_angle; tm = t - ar_angle; ha[0] = *h; /* make triangle for the arrow */ va[0] = *v; ha[1] = *h - r * cos(tm); va[1] = *v - r * sin(tm); ha[2] = *h - r * cos(tp); va[2] = *v - r * sin(tp); *h -= r * cos(t) * 0.5; /* move endpoint of vector back */ *v -= r * sin(t) * 0.5; /* away from tip of arrowhead */ } /* Create a filename for storing output for later inclusion with a dvi file */ makename(s1, s2) char *s1, *s2; { int n; char *p; p = s1; while (*p != '\0') { /* get rid of leading path name */ if (*p == '/') s1 = p+1; p++; } p = s1 + strlen(s1); /* point to null byte */ while (p > s1 && *--p != '.') /* back up looking for a . */ ; if (*p == '.' && strcmp(p, MAC_EXT) == 0) { n = p - s1; strncpy(s2, s1, n); s2[n] = '\0'; strcat(s2, TEX_EXT); } else { /* wrong or no extension so just add to end */ strcpy(s2, s1); strcat(s2, TEX_EXT); } } SHAR_EOF fi # end of overwriting check if test -f 'drawimp.man' then echo shar: will not over-write existing file "'drawimp.man'" else cat << \SHAR_EOF > 'drawimp.man' .TH DRAWIMP LOCAL "17 December 1985" .SH NAME drawimp \- convert MacDraw files to imPRESS format .SH SYNOPSIS .B drawimp [ options ] files .SH DESCRIPTION .vs -1p .I Drawimp converts the named MacDraw format files into imPRESS format for printing on an Imagen laser printer. .I Drawimp can be run in two modes. In the normal mode, imPRESS output from all the files listed on the command line will be written to the standard output. The imPRESS output contains the required headers and should be ready to print with no changes or additions. If .I drawimp is run with the .B \-t option, the program will create a separate output file for each input file. These output files will be in the proper format for merging with .I LaTeX output files for putting figures in documents. .PP The following options may be used .TP .B \-d Write debugging information to standard error. This consists of a list of the objects in the file, their location in MacDraw coordinates, and various attributes. .TP .BI \-p list Print only pages whose row and column numbers appear in a comma-separated .I list of paired row and column numbers in the form .I r:c, or paired rows and columns ranges in the form .I r1-r2:c1-c2. A range .IB r1 \- r2 means rows .I r1 through .I r2 inclusive; an initial .I \-r2 means rows 1 though .I r2 inclusive; and a final .IR r1 \- means from .I r1 to the last row. The same applies for the column specifications. .TP .B \-t Write imPRESS output to separate output files (one for each input file) without a header or trailing .I Endpage or .I Eof bytes. This option should be used if the output is intended for combining with other imPRESS data. In this mode, the page select option .B \-p is not allowed and only the upper left page of the drawing will be processed. The picture on this page be shifted on the coordinate system as if it had been in the upper left corner of the 8x10 page. If the name of an input file ends with .I \.data then the output file will be the same name as the input file with the .I \.data replaced by .I \.imp. Otherwise, the output file name will be the input file name with .I \.imp appended to it. .TP .BI \-R resolution Sets assumed printer resolution (in dots per inch). .SH FILES /tmp/McD*.\c .I rcc - temporary file for imPRESS data for the page at row .I r and column .I cc .SH BUGS Multiple page objects, PICT objects (things from MacPaint via the clipboard), and smoothed polygons are not currently supported. .PP All MacDraw files containing pictures to be included in a single .I LaTeX document must be processed by .I drawimp (with the .B \-t option) at the same time. If this is not done, the fonts used for text in the pictures will get mixed up. .PP The program ignores any information in the file about paper size or orientation. It assumes a paper size of 8x10 inches and will ignore any object that crosses an 8x10 inch page boundary, Because of this, it is best to use that paper size when creating the drawing to better see how the output will be broken up. .PP The program is designed to convert MacDraw files which are in the format produced by \*(lqMacDraw Version 1.7 3/18/85\*(rq and may not be compatible with files produced by other versions of MacDraw. .SH AUTHOR Allan G. Weber (Weber%Brand@USC-ECL.ARPA), University of Southern California, Signal and Image Processing Institute SHAR_EOF fi # end of overwriting check if test -f 'error.c' then echo shar: will not over-write existing file "'error.c'" else cat << \SHAR_EOF > 'error.c' #ifndef lint static char rcsid[] = "$Header: error.c,v 1.1 84/05/20 23:11:37 chris Exp $"; #endif /* Error message routine */ #include <stdio.h> #ifdef lint /* VARARGS */ /* ARGSUSED */ error (quit, e, fmt) int quit, e; char *fmt; { } #else lint extern char *ProgName; extern char *sys_errlist[]; extern int sys_nerr; #ifdef pyr /* pyramid hacks */ #include <varargs.h> #endif pyr /* Print an error message with an optional system error number and optionally quit */ error (quit, e, fmt, arg) int quit, e; char *fmt; { #ifdef pyr va_buf _va; va_list l; fprintf (stderr, "%s: ", ProgName); _vastart (l = (va_list)_va, &arg); _doprnt (fmt, l, stderr); #else pyr fprintf (stderr, "%s: ", ProgName); _doprnt (fmt, &arg, stderr); #endif pyr if (e) { register char *s = e < sys_nerr ? sys_errlist[e] : "Unknown error"; fprintf (stderr, ": %s", s); } putc ('\n', stderr); fflush (stderr); /* just in case */ if (quit) exit (quit); } #endif lint SHAR_EOF fi # end of overwriting check if test -f 'impress.c' then echo shar: will not over-write existing file "'impress.c'" else cat << \SHAR_EOF > 'impress.c' /* This file contains functions for outputting Impress codes to a file. Not all functions have been implemented, only those needed so far. */ #include <stdio.h> /* The following #defines are copied from the Imagen supplied file "imPcodes.h" */ #define imP_SP 128 #define imP_SP1 129 #define imP_OLD_MMOVE 130 #define imP_MPLUS 131 #define imP_MMINUS 132 #define imP_MMOVE 133 #define imP_SMOVE 134 #define imP_SET_ABS_H 135 #define imP_SET_REL_H 136 #define imP_SET_ABS_V 137 #define imP_SET_REL_V 138 #define imP_SRULE 192 #define imP_BRULE 193 #define imP_SET_HPOS 195 #define imP_SET_VPOS 196 #define imP_CRLF 197 #define imP_SGLY 198 #define imP_BGLY 199 #define imP_DELG 200 #define imP_DELC 201 #define imP_DELF 202 #define imP_MAKE_TEXTURE 203 #define imP_SET_HV_SYSTEM 205 #define imP_SET_ADV_DIRS 206 #define imP_SET_FAMILY 207 #define imP_SET_IL 208 #define imP_SET_BOL 209 #define imP_SET_SP 210 #define imP_PUSH 211 #define imP_POP 212 #define imP_PAGE 213 #define imP_SET_PUSH_MASK 214 #define imP_ENDPAGE 219 #define imP_CREATE_FAMILY_TABLE 221 #define imP_CREATE_MAP 222 #define imP_SET_PUM 225 #define imP_CIRC_ARC 150 #define imP_ELLIPSE_ARC 151 #define imP_CIRC_SEGM 160 #define imP_CREATE_PATH 230 #define imP_SET_TEXTURE 231 #define imP_SET_PEN 232 #define imP_FILL_PATH 233 #define imP_DRAW_PATH 234 #define imP_BITMAP 235 #define imP_SET_MAGN 236 #define imP_FORCE_GLY_DEL 240 #define imP_DEFINE_MACRO 242 #define imP_EXEC_MACRO 243 #define imP_DEFINE_FILE 244 #define imP_EXEC_FILE 245 #define imP_NOOP 254 #define imP_EOF 255 static FILE *impfp; FILE *impout(fp) FILE *fp; { FILE *oldfp; oldfp = impfp; impfp = fp; return(oldfp); } static outb(x) int x; { putc(x & 0xff, impfp); } static outw(x) int x; { outb(x >> 8); outb(x); } static outs(s,n) char *s; int n; { fwrite(s,1,n,impfp); } /****************************************************************************/ imP_bgly(rotation,family,member,adv_wid,width,left_off,height,top_off,mask) int rotation,family,member,adv_wid,width,left_off,height,top_off; char *mask; { int n; outb(imP_BGLY); outw(((rotation&0x03) << 14) + ((family&0x7f) << 7) + (member&0x7f)); outw(adv_wid); outw(width); outw(left_off); outw(height); outw(top_off); if (mask != NULL) { n = height * ((width + 7) / 8); while (n--) outb(*mask++); } } imP_create_path(vertex_count, h, v) int vertex_count, *h, *v; { outb(imP_CREATE_PATH); outw(vertex_count); while (vertex_count--) { outw(*h++); outw(*v++); } } imP_crlf() { outb(imP_CRLF); } imP_draw_path(operation_type) int operation_type; { outb(imP_DRAW_PATH); outb(operation_type); } imP_ellipse_arc(radiusa,radiusb,alphaoff,alpha0,alpha1) int radiusa,radiusb,alphaoff,alpha0,alpha1; { outb(imP_ELLIPSE_ARC); outw(radiusa); outw(radiusb); outw(alphaoff); outw(alpha0); outw(alpha1); } imP_endpage() { outb(imP_ENDPAGE); } imP_eof() { outb(imP_EOF); } imP_fill_path(operation_type) int operation_type; { outb(imP_FILL_PATH); outb(operation_type); } imP_member(code) int code; { outb(code); } imP_mminus() { outb(imP_MMINUS); } imP_mmove(deltam) { outb(imP_MMOVE); outw(deltam); } imP_mplus() { outb(imP_MPLUS); } imP_noop() { outb(imP_NOOP); } imP_set_abs_h(new_h) int new_h; { outb(imP_SET_ABS_H); outw(new_h); } imP_set_abs_v(new_v) int new_v; { outb(imP_SET_ABS_V); outw(new_v); } imP_set_bol(line_begin) int line_begin; { outb(imP_SET_BOL); outw(line_begin); } imP_set_family(family) int family; { outb(imP_SET_FAMILY); outb(family); } imP_set_hv_system(origin,axes,orientation) int origin, axes, orientation; { int x; x = ((origin & 3) << 5) + ((axes & 3) << 3) + (orientation & 1); outb(imP_SET_HV_SYSTEM); outb(x); } imP_set_il(inter_line) int inter_line; { outb(imP_SET_IL); outw(inter_line); } imP_page() { outb(imP_PAGE); } imP_set_pen(diameter) int diameter; { outb(imP_SET_PEN); outb(diameter); } imP_set_pum(mode) int mode; { outb(imP_SET_PUM); outb(mode & 1); } imP_set_rel_h(delta_h) int delta_h; { outb(imP_SET_REL_H); outw(delta_h); } imP_set_rel_v(delta_v) int delta_v; { outb(imP_SET_REL_V); outw(delta_v); } imP_set_texture(family,member) int family, member; { outb(imP_SET_TEXTURE); outw(((family & 0x7f) << 7) + (member & 0x7f)); } imP_set_sp(space_size) int space_size; { outb(imP_SET_SP); outw(space_size); } imP_smove(deltas) int deltas; { outb(imP_SMOVE); outw(deltas); } imP_sp() { outb(imP_SP); } SHAR_EOF fi # end of overwriting check if test -f 'machint.s' then echo shar: will not over-write existing file "'machint.s'" else cat << \SHAR_EOF > 'machint.s' rcsid: .asciz "$Header: /ful/chris/ctex/lib/RCS/machint.s,v 1.1 84/05/26 01:53:01 chris Exp $" # machint (addr, count) # char *addr; int count; # # Convert "count" 4-byte PXL-style integers at address "addr" # to and from machine integers. (Note that calling machint # twice is effectively a no-op.) .align 2 .globl _machint _machint: .word 0 movl 4(ap),r1 # r1 = addr ashl $2,8(ap),r2 addl2 r1,r2 # r2 = &addr[count] 1: cmpl r1,r2 # is addr >= end? blss 2f ret # return if r1 >= r2 2: movl (r1)+,r0 # r0 = *r1++ movb r0,-1(r1) # byte 0 to byte 3 ashl $-8,r0,r0 # r0 >>= 8 movb r0,-2(r1) # byte 1 to byte 2 ashl $-8,r0,r0 # etc movb r0,-3(r1) ashl $-8,r0,r0 movb r0,-4(r1) brb 1b # and repeat SHAR_EOF fi # end of overwriting check if test -f 'pxl.c' then echo shar: will not over-write existing file "'pxl.c'" else cat << \SHAR_EOF > 'pxl.c' #ifndef lint static char rcsid[] = "$Header: pxl.c,v 1.9 85/10/15 18:19:05 chris Exp $"; #endif /* Routines for manipulating PXL files---Vax version */ /* The functions DMagFactor, GenPXLFileName, and ReadPXLFile could go in separate files, but it's likely that any program that uses any one function uses all three. */ #include "pxl.h" #include <errno.h> #include <sys/types.h> #include <sys/stat.h> extern int errno; char *malloc (), *sprintf (), *getenv (); long lseek (); /* Convert a magnification factor to floating point. This is used in conjunction with the FONT_SLOP stuff to try to get the file names right, and may also be used by DVI reading programs to get slightly more accurate values for (mag/1000.0). */ double DMagFactor (mag) int mag; { if (mag == 1095) return 1.095445; /* stephalf */ if (mag == 1315) return 1.314534; /* stepihalf */ if (mag == 2074) return 2.0736; /* stepiv */ if (mag == 2488) return 2.48832; /* stepv */ if (mag == 2986) return 2.985984; /* stepiv */ /* remaining mags have been ok */ return (double) mag / 1000.; } /* Generate the name of a PXL font file, given the partial name `nm', at the magnification `magfactor', with design size `designsize', a global mag factor of `globalmag' (default 1000), and a fontname path of `path' (default PXLPATH). Paths are defined as colon- separated strings (eg, "/usr/foo:/usr/bar"). Font directories either contain all the fonts directly, or else each font is in its own subdirectory. For example, amti10.* would be found in the `amti10' directory; ambx7.* in `ambx7', and so forth. The latter method is used iff there is a file in the main directory called `SUBDIR'. */ char * GenPXLFileName (nm, magfactor, designsize, globalmag, path) char *nm; int magfactor, designsize, globalmag; char *path; { double dmag; register char *s, *p; register int mag, /* expected magnification */ slop; /* current slop index */ char *slash; /* path name separator */ char *fmt; /* either oldfmt or newfmt */ char pbuf[256]; /* expansion area for path components */ static char oldfmt[] = "%s%s%s%0.0s.%dpxl"; static char newfmt[] = "%s%s%s/%s.%dpxl"; /* the formats for generating names */ /* arguments are path, /, nm, nm, sz */ static char rv[256]; /* the generated name (and other uses) */ if (globalmag == 0) globalmag = 1000; mag = (int) ((double) magfactor / (double) designsize * 1000.0 + .5); dmag = DMagFactor (mag); mag = (int) (DMagFactor (globalmag) * 1000.0 * dmag + .5); if (mag > 9999) mag = 9999; else if (mag < 0) mag = 0; /* For some reason I used to look for slashes in `nm', and suppress path expansion if there were any. This seems awfully bogus, so I've changed it to suppress path expansion iff the font name starts with '/'. Also, we no longer choke on font names with percent signs in them. */ if (*nm == '/') slash = s = ""; else { s = path; if (s == 0 || *s == 0) s = PXLPATH; slash = "/"; } /* Tread the path in s, trying for the file, and testing "nearby" names */ while (s) { p = pbuf; while (*s) { if ((*p = *s++) == ':') break; p++; } *p = 0; if (*s == 0) s = 0; /* choose new format if SUBDIR file exists, old format otherwise */ /* but always use old format for names starting with / */ if (*nm == '/') fmt = oldfmt; else { (void) sprintf (rv, "%s%sSUBDIR", pbuf, slash); fmt = access (rv, 0) == 0 ? newfmt : oldfmt; } for (slop = 0; slop < FONT_SLOP; slop++) { (void) sprintf (rv, fmt, pbuf, slash, nm, nm, mag + slop); if (access (rv, 4) == 0) return rv; if (slop) { (void) sprintf (rv, fmt, pbuf, slash, nm, nm, mag - slop); if (access (rv, 4) == 0) return rv; } } } /* Not found - give up and return expected name anyway */ /* Someday, we may actually generate the PXL (or GF) file here. */ (void) sprintf (rv, "%s.%dpxl", nm, mag);/* note: no path! */ return rv; } /* Read in a PXL font file, performing all the necessary byte swapping. Return a pointer to a struct pxltail. If 'getrast' is true, get the raster too. */ #define TAILSIZE (517 * 4) /* size of pxl tail info */ struct pxltail * ReadPXLFile (nm, getrast) char *nm; int getrast; { register char *p; register int f; struct stat stat; #define px ((struct pxltail *) p) /* First open the file, and read the pxltail part */ if ((f = open (nm, 0)) < 0) return 0; (void) fstat (f, &stat); /* There should be 4n bytes, with an absolute minimum of TAILSIZE + 4 (+4 for the initial PXLID) */ if (stat.st_size & 3 || stat.st_size < (TAILSIZE + 4)) { errno = EINVAL; return 0; } (void) lseek (f, (long) (-TAILSIZE), 2); p = malloc ((unsigned) TAILSIZE); if (p == 0) return 0; if (read (f, p, TAILSIZE) != TAILSIZE) { int saverr = errno; free (p); errno = saverr; return 0; } /* Next, byte swap, since PXL file byte order is the opposite of VAX byte order */ machint ((int *) p, TAILSIZE / 4); /* Finally, check the PXLID part, and if desired, read the character rasters */ if (px -> px_pxlid != PXLID) error (0, 0, "Warning: strange PXL id (%d) in \"%s\"", px -> px_pxlid, nm); if (getrast) { int rastsize = stat.st_size - (TAILSIZE + 4); if (ReadRasters (px -> px_info, f, rastsize, nm)) { int saverr = errno; free (p); errno = saverr; return 0; } } (void) close (f); return px; #undef px } /* Round n up to the nearest multiple of r (r must be a power of two) */ #define ROUND(n,r) (((n) + ((r) - 1)) & ~((r) - 1)) /* Read the raster info from a PXL file. To avoid system call overhead, we read the entire thing into core, then break up the glyphs for the chinfo array. NOTE: if malloc fails, we don't try very hard to clean up---most programs will die anyway if they fail to find a font. The reason for breaking up the characters in the first place is so that the storage allocated to any particular glyph may be freed. The rotation code uses this to get rid of bits it no longer needs. If they are not released, it is possible to run out of core when using many fonts. */ static ReadRasters (ch, fd, sz, nm) register struct chinfo *ch; int fd, sz; char *nm; { register int i; if (i = sz) { register char *p, /* glyph storage area */ *rp; /* raster pointer */ register int rs; /* raster size, in bytes */ /* First, read all the glyph bits */ if ((p = malloc ((unsigned) i)) == 0) return -1; (void) lseek (fd, 4L, 0); if (read (fd, p, i) != i) return -1; /* Next, break them up into the 128 characters */ p -= 4; /* to account for the initial PXLID */ for (i = 128; --i >= 0; ch++) { if (ch -> ch_rastoff) { rs = ch -> ch_height * (ROUND (ch -> ch_width, 32) >> 3); if ((rp = malloc ((unsigned) rs)) == 0) return -1; /* the << 2 accounts for the fact that ch_rastoff is for 32 bit things, and we are using 8 bits (32/8 = 4 = 1<<2) */ bcopy (&p[ch -> ch_rastoff << 2], rp, rs); ch -> ch_raster = rp; } } /* Finally, release the temporary copy */ free (p + 4); } else { /* should be 'totally white' */ for (i = 128; --i >= 0; ch++) if (ch -> ch_rastoff || ch -> ch_height || ch -> ch_width || ch -> ch_yoffset || ch -> ch_xoffset) error (1, 0, "bad pxl file \"%s\"...help!", nm); } return 0; } SHAR_EOF fi # end of overwriting check # End of shell archive exit 0