/* Amiga bitmapped font builder. File "mkbmap.c". * (C) Adrian Aylward 1991 * * You may freely copy, use, and modify this file. * * This program prints builds an Amiga format bitmapped screen font file * from the corresponding PostScript font, using post.library. It is totally * Amiga specific. * * The program was tested using Lattice C V5.05. It has various Lattice * dependencies. * * This is version 1.0. */ # include # include # include # include # include # include # include # include # include # include "postlib.h" # undef POSTVERNO # define POSTVERNO 15 /* We need post.library version 1.5+ */ /* The following definitions appear to be missing from the Lattice headers */ # ifdef LATTICE extern struct FontContentsHeader *NewFontContents(BPTR lock, char *name); extern void DisposeFontContents(struct FontContentsHeader *fc); # pragma libcall DiskfontBase NewFontContents 2a 9802 ; d0 = (a0, a1) # pragma libcall DiskfontBase DisposeFontContents 30 901 ; (a1) # endif /* Assembler routines */ extern void insertftrap(void); extern void deleteftrap(void); /* Object module hunks */ # define Hunk_Header 0x3F3 # define Hunk_Code 0x3E9 # define Hunk_Reloc32 0x3EC # define Hunk_End 0x3F2 # define MOVFFD0RTS 0x70FF4E75 /* External data (initialised to zero) */ char *argbmapfile, *argfontname, *argpointsizes; char *argstartupfile, *argencodingfile; int optfontencoding, optnew; int optmonospaced, optbold, optitalic, opttrace; int optden, optxden, optyden, optbaseline, optwidth; int pointc, pointn, pointv[100]; int retcode; int arec; struct library *PSbase; struct PSparm parm; APTR functab[10]; int ftrapset; int pointsize; char namebuf[100 + 5]; char psstring[200]; int pserror; int lochar, hichar; int baseline, nomwidth, nomcount; int llx[256], lly[256], urx[256], ury[256]; int cposx, cposy; void *fontmem; int baselen; int maxfontlen, maxcharlen, maxmodulo, maxwidth; int actfontlen, actcharlen, actmodulo, actwidth; int hunklen, hunknum, *hunkptr; BPTR fdlock, cdlock, newfh; struct FontContentsHeader *fcheader; struct DiskFontHeader *dfheader; char *chardata; short *charloc, *charspace, *charkern; /* Routines */ extern int strtoint(char **sp, int *ip); extern char *buildfnumname(char *nbuf, char *name, int num); extern char *buildfdirname(char *nbuf, char *name, int type); extern void pstrace(char *format, ...); extern void pssintf(char *format, ...); extern void __saveds setbbox(int ch, int lx, int ly, int rx, int uy); extern void __saveds setcpos(int cpx, int cpy); /* Main program */ void main(int argc, char **argv) { char *s, *t; int *ip, i, l, ch; int y1, y2, z1, z2, zz, ww; /* Parse arguments. No workbench startup */ optxden = optyden = 75; optbaseline = optwidth = -1; lochar = 32; hichar = 255; if (argc == 0) goto tidyexit; argv++; argc--; if (argc == 0 || (argc == 1 && strcmp(*argv, "?") == 0)) goto query; while (argc) { s = *argv; if (*s != '-') break; argv++; argc--; if (strcmp(s, "--") == 0) break; s++; for (;;) { ch = *s++; if (ch == 0) break; switch (ch) { case 'S': case 's': if (argc == 0) goto badargs; argstartupfile = *argv++; argc--; case 'E': case 'e': if (argc == 0) goto badargs; argencodingfile = *argv++; argc--; case 'F': case 'f': optfontencoding = 1; continue; case 'N': case 'n': optnew = 1; continue; case 'D': case 'd': ip = &optden; break; case 'X': case 'x': ip = &optxden; break; case 'Y': case 'y': ip = &optyden; break; case 'Z': case 'z': ip = &optbaseline; break; case 'L': case 'l': ip = &lochar; break; case 'W': case 'w': ip = &optwidth; break; case 'H': case 'h': ip = &hichar; break; case 'M': case 'm': optmonospaced = 1; continue; case 'B': case 'b': optbold = 1; continue; case 'I': case 'i': optitalic = 1; continue; case 'T': case 't': opttrace = 1; continue; default: fprintf(stderr, "mkbmap: unknown option \"-%c\"", ch); goto badusage; } if (!strtoint(&s, ip)) goto badargs; if (ip == &optden) optxden = optyden = optden; } if (*s == '-' && *(s + 1) == 0) break; } if (lochar > hichar || hichar > 255) { fprintf(stderr, "mkbmap: LoChar/HiChar out of range " "(0 <= Lo <= Hi <= 255)\n"); goto errorexit; } if (argc != 1 && argc != 3) goto badargs; argbmapfile = argv[0]; if (argc == 3) { argfontname = argv[1]; argpointsizes = argv[2]; s = argpointsizes; while (*s) { i = 0; for (;;) { ch = *s; if (ch == 0) break; s++; if (ch == ',') break; if (ch >= '0' && ch <= '9') i = i * 10 + (ch - '0'); else goto badargs; } if (i != 0) { if (i < 5 || i > 500) { fprintf(stderr, "mkbmap: point size %d out of range " "(5 - 500)\n", pointsize); goto errorexit; } if (pointc == 100) goto badargs; pointv[pointc++] = i; } } } if (pointc == 0) goto newfont; if (argencodingfile == NULL) argencodingfile = "PSFonts:encoding.ps"; if (argstartupfile == NULL) argstartupfile = "PSFonts:init.ps"; /* Initialise the PostScript library */ pstrace("%% Opening PostScript library\n"); PSbase = OpenLibrary("post.library", POSTVERNO); if (PSbase == NULL) { fprintf(stderr, "mkbmap: can't open post.library (V15+)\n"); goto errorexit; } pstrace("%% Initialising PostScript activation\n"); parm.page.buf[0] = namebuf; parm.page.len = 100; parm.page.depth = 1; parm.page.xoff = 0; parm.page.yoff = 0; parm.page.xbytes = 10; parm.page.xsize = 80; parm.page.ysize = 10; parm.page.ybase = 0; parm.page.yheight = 10; parm.page.xden = 72; parm.page.yden = 72; parm.page.ydir = -1; parm.memvlen = 20000; parm.memflen = 10000; parm.memllen = defmemllen; parm.memhlen = minmemhlen; parm.infh = Input(); parm.outfh = Output(); parm.errfh = Output(); parm.funcmax = 2; functab[0] = (APTR) setbbox; functab[1] = (APTR) setcpos; parm.functab = functab; insertftrap(); ftrapset = 1; arec = PScreateact(&parm); if (arec == 0) { fprintf(stderr, "mkbmap: post.library can't get memory\n"); goto errorexit; } if ((unsigned) arec <= errmax) { pserror = arec; arec = 0; goto pserror; } /* Load the startup file */ pstrace("%% Loading startup file\n"); pssintf("(%.100s) run clear\n", argstartupfile); /* Load the encoding file */ if (optfontencoding == 0) { pstrace("% Loading encoding file\n"); pssintf("/encoding StandardEncoding 256 array copy def\n"); pssintf("[ (%.100s) run ] aload length 2 idiv\n", argencodingfile); pssintf("{ encoding 3 1 roll put } repeat\n"); } /* Load the font. Make sure we don't get a substitute */ pstrace("%% Loading font\n"); pssintf("/fontname /%.100s def\n", argfontname); pssintf("fontname findfont pop\n"); pssintf("/font fontname .findfont def\n"); /* Encode the font */ pstrace("%% Encoding font\n"); pssintf("/newfont font maxlength dict def\n"); pssintf("font\n" "{ exch dup /FID ne " "{ exch newfont 3 1 roll put } { pop pop } ifelse }\n" "forall\n"); if (optfontencoding == 0) pssintf("newfont /Encoding encoding put\n"); pssintf("/_%.100s newfont definefont pop\n", argfontname); if (pserror != 0) goto pserror; pstrace("%% LoChar = %d; HiChar = %d\n", lochar, hichar); /* Determine the bounding boxes for all the characters */ pstrace("%% Generating bounding boxes\n"); pssintf("/cstr 1 string def\n"); pssintf("newfont 1000 scalefont setfont\n"); pssintf("%d 1 %d\n" "{ /i exch def cstr 0 i put null i\n" " 0 0 moveto cstr false charpath pathbbox newpath\n" " 4 { round cvi 4 1 roll } repeat\n" " 5 0 callextfunc\n" "} for\n", lochar, hichar); if (pserror != 0) goto pserror; /* Position the baseline, if we have not set it explicitly */ if (optbaseline == -1) { /* This is what we have room for */ zz = (1000 * 72) / optyden; /* Calculate the lower and upper limits of the whole character set */ z1 = z2 = 0; for (i = 0; i <= 255 ; i++) { if (lly[i] < z1) z1 = lly[i]; if (ury[i] > z2) z2 = ury[i]; } if (z2 == z1) { fprintf(stderr, "mkbmap: all characters in the font are null\n"); goto errorexit; } /* If we have room for everything, or the font has a non-standard * character set, set the baseline in proportion to the relative * sizes of the ascenders and descenders */ optbaseline = (1000 * (-z1) + (z2 - z1) / 2) / (z2 - z1); /* Otherwise, for fonts with standard character sets, calculate the * limits of the alphabet. If we have room for that then leave just * enough room for the descenders, or else set the baseline * proportionately */ if (z2 - z1 > zz && optfontencoding == 0) { y1 = y2 = 0; for (i = 'A'; i <= 'Z' ; i++) { if (lly[i] < y1) y1 = lly[i]; if (ury[i] > y2) y2 = ury[i]; } for (i = 'a'; i <= 'z' ; i++) { if (lly[i] < y1) y1 = lly[i]; if (ury[i] > y2) y2 = ury[i]; } if (y2 - y1 <= zz) optbaseline = (1000 * (-y1) + zz / 2) / zz; else optbaseline = (1000 * (-y1) + (y2 - y1) / 2) / (y2 - y1); } pstrace("%% Baseline set at %d/1000 of the pixel height\n", optbaseline); } /* Validate the font file name and create the font subdirectory */ if (buildfdirname(namebuf, argbmapfile, 0) == NULL) { fprintf(stderr, "mkbmap: bmap file has no directory path\n"); goto errorexit; } if (optnew) { fdlock = CreateDir(namebuf); if (fdlock) { UnLock(fdlock); fdlock = 0; } } /* Loop through all the point sizes */ for (pointn = 0; pointn < pointc; pointn++) { if (SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto broken; pointsize = pointv[pointn]; pstrace("%% Point size %d\n", pointsize); baseline = (pointsize * optbaseline + 500) / 1000; if (baseline < 0) baseline = 0; if (baseline > pointsize - 1) baseline = pointsize - 1; /* Build the bitmapped font in memory. Estimate the maximum * possible width of the bitmap from the total widths of the * bounding boxes, allowing 2 extra pixels per character for * rounding and stem alignment. Calculate the mamimum font * length, allocate the memory, and initialise the headers */ baselen = 4 + sizeof (struct DiskFontHeader) + 8 * (hichar - lochar + 2); maxwidth = 0; for (ch = lochar; ch <= hichar ; ch++) maxwidth += ((urx[ch] - llx[ch]) * pointsize * optxden) / 72000 + 2; maxmodulo = ((maxwidth + 15) >> 3) & ~1; maxcharlen = maxmodulo * pointsize; maxfontlen = baselen + maxcharlen + 2 + 76; fontmem = AllocMem(maxfontlen, MEMF_PUBLIC|MEMF_CLEAR); if (fontmem == NULL) { fprintf(stderr, "mkbmap: can't get font memory\n"); goto errorexit; } hunkptr = fontmem; dfheader = (void *) &hunkptr[9]; charloc = (void *) &dfheader[1]; charspace = (void *) &charloc[(hichar - lochar + 2) * 2]; charkern = (void *) &charspace[hichar - lochar + 2]; chardata = (void *) &charkern[hichar - lochar + 2]; /* Set up the bitmap to render the characters */ pstrace("%% Rendering bitmaps\n"); parm.page.buf[0] = (char *) chardata; parm.page.len = maxcharlen; parm.page.depth = 1; parm.page.xoff = 0; parm.page.yoff = 0; parm.page.xbytes = maxmodulo; parm.page.xsize = maxwidth; parm.page.ysize = pointsize; parm.page.ybase = 0; parm.page.yheight = pointsize; PSsetdevice(arec, &parm.page); pssintf("initmatrix\n"); pssintf("/xscale %d %d mul 72 div def\n", pointsize, optxden); pssintf("/yscale %d %d mul 72 div def\n", pointsize, optyden); pssintf("newfont [ xscale 0 0 yscale 0 0 ] makefont setfont\n"); actwidth = 0; nomwidth = 0; nomcount = 0; /* Loop to render each character. We estimate the bounds of the * characters conservatively (hinting any shift them a little) and * trim the bitmap if possible. We clip on the left, so any part * of the character projecting to the left is truncated, and does * not overwrite the previous one. We erase the character cell so * it does not matter if the clipping of the right of the previous * character was not complete. We render the portiona above and * below the baseline separately, so they can be indepently scaled * to fit */ for (ch = lochar; ch <= hichar; ch++) { z1 = (llx[ch] * pointsize * optxden - 41000) / 72000; z2 = (urx[ch] * pointsize * optxden + 41000) / 72000; if (z1 < 0) z1 = 0; pssintf("cstr 0 %d put\n", ch); pssintf("%d %d moveto\n", actwidth, baseline); pssintf("gsave %d 0 rlineto 0 %d rlineto " "-%d 0 rlineto closepath clip\n", z2, -baseline, z2); pssintf("1 setgray fill 0 setgray\n"); pssintf("%d %d moveto ", actwidth - z1, baseline); y1 = ((-lly[ch]) * pointsize * optxden) / 72; y2 = baseline * 1000; if (y1 > y2) pssintf("1 %d %d div scale\n", y2, y1); pssintf("cstr show\n" "grestore\n"); pssintf("gsave %d 0 rlineto 0 %d rlineto " "-%d 0 rlineto closepath clip\n", z2, pointsize - baseline, z2); pssintf("1 setgray fill newpath 0 setgray\n"); pssintf("%d %d moveto ", actwidth - z1, baseline); y1 = (ury[ch] * pointsize * optxden) / 72; y2 = (pointsize - baseline) * 1000; if (y1 > y2) pssintf("1 %d %d div scale\n", y2, y1); pssintf("cstr show\n" "null currentpoint 2 { round cvi exch } repeat " "2 1 callextfunc\n" "grestore\n"); ww = cposx - actwidth; zz = z2 - z1; if (zz > ww) zz = ww; i = ch - lochar; charloc[i * 2] = actwidth; charloc[i * 2 + 1] = zz; charspace[i] = ww; charkern[i] = z1; actwidth += zz; if (lly[ch] != ury[ch]) { nomwidth += z1 + ww; nomcount++; } if (SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto broken; } if (pserror != 0) goto pserror; /* If we have not explicitly set the nominal character width, * calculate it as the average width of the non-null characters * we have generated */ if (optwidth == -1) { if (nomcount != 0) nomwidth = (nomwidth + nomcount / 2) / nomcount; } else nomwidth = (optwidth * pointsize * optxden + 36000) / 72000; /* We now know the actual width, so we can calculate the actual * modulo and file lengths. Then we must reformat the bitmap to * the new width */ if (actwidth > maxwidth) { fprintf(stderr, "mkbmap: width estimate exceeded\n"); goto errorexit; } actmodulo = ((actwidth + 15) >> 3) & ~1; actcharlen = actmodulo * pointsize; hunklen = baselen + actcharlen; if (hunklen & 2) hunklen += 2; hunknum = hunklen >> 2; actfontlen = hunklen + 76; i = 1; s = chardata + maxmodulo; t = chardata + actmodulo; while (i < pointsize) { l = actmodulo; while (l--) *t++ = *s++; i++; s += (maxmodulo - actmodulo); } /* Finish the bitmapped font. Write it out to the file */ buildfdirname(namebuf, argbmapfile, 2); hunkptr[0] = Hunk_Header; hunkptr[1] = 0; hunkptr[2] = 1; hunkptr[3] = 0; hunkptr[4] = 0; hunkptr[5] = hunknum; hunkptr[6] = Hunk_Code; hunkptr[7] = hunknum; hunkptr += 8; hunkptr[0] = MOVFFD0RTS; dfheader->dfh_DF.ln_Type = NT_FONT; dfheader->dfh_DF.ln_Name = (char *) 0x0000001A; dfheader->dfh_FileID = DFH_ID; strncpy((char *)&dfheader->dfh_Name, namebuf, MAXFONTNAME); dfheader->dfh_TF.tf_Message.mn_Node.ln_Type = NT_FONT; dfheader->dfh_TF.tf_Message.mn_Node.ln_Name = (char *) 0x0000001A; dfheader->dfh_TF.tf_Message.mn_Length = hunklen - 58; dfheader->dfh_TF.tf_YSize = pointsize; dfheader->dfh_TF.tf_Style = (optbold ? FSF_BOLD : 0) | (optitalic ? FSF_ITALIC : 0); dfheader->dfh_TF.tf_Flags = (optmonospaced ? 0 : FPF_PROPORTIONAL) | FPF_DESIGNED; dfheader->dfh_TF.tf_XSize = nomwidth; dfheader->dfh_TF.tf_Baseline = pointsize - baseline - 1; dfheader->dfh_TF.tf_BoldSmear = pointsize / 20 + 1; dfheader->dfh_TF.tf_LoChar = lochar; dfheader->dfh_TF.tf_HiChar = hichar; dfheader->dfh_TF.tf_CharData = (APTR) ((char *) chardata - (char *) hunkptr); dfheader->dfh_TF.tf_Modulo = actmodulo; dfheader->dfh_TF.tf_CharLoc = (APTR) ((char *) charloc - (char *) hunkptr); dfheader->dfh_TF.tf_CharSpace = (APTR) ((char *) charspace - (char *) hunkptr); dfheader->dfh_TF.tf_CharKern = (APTR) ((char *) charkern - (char *) hunkptr); hunkptr += hunknum; hunkptr[0] = Hunk_Reloc32; hunkptr[1] = 6; hunkptr[2] = 0; hunkptr[3] = 0x0000006A; hunkptr[4] = 0x00000066; hunkptr[5] = 0x00000062; hunkptr[6] = 0x0000005C; hunkptr[7] = 0x00000044; hunkptr[8] = 0x0000000E; hunkptr[9] = 0; hunkptr[10] = Hunk_End; pstrace("%% Writing bmap file\n"); if (buildfnumname(namebuf, argbmapfile, pointsize) == NULL) { fprintf(stderr, "mkbmap: bmap file name too long\n"); goto errorexit; } newfh = Open(namebuf, MODE_NEWFILE); if (newfh == NULL) { fprintf(stderr, "mkbmap: can't open bmap file %s\n", namebuf); goto errorexit; } i = Write(newfh, (UBYTE *) fontmem, actfontlen); Close(newfh); if (i == -1) { fprintf(stderr, "mkbmap: error writing bmap file %s\n", namebuf); goto errorexit; } } /* Update font contents file */ newfont: if (optnew) { pstrace("%% Updating font contents file\n"); buildfdirname(namebuf, argbmapfile, 1); fdlock = Lock(namebuf, SHARED_LOCK); if (fdlock == NULL) { fprintf(stderr, "mkbmap: can't lock font directory %s\n", namebuf); goto errorexit; } buildfdirname(namebuf, argbmapfile, 2); strcat(namebuf, ".font"); DiskfontBase = OpenLibrary("diskfont.library", 34); if (DiskfontBase) fcheader = NewFontContents(fdlock, namebuf); if (fcheader == NULL) { fprintf(stderr, "mkbmap: can't create new font contents %s\n", namebuf); goto errorexit; } if (fcheader->fch_NumEntries == 0) { fprintf(stderr, "mkbmap: font %s directory contains no fonts\n", namebuf); retcode = 10; goto tidyexit; } /* Swap to the font directory, update the file, and swap back */ cdlock = CurrentDir(fdlock); newfh = Open(namebuf, MODE_NEWFILE); if (newfh) { i = Write(newfh, (UBYTE *)fcheader, sizeof (struct FontContentsHeader) + sizeof (struct FontContents) * fcheader->fch_NumEntries); Close(newfh); } CurrentDir(cdlock); if (newfh == NULL) { fprintf(stderr, "mkbmap: can't open font contents file %s\n", namebuf); goto errorexit; } else if (i == -1) { fprintf(stderr, "mkbmap: error writing font contents file %s\n", namebuf); goto errorexit; } /* Tidy up */ DisposeFontContents(fcheader); fcheader = NULL; CloseLibrary(DiskfontBase); DiskfontBase = NULL; UnLock(fdlock); fdlock = NULL; } /* All done */ pstrace("%% All done\n"); goto tidyexit; /* Argument errors and usage query */ query: fprintf(stderr, "Bitmap font generator. MkBmap version 1.0\n" "Makes Amiga bitmapped fonts from PostScript fonts\n" "\n" " Usage:\n" "\n" " mkbmap -options bmapfile fontname nn,nn,...\n" "\n" " -s startupfile Startup file name\n" " -e encodingfile Encoding file name\n" " -f Font specific encoding\n" " -n Make new .font contents\n"); fprintf(stderr, " -dnnn Density: x and y (dpi)\n" " -xnnn Density: x (dpi)\n" " -ynnn Density: y (dpi)\n" " -znnn Baseline (1/1000)\n" " -wnnn Width (1/1000)\n" " -lnnn LoChar\n" " -hnnn Hichar\n" " -m Monospaced\n" " -b Bold\n" " -i Italic\n" " -t Trace (for debuggindg)\n" "\n" " For example:\n" "\n" " mkbmap -n fonts:Times/* Times-Roman 10,12,14\n"); goto tidyexit; badargs: fprintf(stderr, "mkbmap: arguments bad, or value missing"); badusage: retcode = 20; fprintf(stderr, ". Usage:\n" " mkbmap -options bmapfile fontname nn,nn,...\n"); goto tidyexit; /* PostScript library error */ pserror: fprintf(stderr, "mkbmap: post.library interpreter error\n"); goto errorexit; /* Tidy up and exit */ broken: fprintf(stderr, "mkbmap: *** Break\n"); retcode = 10; goto tidyexit; errorexit: retcode = 20; tidyexit: if (ftrapset) { deleteftrap(); ftrapset = 0; } if (arec) PSdeleteact(arec); if (PSbase) CloseLibrary(PSbase); if (fontmem) FreeMem(fontmem, maxfontlen); if (fcheader) DisposeFontContents(fcheader); if (DiskfontBase) CloseLibrary(DiskfontBase); if (fdlock) UnLock(fdlock); exit(retcode); } /* String to integer conversion; digits only, with error check */ int strtoint(char **sp, int *ip) { char *s = *sp; int i = 0; int ch; for (;;) { ch = *s; if (ch < '0' || ch > '9') break; i = i * 10 + (ch - '0'); s++; } if (s == *sp) return 0; else { *sp = s; *ip = i; return 1; } } /* Build the bitmap font file name. Copy it, replacing "*" by the point * size. Then scan it backwards replacing "?" by digits */ char *buildfnumname(char *nbuf, char *name, int num) { char number[10]; int numlen, i, j, k, ch; numlen = 0; while (num) { number[numlen++] = num % 10 + '0'; num /= 10; } i = j = 0; for (;;) { if (j > 100) return NULL; ch = name[i++]; if (ch == '*') { k = numlen; while (k--) nbuf[j++] = number[k]; } else nbuf[j++] = ch; if (ch == 0) break; } k = 0; while (--j) { if (nbuf[j] == '?') nbuf[j] = (k < numlen) ? number[k++] : '0'; } return nbuf; } /* Build the font file/directory name. We copy it, striping off the last * two components: * * type = 0: fontdir/fontname/* => fontdir/fontname * type = 1: fontdir/fontname/* => fontdir * type = 2: fontdir/fontname/* => fontname * * (or fontdir:fontname/* => ...) */ char *buildfdirname(char *nbuf, char *name, int type) { int i, j, k; i = strlen(name); for (;;) { if (i == 0) return NULL; i--; if (name[i] == ':') return NULL; if (name[i] == '/') break; } j = i; for (;;) { if (j == 0) return NULL; j--; if (name[j] == ':') { k = j = j + 1; break; } if (name[j] == '/') { k = j; j = j + 1; break; } } if (k == 0) return NULL; if (i >= 100) return NULL; if (type == 1) i = k; else if (type == 2) { name += j; i -= j; } memcpy(nbuf, name, i); nbuf[i] = 0; return nbuf; } /* Trace output */ void pstrace(char *format, ...) { va_list ap; if (pserror != 0) return; if (opttrace) { va_start(ap, format); vfprintf(stdout, format, ap); fflush(stdout); va_end(ap); } } /* Interpret postscript string */ void pssintf(char *format, ...) { va_list ap; if (pserror != 0) return; va_start(ap, format); if (opttrace) { vfprintf(stdout, format, ap); fflush(stdout); } vsprintf(psstring, format, ap); pserror = PSintstring(arec, psstring, -1, PSFLAGSTRING) va_end(ap); } /* Set character bounding box */ void __saveds setbbox(int ch, int lx, int ly, int rx, int uy) { llx[ch] = lx; lly[ch] = ly; urx[ch] = rx; ury[ch] = uy; } /* Set current point */ void __saveds setcpos(int cpx, int cpy) { cposx = cpx; cposy = cpy; } /* Signal an interrupt */ void __saveds sigint() { PSsignalint(arec, 1); } /* Signal a floating point error */ void __saveds sigfpe() { PSsignalfpe(arec); } /* Dummy stub routine */ void stub(void) { return; } /* Dummy check abort routine */ void chkabort(void) { return; } /* End of file "mkbmap.c" */